diff --git a/asai-examples/Syslib/Logger/Code/index.html b/asai-examples/Syslib/Logger/Code/index.html index 437fe2b..4e24583 100644 --- a/asai-examples/Syslib/Logger/Code/index.html +++ b/asai-examples/Syslib/Logger/Code/index.html @@ -1,2 +1,2 @@ -Code (asai-examples.Syslib.Logger.Code)

Module Logger.Code

type t =
  1. | FileError
  2. | ChiError
  3. | EmojiError
val default_severity : t -> Asai.Diagnostic.severity
val to_string : t -> string
\ No newline at end of file +Code (asai-examples.Syslib.Logger.Code)

Module Logger.Code

type t =
  1. | FileError
  2. | ChiError
  3. | EmojiError
val default_severity : t -> Asai.Diagnostic.severity
val to_string : t -> string
diff --git a/asai-examples/Syslib/Logger/index.html b/asai-examples/Syslib/Logger/index.html index abc0588..3786947 100644 --- a/asai-examples/Syslib/Logger/index.html +++ b/asai-examples/Syslib/Logger/index.html @@ -1,79 +1,79 @@ -Logger (asai-examples.Syslib.Logger)

Module Syslib.Logger

module Code : sig ... end
include sig ... end
val emit : - ?severity:Asai.Diagnostic.severity -> - ?loc:Asai.Span.t -> - ?backtrace:Asai.Diagnostic.backtrace -> - ?additional_messages:Asai.Diagnostic.message list -> +Logger (asai-examples.Syslib.Logger)

Module Syslib.Logger

module Code : sig ... end
include sig ... end
val emit : + ?severity:Asai.Diagnostic.severity -> + ?loc:Asai.Span.t -> + ?backtrace:Asai.Diagnostic.backtrace -> + ?additional_messages:Asai.Diagnostic.message list -> Code.t -> string -> unit
val emitf : - ?severity:Asai.Diagnostic.severity -> - ?loc:Asai.Span.t -> - ?backtrace:Asai.Diagnostic.backtrace -> - ?additional_messages:Asai.Diagnostic.message list -> + ?severity:Asai.Diagnostic.severity -> + ?loc:Asai.Span.t -> + ?backtrace:Asai.Diagnostic.backtrace -> + ?additional_messages:Asai.Diagnostic.message list -> Code.t -> ('a, Stdlib.Format.formatter, unit, unit) Stdlib.format4 -> 'a
val emit_diagnostic : Code.t Asai.Diagnostic.t -> unit
val fatal : - ?severity:Asai.Diagnostic.severity -> - ?loc:Asai.Span.t -> - ?backtrace:Asai.Diagnostic.backtrace -> - ?additional_messages:Asai.Diagnostic.message list -> + ?severity:Asai.Diagnostic.severity -> + ?loc:Asai.Span.t -> + ?backtrace:Asai.Diagnostic.backtrace -> + ?additional_messages:Asai.Diagnostic.message list -> Code.t -> string -> 'a
val fatalf : - ?severity:Asai.Diagnostic.severity -> - ?loc:Asai.Span.t -> - ?backtrace:Asai.Diagnostic.backtrace -> - ?additional_messages:Asai.Diagnostic.message list -> + ?severity:Asai.Diagnostic.severity -> + ?loc:Asai.Span.t -> + ?backtrace:Asai.Diagnostic.backtrace -> + ?additional_messages:Asai.Diagnostic.message list -> Code.t -> ('a, Stdlib.Format.formatter, unit, 'b) Stdlib.format4 -> - 'a
val fatal_diagnostic : Code.t Asai.Diagnostic.t -> 'a
val get_backtrace : unit -> Asai.Diagnostic.backtrace
val with_backtrace : Asai.Diagnostic.backtrace -> (unit -> 'a) -> 'a
val trace : ?loc:Asai.Span.t -> string -> (unit -> 'a) -> 'a
val tracef : - ?loc:Asai.Span.t -> + 'a
val fatal_diagnostic : Code.t Asai.Diagnostic.t -> 'a
val get_backtrace : unit -> Asai.Diagnostic.backtrace
val with_backtrace : Asai.Diagnostic.backtrace -> (unit -> 'a) -> 'a
val trace : ?loc:Asai.Span.t -> string -> (unit -> 'a) -> 'a
val tracef : + ?loc:Asai.Span.t -> ('a, Stdlib.Format.formatter, unit, (unit -> 'b) -> 'b) Stdlib.format4 -> - 'a
val trace_text : ?loc:Asai.Span.t -> Asai.Diagnostic.text -> (unit -> 'a) -> 'a
val trace_message : Asai.Diagnostic.message -> (unit -> 'a) -> 'a
val get_loc : unit -> Asai.Span.t option
val with_loc : Asai.Span.t option -> (unit -> 'a) -> 'a
val merge_loc : Asai.Span.t option -> (unit -> 'a) -> 'a
val diagnostic : - ?severity:Asai.Diagnostic.severity -> - ?loc:Asai.Span.t -> - ?backtrace:Asai.Diagnostic.backtrace -> - ?additional_messages:Asai.Diagnostic.message list -> + 'a
val trace_text : ?loc:Asai.Span.t -> Asai.Diagnostic.text -> (unit -> 'a) -> 'a
val trace_message : Asai.Diagnostic.message -> (unit -> 'a) -> 'a
val get_loc : unit -> Asai.Span.t option
val with_loc : Asai.Span.t option -> (unit -> 'a) -> 'a
val merge_loc : Asai.Span.t option -> (unit -> 'a) -> 'a
val diagnostic : + ?severity:Asai.Diagnostic.severity -> + ?loc:Asai.Span.t -> + ?backtrace:Asai.Diagnostic.backtrace -> + ?additional_messages:Asai.Diagnostic.message list -> Code.t -> string -> Code.t Asai.Diagnostic.t
val diagnosticf : - ?severity:Asai.Diagnostic.severity -> - ?loc:Asai.Span.t -> - ?backtrace:Asai.Diagnostic.backtrace -> - ?additional_messages:Asai.Diagnostic.message list -> + ?severity:Asai.Diagnostic.severity -> + ?loc:Asai.Span.t -> + ?backtrace:Asai.Diagnostic.backtrace -> + ?additional_messages:Asai.Diagnostic.message list -> Code.t -> ('a, Stdlib.Format.formatter, unit, Code.t Asai.Diagnostic.t) Stdlib.format4 -> 'a
val kdiagnosticf : - ?severity:Asai.Diagnostic.severity -> - ?loc:Asai.Span.t -> - ?backtrace:Asai.Diagnostic.backtrace -> - ?additional_messages:Asai.Diagnostic.message list -> + ?severity:Asai.Diagnostic.severity -> + ?loc:Asai.Span.t -> + ?backtrace:Asai.Diagnostic.backtrace -> + ?additional_messages:Asai.Diagnostic.message list -> (Code.t Asai.Diagnostic.t -> 'b) -> Code.t -> ('a, Stdlib.Format.formatter, unit, 'b) Stdlib.format4 -> 'a
val run : - ?init_loc:Asai.Span.t -> - ?init_backtrace:Asai.Diagnostic.backtrace -> - emit:(Code.t Asai.Diagnostic.t -> unit) -> - fatal:(Code.t Asai.Diagnostic.t -> 'a) -> + ?init_loc:Asai.Span.t -> + ?init_backtrace:Asai.Diagnostic.backtrace -> + emit:(Code.t Asai.Diagnostic.t -> unit) -> + fatal:(Code.t Asai.Diagnostic.t -> 'a) -> (unit -> 'a) -> 'a
val adopt : ('code Asai.Diagnostic.t -> Code.t Asai.Diagnostic.t) -> - (?init_loc:Asai.Span.t -> - ?init_backtrace:Asai.Diagnostic.backtrace -> - emit:('code Asai.Diagnostic.t -> unit) -> - fatal:('code Asai.Diagnostic.t -> 'a) -> + (?init_loc:Asai.Span.t -> + ?init_backtrace:Asai.Diagnostic.backtrace -> + emit:('code Asai.Diagnostic.t -> unit) -> + fatal:('code Asai.Diagnostic.t -> 'a) -> (unit -> 'a) -> 'a) -> (unit -> 'a) -> 'a
val try_with : - ?emit:(Code.t Asai.Diagnostic.t -> unit) -> - ?fatal:(Code.t Asai.Diagnostic.t -> 'a) -> + ?emit:(Code.t Asai.Diagnostic.t -> unit) -> + ?fatal:(Code.t Asai.Diagnostic.t -> 'a) -> (unit -> 'a) -> 'a
val register_printer : ([ `Emit of Code.t Asai.Diagnostic.t | `Fatal of Code.t Asai.Diagnostic.t | `Trace ] -> string option) -> - unit
\ No newline at end of file + unit
diff --git a/asai-examples/Syslib/Operations/index.html b/asai-examples/Syslib/Operations/index.html index 50a9309..9a3b13c 100644 --- a/asai-examples/Syslib/Operations/index.html +++ b/asai-examples/Syslib/Operations/index.html @@ -1,2 +1,2 @@ -Operations (asai-examples.Syslib.Operations)

Module Syslib.Operations

val operation1 : string -> unit
val operation2 : string -> unit
val operation3 : string -> 'a
\ No newline at end of file +Operations (asai-examples.Syslib.Operations)

Module Syslib.Operations

val operation1 : string -> unit
val operation2 : string -> unit
val operation3 : string -> 'a
diff --git a/asai-examples/Syslib/index.html b/asai-examples/Syslib/index.html index 48b7d99..a3c3f86 100644 --- a/asai-examples/Syslib/index.html +++ b/asai-examples/Syslib/index.html @@ -1,2 +1,2 @@ -Syslib (asai-examples.Syslib)

Module Syslib

module Logger : sig ... end
module Operations : sig ... end
\ No newline at end of file +Syslib (asai-examples.Syslib)

Module Syslib

module Logger : sig ... end
module Operations : sig ... end
diff --git a/asai-examples/index.html b/asai-examples/index.html index 5dd2198..b7d3bed 100644 --- a/asai-examples/index.html +++ b/asai-examples/index.html @@ -1,2 +1,2 @@ -index (asai-examples.index)

asai-examples index

Library asai-examples.syslib

The entry point of this library is the module: Syslib.

\ No newline at end of file +index (asai-examples.index)

asai-examples index

Library asai-examples.syslib

The entry point of this library is the module: Syslib.

diff --git a/asai/Asai/Diagnostic/index.html b/asai/Asai/Diagnostic/index.html index a200d21..514cef6 100644 --- a/asai/Asai/Diagnostic/index.html +++ b/asai/Asai/Diagnostic/index.html @@ -1,40 +1,40 @@ -Diagnostic (asai.Asai.Diagnostic)

Module Asai.Diagnostic

The definition of diagnostics and some utility functions.

Types

type severity =
  1. | Hint
  2. | Info
  3. | Warning
  4. | Error
  5. | Bug

The type of severity.

module type Code = sig ... end

The signature of message code. An implementer should specify the message code used in their library or application.

type text = Stdlib.Format.formatter -> unit

The type of text.

When we render a diagnostic, the layout engine of the rendering backend should be the one making layout choices. Therefore, we cannot pass already formatted strings. Instead, a text is defined to be a function that takes a formatter and uses it to render the content. The following two conditions must be satisfied:

  1. All string (and character) literals must be encoded using UTF-8.
  2. All string (and character) literals must not contain control characters (such as the newline character \n). It is okay to have break hints (such as @, and @ ) but not literal control characters. This means you should avoid pre-formatted strings, and if you must use them, use text to convert newline characters. Control characters include `U+0000-001F` (C0 controls), `U+007F` (backspace) and `U+0080-009F` (C1 controls). These characters are banned because they would mess up the cursor position.
type message = text Span.located

A message is a located text.

type backtrace = message Bwd.bwd

A backtrace is a (backward) list of messages.

type 'code t = {
  1. severity : severity;
    (*

    Severity of the diagnostic.

    *)
  2. code : 'code;
    (*

    The message code.

    *)
  3. message : message;
    (*

    The main message.

    *)
  4. backtrace : backtrace;
    (*

    The backtrace leading to this diagnostic.

    *)
  5. additional_messages : message list;
    (*

    Additional messages relevant to the main message that are not part of the backtrace.

    *)
}

The type of diagnostics.

Constructing Messages

val text : string -> text

text str converts the string str into a text, converting each '\n' into a call to Format.pp_force_newline.

val textf : ('a, Stdlib.Format.formatter, unit, text) Stdlib.format4 -> 'a

textf format ... constructs a text. It is an alias of Format.dprintf. Note that there should not be any literal control characters (e.g., literal newline characters).

val ktextf : +Diagnostic (asai.Asai.Diagnostic)

Module Asai.Diagnostic

The definition of diagnostics and some utility functions.

Types

type severity =
  1. | Hint
  2. | Info
  3. | Warning
  4. | Error
  5. | Bug

The type of severity.

module type Code = sig ... end

The signature of message code. An implementer should specify the message code used in their library or application.

type text = Stdlib.Format.formatter -> unit

The type of text.

When we render a diagnostic, the layout engine of the rendering backend should be the one making layout choices. Therefore, we cannot pass already formatted strings. Instead, a text is defined to be a function that takes a formatter and uses it to render the content. The following two conditions must be satisfied:

  1. All string (and character) literals must be encoded using UTF-8.
  2. All string (and character) literals must not contain control characters (such as the newline character \n). It is okay to have break hints (such as @, and @ ) but not literal control characters. This means you should avoid pre-formatted strings, and if you must use them, use text to convert newline characters. Control characters include `U+0000-001F` (C0 controls), `U+007F` (backspace) and `U+0080-009F` (C1 controls). These characters are banned because they would mess up the cursor position.
type message = text Span.located

A message is a located text.

type backtrace = message Bwd.bwd

A backtrace is a (backward) list of messages.

type 'code t = {
  1. severity : severity;
    (*

    Severity of the diagnostic.

    *)
  2. code : 'code;
    (*

    The message code.

    *)
  3. message : message;
    (*

    The main message.

    *)
  4. backtrace : backtrace;
    (*

    The backtrace leading to this diagnostic.

    *)
  5. additional_messages : message list;
    (*

    Additional messages relevant to the main message that are not part of the backtrace.

    *)
}

The type of diagnostics.

Constructing Messages

val text : string -> text

text str converts the string str into a text, converting each '\n' into a call to Format.pp_force_newline.

val textf : ('a, Stdlib.Format.formatter, unit, text) Stdlib.format4 -> 'a

textf format ... constructs a text. It is an alias of Format.dprintf. Note that there should not be any literal control characters (e.g., literal newline characters).

val ktextf : (text -> 'b) -> ('a, Stdlib.Format.formatter, unit, 'b) Stdlib.format4 -> - 'a

ktextf kont format ... is kont (textf code format ...). It is an alias of Format.kdprintf.

val message : ?loc:Span.t -> string -> message

message str converts the string str into a message.

  • parameter loc

    The location of the message (usually the code) to highlight.

val messagef : - ?loc:Span.t -> + 'a

ktextf kont format ... is kont (textf code format ...). It is an alias of Format.kdprintf.

val message : ?loc:Span.t -> string -> message

message str converts the string str into a message.

  • parameter loc

    The location of the message (usually the code) to highlight.

val messagef : + ?loc:Span.t -> ('a, Stdlib.Format.formatter, unit, message) Stdlib.format4 -> 'a

messagef format ... constructs a message. Note that there should not be any literal control characters (e.g., literal newline characters).

  • parameter loc

    The location of the message (usually the code) to highlight.

val kmessagef : - ?loc:Span.t -> + ?loc:Span.t -> (message -> 'b) -> ('a, Stdlib.Format.formatter, unit, 'b) Stdlib.format4 -> 'a

kmessagef kont format ... is kont (messagef code format ...).

  • parameter loc

    The location of the message (usually the code) to highlight.

Constructing Diagnostics

val make : - ?loc:Span.t -> - ?backtrace:backtrace -> - ?additional_messages:message list -> + ?loc:Span.t -> + ?backtrace:backtrace -> + ?additional_messages:message list -> severity -> 'code -> string -> 'code t

make severity code str constructs a diagnostic with the message str.

Example:

make Warning `ChiError "Your Ch'i is critically low"
  • parameter backtrace

    The backtrace (to overwrite the accumulative frames up to this point).

  • parameter additional_messages

    Additional messages that part of the backtrace. For example, they can be bindings shadowed by the current one.

val makef : - ?loc:Span.t -> - ?backtrace:backtrace -> - ?additional_messages:message list -> + ?loc:Span.t -> + ?backtrace:backtrace -> + ?additional_messages:message list -> severity -> 'code -> ('a, Stdlib.Format.formatter, unit, 'code t) Stdlib.format4 -> 'a

makef severity code format ... is make severity code (messagef format ...). It formats the message and constructs a diagnostic out of it.

Example:

makef Warning `ChiError "Your %s is critically low" "Ch'i"
  • parameter loc

    The location of the text (usually the code) to highlight.

  • parameter backtrace

    The backtrace (to overwrite the accumulative frames up to this point).

  • parameter additional_messages

    Additional messages that part of the backtrace. For example, they can be bindings shadowed by the current one.

val kmakef : - ?loc:Span.t -> - ?backtrace:backtrace -> - ?additional_messages:message list -> + ?loc:Span.t -> + ?backtrace:backtrace -> + ?additional_messages:message list -> ('code t -> 'b) -> severity -> 'code -> ('a, Stdlib.Format.formatter, unit, 'b) Stdlib.format4 -> 'a

kmakef kont severity code format ... is kont (makef severity code format ...).

  • parameter loc

    The location of the text (usually the code) to highlight.

  • parameter backtrace

    The backtrace (to overwrite the accumulative frames up to this point).

  • parameter additional_messages

    Additional messages that part of the backtrace. For example, they can be bindings shadowed by the current one.

val of_message : - ?backtrace:backtrace -> - ?additional_messages:message list -> + ?backtrace:backtrace -> + ?additional_messages:message list -> severity -> 'code -> message -> - 'code t

of_message severity code message constructs a diagnostic with the message.

Example:

make Warning `ChiError @@ message "Your Ch'i is critically low"
  • parameter backtrace

    The backtrace (to overwrite the accumulative frames up to this point).

  • parameter additional_messages

    Additional messages that part of the backtrace. For example, they can be bindings shadowed by the current one.

Other Helper Functions

val map : ('code1 -> 'code2) -> 'code1 t -> 'code2 t

A convenience function that maps the message code. This is helpful when using Logger.S.adopt.

val string_of_severity : severity -> string

A convenience function that converts a severity into its constructor name. For example, Warning will be converted into the string "Warning".

val string_of_text : text -> string

A convenience function that converts a text into a string by formatting it with the maximum admissible margin. Note that the resulting string may contain control characters and might not be suitable for constructing new instances of text or message.

\ No newline at end of file + 'code t

of_message severity code message constructs a diagnostic with the message.

Example:

make Warning `ChiError @@ message "Your Ch'i is critically low"
  • parameter backtrace

    The backtrace (to overwrite the accumulative frames up to this point).

  • parameter additional_messages

    Additional messages that part of the backtrace. For example, they can be bindings shadowed by the current one.

Other Helper Functions

val map : ('code1 -> 'code2) -> 'code1 t -> 'code2 t

A convenience function that maps the message code. This is helpful when using Logger.S.adopt.

val string_of_severity : severity -> string

A convenience function that converts a severity into its constructor name. For example, Warning will be converted into the string "Warning".

val string_of_text : text -> string

A convenience function that converts a text into a string by formatting it with the maximum admissible margin. Note that the resulting string may contain control characters and might not be suitable for constructing new instances of text or message.

diff --git a/asai/Asai/Diagnostic/module-type-Code/index.html b/asai/Asai/Diagnostic/module-type-Code/index.html index a97cc67..44436b6 100644 --- a/asai/Asai/Diagnostic/module-type-Code/index.html +++ b/asai/Asai/Diagnostic/module-type-Code/index.html @@ -1,2 +1,2 @@ -Code (asai.Asai.Diagnostic.Code)

Module type Diagnostic.Code

The signature of message code. An implementer should specify the message code used in their library or application.

type t

The type of all message codes.

val default_severity : t -> severity

The default severity of the code. The severity of a message is about whether the message is an error or a warning, etc. To clarify, it is about how serious the message is to the end user, not whether the program should stop or continue. The severity may be overwritten at the time of issuing a message to the end user.

val to_string : t -> string

A concise, ideally Google-able string representation of each message code. Detailed or long descriptions of code should be avoided. For example, E001 works better than type-checking error. The shorter, the better.

\ No newline at end of file +Code (asai.Asai.Diagnostic.Code)

Module type Diagnostic.Code

The signature of message code. An implementer should specify the message code used in their library or application.

type t

The type of all message codes.

val default_severity : t -> severity

The default severity of the code. The severity of a message is about whether the message is an error or a warning, etc. To clarify, it is about how serious the message is to the end user, not whether the program should stop or continue. The severity may be overwritten at the time of issuing a message to the end user.

val to_string : t -> string

A concise, ideally Google-able string representation of each message code. Detailed or long descriptions of code should be avoided. For example, E001 works better than type-checking error. The shorter, the better.

diff --git a/asai/Asai/Explication/index.html b/asai/Asai/Explication/index.html index aef8b3e..4c9bddf 100644 --- a/asai/Asai/Explication/index.html +++ b/asai/Asai/Explication/index.html @@ -1,6 +1,6 @@ -Explication (asai.Asai.Explication)

Module Asai.Explication

The definition of highlighted text suitable for rendering. You probably do not need this module unless you want to create your own backend.

Types

type ('a, 'style) styled = {
  1. style : 'style;
  2. value : 'a;
}

A styled value is a value with a style.

type 'style segment = (string, 'style) styled

A segment is a styled string from the user content.

type 'style line = 'style segment list

A line is a list of segments.

type 'style block = {
  1. start_line_num : int;
    (*

    The starting 1-indexed line number of a block.

    *)
  2. lines : 'style line list;
    (*

    The lines within a block.

    *)
}

A block is a collection of consecutive lines.

type 'style part = {
  1. file_path : string;
    (*

    The file path of a part.

    *)
  2. blocks : 'style block list;
    (*

    The blocks within a part.

    *)
}

A part consists of multiple blocks from the same file. These blocks should be non-overlapping and sorted by importance or the textual order.

type 'style t = 'style part list

Highlighted texts instead of spans.

Helper Functions

val style : 'style -> 'value -> ('value, 'style) styled

Debugging

val dump : +Explication (asai.Asai.Explication)

Module Asai.Explication

The definition of highlighted text suitable for rendering. You probably do not need this module unless you want to create your own backend.

Types

type ('a, 'style) styled = {
  1. style : 'style;
  2. value : 'a;
}

A styled value is a value with a style.

type 'style segment = (string, 'style) styled

A segment is a styled string from the user content.

type 'style line = 'style segment list

A line is a list of segments.

type 'style block = {
  1. start_line_num : int;
    (*

    The starting 1-indexed line number of a block.

    *)
  2. lines : 'style line list;
    (*

    The lines within a block.

    *)
}

A block is a collection of consecutive lines.

type 'style part = {
  1. file_path : string;
    (*

    The file path of a part.

    *)
  2. blocks : 'style block list;
    (*

    The blocks within a part.

    *)
}

A part consists of multiple blocks from the same file. These blocks should be non-overlapping and sorted by importance or the textual order.

type 'style t = 'style part list

Highlighted texts instead of spans.

Helper Functions

val style : 'style -> 'value -> ('value, 'style) styled

Debugging

val dump : (Stdlib.Format.formatter -> 'style -> unit) -> Stdlib.Format.formatter -> 'style t -> - unit

Ugly printer for debugging

\ No newline at end of file + unit

Ugly printer for debugging

diff --git a/asai/Asai/Explicator/Make/argument-1-_/index.html b/asai/Asai/Explicator/Make/argument-1-_/index.html index 512d8c9..68d8b99 100644 --- a/asai/Asai/Explicator/Make/argument-1-_/index.html +++ b/asai/Asai/Explicator/Make/argument-1-_/index.html @@ -1,2 +1,2 @@ -_ (asai.Asai.Explicator.Make._)

Parameter Make._

type file

An abstract type of files.

val load : string -> file

load file_path loads the resource at file_path.

val length : file -> int

length file_path gets the size of the file.

val unsafe_get : file -> int -> char

unsafe_get file_path i reads the ith byte of the file without checking the file size.

\ No newline at end of file +_ (asai.Asai.Explicator.Make._)

Parameter Make._

type file

An abstract type of files.

val load : string -> file

load file_path loads the resource at file_path.

val length : file -> int

length file_path gets the size of the file.

val unsafe_get : file -> int -> char

unsafe_get file_path i reads the ith byte of the file without checking the file size.

diff --git a/asai/Asai/Explicator/Make/argument-2-Style/index.html b/asai/Asai/Explicator/Make/argument-2-Style/index.html index 5980af8..5a440cf 100644 --- a/asai/Asai/Explicator/Make/argument-2-Style/index.html +++ b/asai/Asai/Explicator/Make/argument-2-Style/index.html @@ -1,2 +1,2 @@ -Style (asai.Asai.Explicator.Make.Style)

Parameter Make.Style

type t

The abstract type of highlighting styles.

val default : t

default is the default style, meaning no highlighting is applied. It should be the unit of compose.

val equal : t -> t -> bool

Comparing whether two styles are equivalent.

val compare : t -> t -> int

Comparing styles for the importance they represent.

val max : t -> t -> t

max s1 s2 gives the style that signals more importance.

val is_default : t -> bool

is_default s checks if the style is the default style. It should be equivalent to equal default s.

val compose : t -> t -> t

Compose two styles into one. The operator should form a commutative group with default being its unit.

val dump : Stdlib.Format.formatter -> t -> unit

Ugly printer for debugging

\ No newline at end of file +Style (asai.Asai.Explicator.Make.Style)

Parameter Make.Style

type t

The abstract type of highlighting styles.

val default : t

default is the default style, meaning no highlighting is applied. It should be the unit of compose.

val equal : t -> t -> bool

Comparing whether two styles are equivalent.

val compare : t -> t -> int

Comparing styles for the importance they represent.

val max : t -> t -> t

max s1 s2 gives the style that signals more importance.

val is_default : t -> bool

is_default s checks if the style is the default style. It should be equivalent to equal default s.

val compose : t -> t -> t

Compose two styles into one. The operator should form a commutative group with default being its unit.

val dump : Stdlib.Format.formatter -> t -> unit

Ugly printer for debugging

diff --git a/asai/Asai/Explicator/Make/index.html b/asai/Asai/Explicator/Make/index.html index da309b8..f72665a 100644 --- a/asai/Asai/Explicator/Make/index.html +++ b/asai/Asai/Explicator/Make/index.html @@ -1,6 +1,6 @@ -Make (asai.Asai.Explicator.Make)

Module Explicator.Make

Making an explicator.

Parameters

module _ : Reader
module Style : Style

Signature

exception Unexpected_end_of_file of Span.position

Unexpected_end_of_file pos means the pos lies beyond the end of file. This usually means the file has been truncated after the parsing.

exception Unexpected_line_num_increment of Span.position

Unexpected_line_num_increment pos means the line number of pos is larger than than that of its preceding position during explication, but the explicator did not encounter a newline in between. This usually indicates that there's something wrong with the lexer, or that the file has changed since the parsing.

exception Unexpected_newline of Span.position

Unexpected_newline pos means the line number of pos is the same as its preceding position during explication, but the explicator encountered a newline in between. This usually indicates that there's something wrong with the lexer, or that the file has changed since the parsing.

exception Unexpected_position_in_newline of Span.position

Unexpected_position_in_newline pos means the position pos is in the middle of a newline. This can happen when the newline consists of multiple bytes, for example 0x0D 0x0A. It usually indicates that there's something wrong with the lexer, or that the file has changed since the parsing.

val explicate : - ?line_breaking:[ `Unicode | `Traditional ] -> - ?block_splitting_threshold:int -> +Make (asai.Asai.Explicator.Make)

Module Explicator.Make

Making an explicator.

Parameters

module _ : Reader
module Style : Style

Signature

exception Unexpected_end_of_file of Span.position

Unexpected_end_of_file pos means the pos lies beyond the end of file. This usually means the file has been truncated after the parsing.

exception Unexpected_line_num_increment of Span.position

Unexpected_line_num_increment pos means the line number of pos is larger than than that of its preceding position during explication, but the explicator did not encounter a newline in between. This usually indicates that there's something wrong with the lexer, or that the file has changed since the parsing.

exception Unexpected_newline of Span.position

Unexpected_newline pos means the line number of pos is the same as its preceding position during explication, but the explicator encountered a newline in between. This usually indicates that there's something wrong with the lexer, or that the file has changed since the parsing.

exception Unexpected_position_in_newline of Span.position

Unexpected_position_in_newline pos means the position pos is in the middle of a newline. This can happen when the newline consists of multiple bytes, for example 0x0D 0x0A. It usually indicates that there's something wrong with the lexer, or that the file has changed since the parsing.

val explicate : + ?line_breaking:[ `Unicode | `Traditional ] -> + ?block_splitting_threshold:int -> (Span.t, Style.t) Explication.styled list -> - Style.t Explication.t

Explicate a list of spans using content from a data reader.

  • parameter line_breaking

    The algorithm to recognize (hard) line breaks. The `Unicode algorithm recognizes all Unicode character sequences in Unicode 15.0.0 Table 5-1 as line breaks. The `Traditional algorithm only recognizes U+000A (LF), U+000D (CR), and U+000D U+000A (CRLF) as line breaks. The default is the `Traditional algorithm.

  • parameter block_splitting_threshold

    The maximum number of consecutive, non-highlighted lines allowed in a block. The function will try to minimize the number of blocks, as long as no block has too many consecutive, non-highlighted lines. A higher threshold will lead to fewer blocks. When the threshold is zero, it means no block can contain any non-highlighted line. The default value is zero.

  • raises UnexpectedLineNumIncrement

    if the line number of some position is increased by one but there was no newline character \n.

  • raises PositionBeyondEndOfFile

    if some position falls outside the data content. (That is, the file is too smaller, if the data reader is reading files.)

\ No newline at end of file + Style.t Explication.t

Explicate a list of spans using content from a data reader.

  • parameter line_breaking

    The algorithm to recognize (hard) line breaks. The `Unicode algorithm recognizes all Unicode character sequences in Unicode 15.0.0 Table 5-1 as line breaks. The `Traditional algorithm only recognizes U+000A (LF), U+000D (CR), and U+000D U+000A (CRLF) as line breaks. The default is the `Traditional algorithm.

  • parameter block_splitting_threshold

    The maximum number of consecutive, non-highlighted lines allowed in a block. The function will try to minimize the number of blocks, as long as no block has too many consecutive, non-highlighted lines. A higher threshold will lead to fewer blocks. When the threshold is zero, it means no block can contain any non-highlighted line. The default value is zero.

  • raises UnexpectedLineNumIncrement

    if the line number of some position is increased by one but there was no newline character \n.

  • raises PositionBeyondEndOfFile

    if some position falls outside the data content. (That is, the file is too smaller, if the data reader is reading files.)

diff --git a/asai/Asai/Explicator/index.html b/asai/Asai/Explicator/index.html index bfc5be2..2ecdca1 100644 --- a/asai/Asai/Explicator/index.html +++ b/asai/Asai/Explicator/index.html @@ -1,2 +1,2 @@ -Explicator (asai.Asai.Explicator)

Module Asai.Explicator

Turning location information into highlighted text suitable for rendering. You probably do not need this module unless you want to create your own backend.

module type Reader = sig ... end

The signature of data readers.

module type Style = sig ... end

The signature of highlighting styles

module type S = sig ... end

The signature of explicators.

module Make (_ : Reader) (Style : Style) : S with module Style := Style

Making an explicator.

\ No newline at end of file +Explicator (asai.Asai.Explicator)

Module Asai.Explicator

Turning location information into highlighted text suitable for rendering. You probably do not need this module unless you want to create your own backend.

module type Reader = sig ... end

The signature of data readers.

module type Style = sig ... end

The signature of highlighting styles

module type S = sig ... end

The signature of explicators.

module Make (_ : Reader) (Style : Style) : S with module Style := Style

Making an explicator.

diff --git a/asai/Asai/Explicator/module-type-Reader/index.html b/asai/Asai/Explicator/module-type-Reader/index.html index 5466e35..d4dd9d1 100644 --- a/asai/Asai/Explicator/module-type-Reader/index.html +++ b/asai/Asai/Explicator/module-type-Reader/index.html @@ -1,2 +1,2 @@ -Reader (asai.Asai.Explicator.Reader)

Module type Explicator.Reader

The signature of data readers.

type file

An abstract type of files.

val load : string -> file

load file_path loads the resource at file_path.

val length : file -> int

length file_path gets the size of the file.

val unsafe_get : file -> int -> char

unsafe_get file_path i reads the ith byte of the file without checking the file size.

\ No newline at end of file +Reader (asai.Asai.Explicator.Reader)

Module type Explicator.Reader

The signature of data readers.

type file

An abstract type of files.

val load : string -> file

load file_path loads the resource at file_path.

val length : file -> int

length file_path gets the size of the file.

val unsafe_get : file -> int -> char

unsafe_get file_path i reads the ith byte of the file without checking the file size.

diff --git a/asai/Asai/Explicator/module-type-S/Style/index.html b/asai/Asai/Explicator/module-type-S/Style/index.html index 54ed0fa..790dcb4 100644 --- a/asai/Asai/Explicator/module-type-S/Style/index.html +++ b/asai/Asai/Explicator/module-type-S/Style/index.html @@ -1,2 +1,2 @@ -Style (asai.Asai.Explicator.S.Style)

Module S.Style

type t

The abstract type of highlighting styles.

val default : t

default is the default style, meaning no highlighting is applied. It should be the unit of compose.

val equal : t -> t -> bool

Comparing whether two styles are equivalent.

val compare : t -> t -> int

Comparing styles for the importance they represent.

val max : t -> t -> t

max s1 s2 gives the style that signals more importance.

val is_default : t -> bool

is_default s checks if the style is the default style. It should be equivalent to equal default s.

val compose : t -> t -> t

Compose two styles into one. The operator should form a commutative group with default being its unit.

val dump : Stdlib.Format.formatter -> t -> unit

Ugly printer for debugging

\ No newline at end of file +Style (asai.Asai.Explicator.S.Style)

Module S.Style

type t

The abstract type of highlighting styles.

val default : t

default is the default style, meaning no highlighting is applied. It should be the unit of compose.

val equal : t -> t -> bool

Comparing whether two styles are equivalent.

val compare : t -> t -> int

Comparing styles for the importance they represent.

val max : t -> t -> t

max s1 s2 gives the style that signals more importance.

val is_default : t -> bool

is_default s checks if the style is the default style. It should be equivalent to equal default s.

val compose : t -> t -> t

Compose two styles into one. The operator should form a commutative group with default being its unit.

val dump : Stdlib.Format.formatter -> t -> unit

Ugly printer for debugging

diff --git a/asai/Asai/Explicator/module-type-S/index.html b/asai/Asai/Explicator/module-type-S/index.html index 87a03af..5dc81b3 100644 --- a/asai/Asai/Explicator/module-type-S/index.html +++ b/asai/Asai/Explicator/module-type-S/index.html @@ -1,6 +1,6 @@ -S (asai.Asai.Explicator.S)

Module type Explicator.S

The signature of explicators.

module Style : Style
exception Unexpected_end_of_file of Span.position

Unexpected_end_of_file pos means the pos lies beyond the end of file. This usually means the file has been truncated after the parsing.

exception Unexpected_line_num_increment of Span.position

Unexpected_line_num_increment pos means the line number of pos is larger than than that of its preceding position during explication, but the explicator did not encounter a newline in between. This usually indicates that there's something wrong with the lexer, or that the file has changed since the parsing.

exception Unexpected_newline of Span.position

Unexpected_newline pos means the line number of pos is the same as its preceding position during explication, but the explicator encountered a newline in between. This usually indicates that there's something wrong with the lexer, or that the file has changed since the parsing.

exception Unexpected_position_in_newline of Span.position

Unexpected_position_in_newline pos means the position pos is in the middle of a newline. This can happen when the newline consists of multiple bytes, for example 0x0D 0x0A. It usually indicates that there's something wrong with the lexer, or that the file has changed since the parsing.

val explicate : - ?line_breaking:[ `Unicode | `Traditional ] -> - ?block_splitting_threshold:int -> +S (asai.Asai.Explicator.S)

Module type Explicator.S

The signature of explicators.

module Style : Style
exception Unexpected_end_of_file of Span.position

Unexpected_end_of_file pos means the pos lies beyond the end of file. This usually means the file has been truncated after the parsing.

exception Unexpected_line_num_increment of Span.position

Unexpected_line_num_increment pos means the line number of pos is larger than than that of its preceding position during explication, but the explicator did not encounter a newline in between. This usually indicates that there's something wrong with the lexer, or that the file has changed since the parsing.

exception Unexpected_newline of Span.position

Unexpected_newline pos means the line number of pos is the same as its preceding position during explication, but the explicator encountered a newline in between. This usually indicates that there's something wrong with the lexer, or that the file has changed since the parsing.

exception Unexpected_position_in_newline of Span.position

Unexpected_position_in_newline pos means the position pos is in the middle of a newline. This can happen when the newline consists of multiple bytes, for example 0x0D 0x0A. It usually indicates that there's something wrong with the lexer, or that the file has changed since the parsing.

val explicate : + ?line_breaking:[ `Unicode | `Traditional ] -> + ?block_splitting_threshold:int -> (Span.t, Style.t) Explication.styled list -> - Style.t Explication.t

Explicate a list of spans using content from a data reader.

  • parameter line_breaking

    The algorithm to recognize (hard) line breaks. The `Unicode algorithm recognizes all Unicode character sequences in Unicode 15.0.0 Table 5-1 as line breaks. The `Traditional algorithm only recognizes U+000A (LF), U+000D (CR), and U+000D U+000A (CRLF) as line breaks. The default is the `Traditional algorithm.

  • parameter block_splitting_threshold

    The maximum number of consecutive, non-highlighted lines allowed in a block. The function will try to minimize the number of blocks, as long as no block has too many consecutive, non-highlighted lines. A higher threshold will lead to fewer blocks. When the threshold is zero, it means no block can contain any non-highlighted line. The default value is zero.

  • raises UnexpectedLineNumIncrement

    if the line number of some position is increased by one but there was no newline character \n.

  • raises PositionBeyondEndOfFile

    if some position falls outside the data content. (That is, the file is too smaller, if the data reader is reading files.)

\ No newline at end of file + Style.t Explication.t

Explicate a list of spans using content from a data reader.

  • parameter line_breaking

    The algorithm to recognize (hard) line breaks. The `Unicode algorithm recognizes all Unicode character sequences in Unicode 15.0.0 Table 5-1 as line breaks. The `Traditional algorithm only recognizes U+000A (LF), U+000D (CR), and U+000D U+000A (CRLF) as line breaks. The default is the `Traditional algorithm.

  • parameter block_splitting_threshold

    The maximum number of consecutive, non-highlighted lines allowed in a block. The function will try to minimize the number of blocks, as long as no block has too many consecutive, non-highlighted lines. A higher threshold will lead to fewer blocks. When the threshold is zero, it means no block can contain any non-highlighted line. The default value is zero.

  • raises UnexpectedLineNumIncrement

    if the line number of some position is increased by one but there was no newline character \n.

  • raises PositionBeyondEndOfFile

    if some position falls outside the data content. (That is, the file is too smaller, if the data reader is reading files.)

diff --git a/asai/Asai/Explicator/module-type-Style/index.html b/asai/Asai/Explicator/module-type-Style/index.html index 6c16667..461165e 100644 --- a/asai/Asai/Explicator/module-type-Style/index.html +++ b/asai/Asai/Explicator/module-type-Style/index.html @@ -1,2 +1,2 @@ -Style (asai.Asai.Explicator.Style)

Module type Explicator.Style

The signature of highlighting styles

type t

The abstract type of highlighting styles.

val default : t

default is the default style, meaning no highlighting is applied. It should be the unit of compose.

val equal : t -> t -> bool

Comparing whether two styles are equivalent.

val compare : t -> t -> int

Comparing styles for the importance they represent.

val max : t -> t -> t

max s1 s2 gives the style that signals more importance.

val is_default : t -> bool

is_default s checks if the style is the default style. It should be equivalent to equal default s.

val compose : t -> t -> t

Compose two styles into one. The operator should form a commutative group with default being its unit.

val dump : Stdlib.Format.formatter -> t -> unit

Ugly printer for debugging

\ No newline at end of file +Style (asai.Asai.Explicator.Style)

Module type Explicator.Style

The signature of highlighting styles

type t

The abstract type of highlighting styles.

val default : t

default is the default style, meaning no highlighting is applied. It should be the unit of compose.

val equal : t -> t -> bool

Comparing whether two styles are equivalent.

val compare : t -> t -> int

Comparing styles for the importance they represent.

val max : t -> t -> t

max s1 s2 gives the style that signals more importance.

val is_default : t -> bool

is_default s checks if the style is the default style. It should be equivalent to equal default s.

val compose : t -> t -> t

Compose two styles into one. The operator should form a commutative group with default being its unit.

val dump : Stdlib.Format.formatter -> t -> unit

Ugly printer for debugging

diff --git a/asai/Asai/FileReader/index.html b/asai/Asai/FileReader/index.html index fe19af1..664e032 100644 --- a/asai/Asai/FileReader/index.html +++ b/asai/Asai/FileReader/index.html @@ -1,2 +1,2 @@ -FileReader (asai.Asai.FileReader)

Module Asai.FileReader

An implementation of Explicator.Reader using memory-mapped file I/O. You probably do not need this module unless you want to create your own backend.

include Explicator.Reader
type file

An abstract type of files.

val load : string -> file

load file_path loads the resource at file_path.

val length : file -> int

length file_path gets the size of the file.

val unsafe_get : file -> int -> char

unsafe_get file_path i reads the ith byte of the file without checking the file size.

val run : (unit -> 'a) -> 'a

run f runs the thunk f and handles the internal algebraic effects.

\ No newline at end of file +FileReader (asai.Asai.FileReader)

Module Asai.FileReader

An implementation of Explicator.Reader using memory-mapped file I/O. You probably do not need this module unless you want to create your own backend.

include Explicator.Reader
type file

An abstract type of files.

val load : string -> file

load file_path loads the resource at file_path.

val length : file -> int

length file_path gets the size of the file.

val unsafe_get : file -> int -> char

unsafe_get file_path i reads the ith byte of the file without checking the file size.

val run : (unit -> 'a) -> 'a

run f runs the thunk f and handles the internal algebraic effects.

diff --git a/asai/Asai/GitHub/Make/argument-1-Code/index.html b/asai/Asai/GitHub/Make/argument-1-Code/index.html index b4a7750..7bf5edd 100644 --- a/asai/Asai/GitHub/Make/argument-1-Code/index.html +++ b/asai/Asai/GitHub/Make/argument-1-Code/index.html @@ -1,2 +1,2 @@ -Code (asai.Asai.GitHub.Make.Code)

Parameter Make.Code

type t

The type of all message codes.

val default_severity : t -> Diagnostic.severity

The default severity of the code. The severity of a message is about whether the message is an error or a warning, etc. To clarify, it is about how serious the message is to the end user, not whether the program should stop or continue. The severity may be overwritten at the time of issuing a message to the end user.

val to_string : t -> string

A concise, ideally Google-able string representation of each message code. Detailed or long descriptions of code should be avoided. For example, E001 works better than type-checking error. The shorter, the better.

\ No newline at end of file +Code (asai.Asai.GitHub.Make.Code)

Parameter Make.Code

type t

The type of all message codes.

val default_severity : t -> Diagnostic.severity

The default severity of the code. The severity of a message is about whether the message is an error or a warning, etc. To clarify, it is about how serious the message is to the end user, not whether the program should stop or continue. The severity may be overwritten at the time of issuing a message to the end user.

val to_string : t -> string

A concise, ideally Google-able string representation of each message code. Detailed or long descriptions of code should be avoided. For example, E001 works better than type-checking error. The shorter, the better.

diff --git a/asai/Asai/GitHub/Make/index.html b/asai/Asai/GitHub/Make/index.html index d150144..9b5c8ca 100644 --- a/asai/Asai/GitHub/Make/index.html +++ b/asai/Asai/GitHub/Make/index.html @@ -1,2 +1,2 @@ -Make (asai.Asai.GitHub.Make)

Module GitHub.Make

The functor to create a printer for GitHub Actions workflow commands.

Parameters

Signature

val print : Code.t Diagnostic.t -> unit

Print a diagnostic as a GitHub Actions workflow command.

\ No newline at end of file +Make (asai.Asai.GitHub.Make)

Module GitHub.Make

The functor to create a printer for GitHub Actions workflow commands.

Parameters

Signature

val print : Code.t Diagnostic.t -> unit

Print a diagnostic as a GitHub Actions workflow command.

diff --git a/asai/Asai/GitHub/index.html b/asai/Asai/GitHub/index.html index 8b3b608..55490c3 100644 --- a/asai/Asai/GitHub/index.html +++ b/asai/Asai/GitHub/index.html @@ -1,2 +1,2 @@ -GitHub (asai.Asai.GitHub)

Module Asai.GitHub

GitHub Actions workflow commands.

module Make (Code : Diagnostic.Code) : sig ... end

The functor to create a printer for GitHub Actions workflow commands.

\ No newline at end of file +GitHub (asai.Asai.GitHub)

Module Asai.GitHub

GitHub Actions workflow commands.

module Make (Code : Diagnostic.Code) : sig ... end

The functor to create a printer for GitHub Actions workflow commands.

diff --git a/asai/Asai/Logger/Make/argument-1-Code/index.html b/asai/Asai/Logger/Make/argument-1-Code/index.html index 5d65991..09723c3 100644 --- a/asai/Asai/Logger/Make/argument-1-Code/index.html +++ b/asai/Asai/Logger/Make/argument-1-Code/index.html @@ -1,2 +1,2 @@ -Code (asai.Asai.Logger.Make.Code)

Parameter Make.Code

type t

The type of all message codes.

val default_severity : t -> Diagnostic.severity

The default severity of the code. The severity of a message is about whether the message is an error or a warning, etc. To clarify, it is about how serious the message is to the end user, not whether the program should stop or continue. The severity may be overwritten at the time of issuing a message to the end user.

val to_string : t -> string

A concise, ideally Google-able string representation of each message code. Detailed or long descriptions of code should be avoided. For example, E001 works better than type-checking error. The shorter, the better.

\ No newline at end of file +Code (asai.Asai.Logger.Make.Code)

Parameter Make.Code

type t

The type of all message codes.

val default_severity : t -> Diagnostic.severity

The default severity of the code. The severity of a message is about whether the message is an error or a warning, etc. To clarify, it is about how serious the message is to the end user, not whether the program should stop or continue. The severity may be overwritten at the time of issuing a message to the end user.

val to_string : t -> string

A concise, ideally Google-able string representation of each message code. Detailed or long descriptions of code should be avoided. For example, E001 works better than type-checking error. The shorter, the better.

diff --git a/asai/Asai/Logger/Make/index.html b/asai/Asai/Logger/Make/index.html index f68e90a..30f52ee 100644 --- a/asai/Asai/Logger/Make/index.html +++ b/asai/Asai/Logger/Make/index.html @@ -1,70 +1,70 @@ -Make (asai.Asai.Logger.Make)

Module Logger.Make

The functor to generate a logger.

Parameters

Signature

Sending Messages

val emit : - ?severity:Diagnostic.severity -> - ?loc:Span.t -> - ?backtrace:Diagnostic.backtrace -> - ?additional_messages:Diagnostic.message list -> +Make (asai.Asai.Logger.Make)

Module Logger.Make

The functor to generate a logger.

Parameters

Signature

Sending Messages

val emit : + ?severity:Diagnostic.severity -> + ?loc:Span.t -> + ?backtrace:Diagnostic.backtrace -> + ?additional_messages:Diagnostic.message list -> Code.t -> string -> unit

emit code str emits a string and continues the computation.

Example:

Logger.emit `TypeError "This type is extremely unnatural:\nNat"
  • parameter severity

    The severity (to overwrite the default severity inferred from the message code).

  • parameter loc

    The location of the text (usually the code) to highlight.

  • parameter backtrace

    The backtrace (to overwrite the accumulative frames up to this point).

  • parameter additional_messages

    Additional messages that part of the backtrace. For example, they can be bindings shadowed by the current one.

val emitf : - ?severity:Diagnostic.severity -> - ?loc:Span.t -> - ?backtrace:Diagnostic.backtrace -> - ?additional_messages:Diagnostic.message list -> + ?severity:Diagnostic.severity -> + ?loc:Span.t -> + ?backtrace:Diagnostic.backtrace -> + ?additional_messages:Diagnostic.message list -> Code.t -> ('a, Stdlib.Format.formatter, unit, unit) Stdlib.format4 -> 'a

emitf code format ... formats and emits a message, and then continues the computation. Note that there should not be any literal control characters. See Diagnostic.text.

Example:

Logger.emitf `TypeError "Type %a is too ugly" Syntax.pp tp
  • parameter severity

    The severity (to overwrite the default severity inferred from the message code).

  • parameter loc

    The location of the text (usually the code) to highlight.

  • parameter backtrace

    The backtrace (to overwrite the accumulative frames up to this point).

  • parameter additional_messages

    Additional messages that part of the backtrace. For example, they can be bindings shadowed by the current one.

val emit_diagnostic : Code.t Diagnostic.t -> unit

Emit a diagnostic and continue the computation.

val fatal : - ?severity:Diagnostic.severity -> - ?loc:Span.t -> - ?backtrace:Diagnostic.backtrace -> - ?additional_messages:Diagnostic.message list -> + ?severity:Diagnostic.severity -> + ?loc:Span.t -> + ?backtrace:Diagnostic.backtrace -> + ?additional_messages:Diagnostic.message list -> Code.t -> string -> 'a

fatal code str aborts the current computation with the string str.

Example:

Logger.fatal `FileError "Forgot to feed the cat"
  • parameter severity

    The severity (to overwrite the default severity inferred from the message code).

  • parameter loc

    The location of the text (usually the code) to highlight.

  • parameter backtrace

    The backtrace (to overwrite the accumulative frames up to this point).

  • parameter additional_messages

    Additional messages that part of the backtrace. For example, they can be bindings shadowed by the current one.

val fatalf : - ?severity:Diagnostic.severity -> - ?loc:Span.t -> - ?backtrace:Diagnostic.backtrace -> - ?additional_messages:Diagnostic.message list -> + ?severity:Diagnostic.severity -> + ?loc:Span.t -> + ?backtrace:Diagnostic.backtrace -> + ?additional_messages:Diagnostic.message list -> Code.t -> ('a, Stdlib.Format.formatter, unit, 'b) Stdlib.format4 -> 'a

fatalf code format ... constructs a diagnostic and aborts the current computation with the diagnostic. Note that there should not be any literal control characters. See Diagnostic.text.

Example:

Logger.fatalf `FileError "Failed to write the password to %s" file_path
  • parameter severity

    The severity (to overwrite the default severity inferred from the message code).

  • parameter loc

    The location of the text (usually the code) to highlight.

  • parameter backtrace

    The backtrace (to overwrite the accumulative frames up to this point).

  • parameter additional_messages

    Additional messages that part of the backtrace. For example, they can be bindings shadowed by the current one.

val fatal_diagnostic : Code.t Diagnostic.t -> 'a

Abort the computation with a diagnostic.

Backtraces

val get_backtrace : unit -> Diagnostic.backtrace

get_backtrace() returns the current backtrace.

val with_backtrace : Diagnostic.backtrace -> (unit -> 'a) -> 'a

with_backtrace bt f runs the thunk f with bt as the initial backtrace.

Example:

(* running code with a fresh backtrace *)
-with_backtrace Emp @@ fun () -> ...
val trace : ?loc:Span.t -> string -> (unit -> 'a) -> 'a

trace str f records the string str and runs the thunk f with the new backtrace.

  • parameter loc

    The location of the text (usually the code) to highlight.

val tracef : - ?loc:Span.t -> +with_backtrace Emp @@ fun () -> ...
val trace : ?loc:Span.t -> string -> (unit -> 'a) -> 'a

trace str f records the string str and runs the thunk f with the new backtrace.

  • parameter loc

    The location of the text (usually the code) to highlight.

val tracef : + ?loc:Span.t -> ('a, Stdlib.Format.formatter, unit, (unit -> 'b) -> 'b) Stdlib.format4 -> - 'a

tracef format ... f formats and records a message as a frame in the backtrace, and runs the thunk f with the new backtrace. Note that there should not be any literal control characters. See Diagnostic.text.

  • parameter loc

    The location of the text (usually the code) to highlight.

val trace_text : ?loc:Span.t -> Diagnostic.text -> (unit -> 'a) -> 'a

trace_text text f records the message text and runs the thunk f with the new backtrace.

  • parameter loc

    The location of the text (usually the code) to highlight.

val trace_message : Diagnostic.message -> (unit -> 'a) -> 'a

trace_message msg f records the message msg and runs the thunk f with the new backtrace.

Locations

val get_loc : unit -> Span.t option

get_loc() returns the current location.

val with_loc : Span.t option -> (unit -> 'a) -> 'a

with_loc loc f runs the thunk f with loc as the initial location loc. Note that with_loc None will clear the current location, while merge_loc None will keep it. See merge_loc.

val merge_loc : Span.t option -> (unit -> 'a) -> 'a

merge_loc loc f "merges" loc into the current location and runs the thunk f. By "merge", it means that if loc is None, then the current location is kept; otherwise, it is overwritten. Note that with_loc None will clear the current location, while merge_loc None will keep it. See with_loc.

Constructing Diagnostics

Functions in this section differ from the ones in Diagnostic (for example, Diagnostic.make) in that they fill out the current location, the current backtrace, and the severity automatically. (One can still overwrite them with optional arguments.)

val diagnostic : - ?severity:Diagnostic.severity -> - ?loc:Span.t -> - ?backtrace:Diagnostic.backtrace -> - ?additional_messages:Diagnostic.message list -> + 'a

tracef format ... f formats and records a message as a frame in the backtrace, and runs the thunk f with the new backtrace. Note that there should not be any literal control characters. See Diagnostic.text.

  • parameter loc

    The location of the text (usually the code) to highlight.

val trace_text : ?loc:Span.t -> Diagnostic.text -> (unit -> 'a) -> 'a

trace_text text f records the message text and runs the thunk f with the new backtrace.

  • parameter loc

    The location of the text (usually the code) to highlight.

val trace_message : Diagnostic.message -> (unit -> 'a) -> 'a

trace_message msg f records the message msg and runs the thunk f with the new backtrace.

Locations

val get_loc : unit -> Span.t option

get_loc() returns the current location.

val with_loc : Span.t option -> (unit -> 'a) -> 'a

with_loc loc f runs the thunk f with loc as the initial location loc. Note that with_loc None will clear the current location, while merge_loc None will keep it. See merge_loc.

val merge_loc : Span.t option -> (unit -> 'a) -> 'a

merge_loc loc f "merges" loc into the current location and runs the thunk f. By "merge", it means that if loc is None, then the current location is kept; otherwise, it is overwritten. Note that with_loc None will clear the current location, while merge_loc None will keep it. See with_loc.

Constructing Diagnostics

Functions in this section differ from the ones in Diagnostic (for example, Diagnostic.make) in that they fill out the current location, the current backtrace, and the severity automatically. (One can still overwrite them with optional arguments.)

val diagnostic : + ?severity:Diagnostic.severity -> + ?loc:Span.t -> + ?backtrace:Diagnostic.backtrace -> + ?additional_messages:Diagnostic.message list -> Code.t -> string -> Code.t Diagnostic.t

diagnostic code str constructs a diagnostic with the message str along with the backtrace frames recorded via tracef.

Example:

Logger.diagnostic `TypeError "This\nis\ntoo\nmuch."
  • parameter severity

    The severity (to overwrite the default severity inferred from the message code).

  • parameter loc

    The location of the text (usually the code) to highlight.

  • parameter backtrace

    The backtrace (to overwrite the accumulative frames up to this point).

  • parameter additional_messages

    Additional messages that part of the backtrace. For example, they can be bindings shadowed by the current one.

val diagnosticf : - ?severity:Diagnostic.severity -> - ?loc:Span.t -> - ?backtrace:Diagnostic.backtrace -> - ?additional_messages:Diagnostic.message list -> + ?severity:Diagnostic.severity -> + ?loc:Span.t -> + ?backtrace:Diagnostic.backtrace -> + ?additional_messages:Diagnostic.message list -> Code.t -> ('a, Stdlib.Format.formatter, unit, Code.t Diagnostic.t) Stdlib.format4 -> 'a

diagnosticf code format ... constructs a diagnostic along with the backtrace frames recorded via trace. Note that there should not be any literal control characters. See Diagnostic.text.

Example:

Logger.diagnosticf `TypeError "Term %a does not type check, or does it?" Syntax.pp tm
  • parameter severity

    The severity (to overwrite the default severity inferred from the message code).

  • parameter loc

    The location of the text (usually the code) to highlight.

  • parameter backtrace

    The backtrace (to overwrite the accumulative frames up to this point).

  • parameter additional_messages

    Additional messages that part of the backtrace. For example, they can be bindings shadowed by the current one.

val kdiagnosticf : - ?severity:Diagnostic.severity -> - ?loc:Span.t -> - ?backtrace:Diagnostic.backtrace -> - ?additional_messages:Diagnostic.message list -> + ?severity:Diagnostic.severity -> + ?loc:Span.t -> + ?backtrace:Diagnostic.backtrace -> + ?additional_messages:Diagnostic.message list -> (Code.t Diagnostic.t -> 'b) -> Code.t -> ('a, Stdlib.Format.formatter, unit, 'b) Stdlib.format4 -> 'a

kdiagnosticf kont code format ... is kont (diagnosticf code format ...). Note that there should not be any literal control characters. See Diagnostic.text.

  • parameter severity

    The severity (to overwrite the default severity inferred from the message code).

  • parameter loc

    The location of the text (usually the code) to highlight.

  • parameter backtrace

    The backtrace (to overwrite the accumulative frames up to this point).

  • parameter additional_messages

    Additional messages that part of the backtrace. For example, they can be bindings shadowed by the current one.

Algebraic Effects

val run : - ?init_loc:Span.t -> - ?init_backtrace:Diagnostic.backtrace -> - emit:(Code.t Diagnostic.t -> unit) -> - fatal:(Code.t Diagnostic.t -> 'a) -> + ?init_loc:Span.t -> + ?init_backtrace:Diagnostic.backtrace -> + emit:(Code.t Diagnostic.t -> unit) -> + fatal:(Code.t Diagnostic.t -> 'a) -> (unit -> 'a) -> 'a

run ~emit ~fatal f runs the thunk f, using emit to handle non-fatal diagnostics before continuing the computation (see emit and emitf), and fatal to handle fatal diagnostics that have aborted the computation (see fatal and fatalf).

  • parameter init_backtrace

    The initial backtrace to start with. The default value is the empty backtrace.

  • parameter emit

    The handler of non-fatal diagnostics.

  • parameter fatal

    The handler of fatal diagnostics.

val adopt : ('code Diagnostic.t -> Code.t Diagnostic.t) -> - (?init_loc:Span.t -> - ?init_backtrace:Diagnostic.backtrace -> - emit:('code Diagnostic.t -> unit) -> - fatal:('code Diagnostic.t -> 'a) -> + (?init_loc:Span.t -> + ?init_backtrace:Diagnostic.backtrace -> + emit:('code Diagnostic.t -> unit) -> + fatal:('code Diagnostic.t -> 'a) -> (unit -> 'a) -> 'a) -> (unit -> 'a) -> @@ -78,10 +78,10 @@ module LibLogger = Lib.Logger let _ = MainLogger.adopt (Diagnostic.map code_mapper) LibLogger.run @@ fun () -> ...
val try_with : - ?emit:(Code.t Diagnostic.t -> unit) -> - ?fatal:(Code.t Diagnostic.t -> 'a) -> + ?emit:(Code.t Diagnostic.t -> unit) -> + ?fatal:(Code.t Diagnostic.t -> 'a) -> (unit -> 'a) -> 'a

try_with ~emit ~fatal f runs the thunk f, using emit to intercept non-fatal diagnostics before continuing the computation (see emit and emitf), and fatal to intercept fatal diagnostics that have aborted the computation (see fatal and fatalf). The default interceptors re-emit or re-raise the intercepted diagnostics.

  • parameter emit

    The interceptor of non-fatal diagnostics. The default value is emit_diagnostic.

  • parameter fatal

    The interceptor of fatal diagnostics. The default value is fatal_diagnostic.

val register_printer : ([ `Trace | `Emit of Code.t Diagnostic.t | `Fatal of Code.t Diagnostic.t ] -> string option) -> - unit

register_printer p registers a printer p via Printexc.register_printer to convert unhandled internal effects and exceptions into strings for the OCaml runtime system to display. Ideally, all internal effects and exceptions should have been handled by run and there is no need to use this function, but when it is not the case, this function can be helpful for debugging. The functor Logger.Make always registers a simple printer to suggest using run, but you can register new ones to override it. The return type of the printer p should return Some s where s is the resulting string, or None if it chooses not to convert a particular effect or exception. The registered printers are tried in reverse order until one of them returns Some s for some s; that is, the last registered printer is tried first. Note that this function is a wrapper of Printexc.register_printer and all the registered printers (via this function or Printexc.register_printer) are put into the same list.

The input type of the printer p is a variant representation of all internal effects and exceptions used in this module:

  • `Trace corresponds to the effect triggered by trace; and
  • `Emit diag corresponds to the effect triggered by emit; and
  • `Fatal diag corresponds to the exception triggered by fatal.

Note: Diagnostic.string_of_text can be handy for converting a message into a string.

\ No newline at end of file + unit

register_printer p registers a printer p via Printexc.register_printer to convert unhandled internal effects and exceptions into strings for the OCaml runtime system to display. Ideally, all internal effects and exceptions should have been handled by run and there is no need to use this function, but when it is not the case, this function can be helpful for debugging. The functor Logger.Make always registers a simple printer to suggest using run, but you can register new ones to override it. The return type of the printer p should return Some s where s is the resulting string, or None if it chooses not to convert a particular effect or exception. The registered printers are tried in reverse order until one of them returns Some s for some s; that is, the last registered printer is tried first. Note that this function is a wrapper of Printexc.register_printer and all the registered printers (via this function or Printexc.register_printer) are put into the same list.

The input type of the printer p is a variant representation of all internal effects and exceptions used in this module:

  • `Trace corresponds to the effect triggered by trace; and
  • `Emit diag corresponds to the effect triggered by emit; and
  • `Fatal diag corresponds to the exception triggered by fatal.

Note: Diagnostic.string_of_text can be handy for converting a message into a string.

diff --git a/asai/Asai/Logger/index.html b/asai/Asai/Logger/index.html index 1741311..f459632 100644 --- a/asai/Asai/Logger/index.html +++ b/asai/Asai/Logger/index.html @@ -1,2 +1,2 @@ -Logger (asai.Asai.Logger)

Module Asai.Logger

Generating and handling diagnostics using algebraic effects.

module type S = sig ... end

The signature of a logger.

module Make (Code : Diagnostic.Code) : S with module Code := Code

The functor to generate a logger.

\ No newline at end of file +Logger (asai.Asai.Logger)

Module Asai.Logger

Generating and handling diagnostics using algebraic effects.

module type S = sig ... end

The signature of a logger.

module Make (Code : Diagnostic.Code) : S with module Code := Code

The functor to generate a logger.

diff --git a/asai/Asai/Logger/module-type-S/Code/index.html b/asai/Asai/Logger/module-type-S/Code/index.html index 788fe04..99d9bef 100644 --- a/asai/Asai/Logger/module-type-S/Code/index.html +++ b/asai/Asai/Logger/module-type-S/Code/index.html @@ -1,2 +1,2 @@ -Code (asai.Asai.Logger.S.Code)

Module S.Code

type t

The type of all message codes.

val default_severity : t -> Diagnostic.severity

The default severity of the code. The severity of a message is about whether the message is an error or a warning, etc. To clarify, it is about how serious the message is to the end user, not whether the program should stop or continue. The severity may be overwritten at the time of issuing a message to the end user.

val to_string : t -> string

A concise, ideally Google-able string representation of each message code. Detailed or long descriptions of code should be avoided. For example, E001 works better than type-checking error. The shorter, the better.

\ No newline at end of file +Code (asai.Asai.Logger.S.Code)

Module S.Code

type t

The type of all message codes.

val default_severity : t -> Diagnostic.severity

The default severity of the code. The severity of a message is about whether the message is an error or a warning, etc. To clarify, it is about how serious the message is to the end user, not whether the program should stop or continue. The severity may be overwritten at the time of issuing a message to the end user.

val to_string : t -> string

A concise, ideally Google-able string representation of each message code. Detailed or long descriptions of code should be avoided. For example, E001 works better than type-checking error. The shorter, the better.

diff --git a/asai/Asai/Logger/module-type-S/index.html b/asai/Asai/Logger/module-type-S/index.html index 1fb7f06..1181dae 100644 --- a/asai/Asai/Logger/module-type-S/index.html +++ b/asai/Asai/Logger/module-type-S/index.html @@ -1,70 +1,70 @@ -S (asai.Asai.Logger.S)

Module type Logger.S

The signature of a logger.

Sending Messages

val emit : - ?severity:Diagnostic.severity -> - ?loc:Span.t -> - ?backtrace:Diagnostic.backtrace -> - ?additional_messages:Diagnostic.message list -> +S (asai.Asai.Logger.S)

Module type Logger.S

The signature of a logger.

Sending Messages

val emit : + ?severity:Diagnostic.severity -> + ?loc:Span.t -> + ?backtrace:Diagnostic.backtrace -> + ?additional_messages:Diagnostic.message list -> Code.t -> string -> unit

emit code str emits a string and continues the computation.

Example:

Logger.emit `TypeError "This type is extremely unnatural:\nNat"
  • parameter severity

    The severity (to overwrite the default severity inferred from the message code).

  • parameter loc

    The location of the text (usually the code) to highlight.

  • parameter backtrace

    The backtrace (to overwrite the accumulative frames up to this point).

  • parameter additional_messages

    Additional messages that part of the backtrace. For example, they can be bindings shadowed by the current one.

val emitf : - ?severity:Diagnostic.severity -> - ?loc:Span.t -> - ?backtrace:Diagnostic.backtrace -> - ?additional_messages:Diagnostic.message list -> + ?severity:Diagnostic.severity -> + ?loc:Span.t -> + ?backtrace:Diagnostic.backtrace -> + ?additional_messages:Diagnostic.message list -> Code.t -> ('a, Stdlib.Format.formatter, unit, unit) Stdlib.format4 -> 'a

emitf code format ... formats and emits a message, and then continues the computation. Note that there should not be any literal control characters. See Diagnostic.text.

Example:

Logger.emitf `TypeError "Type %a is too ugly" Syntax.pp tp
  • parameter severity

    The severity (to overwrite the default severity inferred from the message code).

  • parameter loc

    The location of the text (usually the code) to highlight.

  • parameter backtrace

    The backtrace (to overwrite the accumulative frames up to this point).

  • parameter additional_messages

    Additional messages that part of the backtrace. For example, they can be bindings shadowed by the current one.

val emit_diagnostic : Code.t Diagnostic.t -> unit

Emit a diagnostic and continue the computation.

val fatal : - ?severity:Diagnostic.severity -> - ?loc:Span.t -> - ?backtrace:Diagnostic.backtrace -> - ?additional_messages:Diagnostic.message list -> + ?severity:Diagnostic.severity -> + ?loc:Span.t -> + ?backtrace:Diagnostic.backtrace -> + ?additional_messages:Diagnostic.message list -> Code.t -> string -> 'a

fatal code str aborts the current computation with the string str.

Example:

Logger.fatal `FileError "Forgot to feed the cat"
  • parameter severity

    The severity (to overwrite the default severity inferred from the message code).

  • parameter loc

    The location of the text (usually the code) to highlight.

  • parameter backtrace

    The backtrace (to overwrite the accumulative frames up to this point).

  • parameter additional_messages

    Additional messages that part of the backtrace. For example, they can be bindings shadowed by the current one.

val fatalf : - ?severity:Diagnostic.severity -> - ?loc:Span.t -> - ?backtrace:Diagnostic.backtrace -> - ?additional_messages:Diagnostic.message list -> + ?severity:Diagnostic.severity -> + ?loc:Span.t -> + ?backtrace:Diagnostic.backtrace -> + ?additional_messages:Diagnostic.message list -> Code.t -> ('a, Stdlib.Format.formatter, unit, 'b) Stdlib.format4 -> 'a

fatalf code format ... constructs a diagnostic and aborts the current computation with the diagnostic. Note that there should not be any literal control characters. See Diagnostic.text.

Example:

Logger.fatalf `FileError "Failed to write the password to %s" file_path
  • parameter severity

    The severity (to overwrite the default severity inferred from the message code).

  • parameter loc

    The location of the text (usually the code) to highlight.

  • parameter backtrace

    The backtrace (to overwrite the accumulative frames up to this point).

  • parameter additional_messages

    Additional messages that part of the backtrace. For example, they can be bindings shadowed by the current one.

val fatal_diagnostic : Code.t Diagnostic.t -> 'a

Abort the computation with a diagnostic.

Backtraces

val get_backtrace : unit -> Diagnostic.backtrace

get_backtrace() returns the current backtrace.

val with_backtrace : Diagnostic.backtrace -> (unit -> 'a) -> 'a

with_backtrace bt f runs the thunk f with bt as the initial backtrace.

Example:

(* running code with a fresh backtrace *)
-with_backtrace Emp @@ fun () -> ...
val trace : ?loc:Span.t -> string -> (unit -> 'a) -> 'a

trace str f records the string str and runs the thunk f with the new backtrace.

  • parameter loc

    The location of the text (usually the code) to highlight.

val tracef : - ?loc:Span.t -> +with_backtrace Emp @@ fun () -> ...
val trace : ?loc:Span.t -> string -> (unit -> 'a) -> 'a

trace str f records the string str and runs the thunk f with the new backtrace.

  • parameter loc

    The location of the text (usually the code) to highlight.

val tracef : + ?loc:Span.t -> ('a, Stdlib.Format.formatter, unit, (unit -> 'b) -> 'b) Stdlib.format4 -> - 'a

tracef format ... f formats and records a message as a frame in the backtrace, and runs the thunk f with the new backtrace. Note that there should not be any literal control characters. See Diagnostic.text.

  • parameter loc

    The location of the text (usually the code) to highlight.

val trace_text : ?loc:Span.t -> Diagnostic.text -> (unit -> 'a) -> 'a

trace_text text f records the message text and runs the thunk f with the new backtrace.

  • parameter loc

    The location of the text (usually the code) to highlight.

val trace_message : Diagnostic.message -> (unit -> 'a) -> 'a

trace_message msg f records the message msg and runs the thunk f with the new backtrace.

Locations

val get_loc : unit -> Span.t option

get_loc() returns the current location.

val with_loc : Span.t option -> (unit -> 'a) -> 'a

with_loc loc f runs the thunk f with loc as the initial location loc. Note that with_loc None will clear the current location, while merge_loc None will keep it. See merge_loc.

val merge_loc : Span.t option -> (unit -> 'a) -> 'a

merge_loc loc f "merges" loc into the current location and runs the thunk f. By "merge", it means that if loc is None, then the current location is kept; otherwise, it is overwritten. Note that with_loc None will clear the current location, while merge_loc None will keep it. See with_loc.

Constructing Diagnostics

Functions in this section differ from the ones in Diagnostic (for example, Diagnostic.make) in that they fill out the current location, the current backtrace, and the severity automatically. (One can still overwrite them with optional arguments.)

val diagnostic : - ?severity:Diagnostic.severity -> - ?loc:Span.t -> - ?backtrace:Diagnostic.backtrace -> - ?additional_messages:Diagnostic.message list -> + 'a

tracef format ... f formats and records a message as a frame in the backtrace, and runs the thunk f with the new backtrace. Note that there should not be any literal control characters. See Diagnostic.text.

  • parameter loc

    The location of the text (usually the code) to highlight.

val trace_text : ?loc:Span.t -> Diagnostic.text -> (unit -> 'a) -> 'a

trace_text text f records the message text and runs the thunk f with the new backtrace.

  • parameter loc

    The location of the text (usually the code) to highlight.

val trace_message : Diagnostic.message -> (unit -> 'a) -> 'a

trace_message msg f records the message msg and runs the thunk f with the new backtrace.

Locations

val get_loc : unit -> Span.t option

get_loc() returns the current location.

val with_loc : Span.t option -> (unit -> 'a) -> 'a

with_loc loc f runs the thunk f with loc as the initial location loc. Note that with_loc None will clear the current location, while merge_loc None will keep it. See merge_loc.

val merge_loc : Span.t option -> (unit -> 'a) -> 'a

merge_loc loc f "merges" loc into the current location and runs the thunk f. By "merge", it means that if loc is None, then the current location is kept; otherwise, it is overwritten. Note that with_loc None will clear the current location, while merge_loc None will keep it. See with_loc.

Constructing Diagnostics

Functions in this section differ from the ones in Diagnostic (for example, Diagnostic.make) in that they fill out the current location, the current backtrace, and the severity automatically. (One can still overwrite them with optional arguments.)

val diagnostic : + ?severity:Diagnostic.severity -> + ?loc:Span.t -> + ?backtrace:Diagnostic.backtrace -> + ?additional_messages:Diagnostic.message list -> Code.t -> string -> Code.t Diagnostic.t

diagnostic code str constructs a diagnostic with the message str along with the backtrace frames recorded via tracef.

Example:

Logger.diagnostic `TypeError "This\nis\ntoo\nmuch."
  • parameter severity

    The severity (to overwrite the default severity inferred from the message code).

  • parameter loc

    The location of the text (usually the code) to highlight.

  • parameter backtrace

    The backtrace (to overwrite the accumulative frames up to this point).

  • parameter additional_messages

    Additional messages that part of the backtrace. For example, they can be bindings shadowed by the current one.

val diagnosticf : - ?severity:Diagnostic.severity -> - ?loc:Span.t -> - ?backtrace:Diagnostic.backtrace -> - ?additional_messages:Diagnostic.message list -> + ?severity:Diagnostic.severity -> + ?loc:Span.t -> + ?backtrace:Diagnostic.backtrace -> + ?additional_messages:Diagnostic.message list -> Code.t -> ('a, Stdlib.Format.formatter, unit, Code.t Diagnostic.t) Stdlib.format4 -> 'a

diagnosticf code format ... constructs a diagnostic along with the backtrace frames recorded via trace. Note that there should not be any literal control characters. See Diagnostic.text.

Example:

Logger.diagnosticf `TypeError "Term %a does not type check, or does it?" Syntax.pp tm
  • parameter severity

    The severity (to overwrite the default severity inferred from the message code).

  • parameter loc

    The location of the text (usually the code) to highlight.

  • parameter backtrace

    The backtrace (to overwrite the accumulative frames up to this point).

  • parameter additional_messages

    Additional messages that part of the backtrace. For example, they can be bindings shadowed by the current one.

val kdiagnosticf : - ?severity:Diagnostic.severity -> - ?loc:Span.t -> - ?backtrace:Diagnostic.backtrace -> - ?additional_messages:Diagnostic.message list -> + ?severity:Diagnostic.severity -> + ?loc:Span.t -> + ?backtrace:Diagnostic.backtrace -> + ?additional_messages:Diagnostic.message list -> (Code.t Diagnostic.t -> 'b) -> Code.t -> ('a, Stdlib.Format.formatter, unit, 'b) Stdlib.format4 -> 'a

kdiagnosticf kont code format ... is kont (diagnosticf code format ...). Note that there should not be any literal control characters. See Diagnostic.text.

  • parameter severity

    The severity (to overwrite the default severity inferred from the message code).

  • parameter loc

    The location of the text (usually the code) to highlight.

  • parameter backtrace

    The backtrace (to overwrite the accumulative frames up to this point).

  • parameter additional_messages

    Additional messages that part of the backtrace. For example, they can be bindings shadowed by the current one.

Algebraic Effects

val run : - ?init_loc:Span.t -> - ?init_backtrace:Diagnostic.backtrace -> - emit:(Code.t Diagnostic.t -> unit) -> - fatal:(Code.t Diagnostic.t -> 'a) -> + ?init_loc:Span.t -> + ?init_backtrace:Diagnostic.backtrace -> + emit:(Code.t Diagnostic.t -> unit) -> + fatal:(Code.t Diagnostic.t -> 'a) -> (unit -> 'a) -> 'a

run ~emit ~fatal f runs the thunk f, using emit to handle non-fatal diagnostics before continuing the computation (see emit and emitf), and fatal to handle fatal diagnostics that have aborted the computation (see fatal and fatalf).

  • parameter init_backtrace

    The initial backtrace to start with. The default value is the empty backtrace.

  • parameter emit

    The handler of non-fatal diagnostics.

  • parameter fatal

    The handler of fatal diagnostics.

val adopt : ('code Diagnostic.t -> Code.t Diagnostic.t) -> - (?init_loc:Span.t -> - ?init_backtrace:Diagnostic.backtrace -> - emit:('code Diagnostic.t -> unit) -> - fatal:('code Diagnostic.t -> 'a) -> + (?init_loc:Span.t -> + ?init_backtrace:Diagnostic.backtrace -> + emit:('code Diagnostic.t -> unit) -> + fatal:('code Diagnostic.t -> 'a) -> (unit -> 'a) -> 'a) -> (unit -> 'a) -> @@ -78,10 +78,10 @@ module LibLogger = Lib.Logger let _ = MainLogger.adopt (Diagnostic.map code_mapper) LibLogger.run @@ fun () -> ...
val try_with : - ?emit:(Code.t Diagnostic.t -> unit) -> - ?fatal:(Code.t Diagnostic.t -> 'a) -> + ?emit:(Code.t Diagnostic.t -> unit) -> + ?fatal:(Code.t Diagnostic.t -> 'a) -> (unit -> 'a) -> 'a

try_with ~emit ~fatal f runs the thunk f, using emit to intercept non-fatal diagnostics before continuing the computation (see emit and emitf), and fatal to intercept fatal diagnostics that have aborted the computation (see fatal and fatalf). The default interceptors re-emit or re-raise the intercepted diagnostics.

  • parameter emit

    The interceptor of non-fatal diagnostics. The default value is emit_diagnostic.

  • parameter fatal

    The interceptor of fatal diagnostics. The default value is fatal_diagnostic.

val register_printer : ([ `Trace | `Emit of Code.t Diagnostic.t | `Fatal of Code.t Diagnostic.t ] -> string option) -> - unit

register_printer p registers a printer p via Printexc.register_printer to convert unhandled internal effects and exceptions into strings for the OCaml runtime system to display. Ideally, all internal effects and exceptions should have been handled by run and there is no need to use this function, but when it is not the case, this function can be helpful for debugging. The functor Logger.Make always registers a simple printer to suggest using run, but you can register new ones to override it. The return type of the printer p should return Some s where s is the resulting string, or None if it chooses not to convert a particular effect or exception. The registered printers are tried in reverse order until one of them returns Some s for some s; that is, the last registered printer is tried first. Note that this function is a wrapper of Printexc.register_printer and all the registered printers (via this function or Printexc.register_printer) are put into the same list.

The input type of the printer p is a variant representation of all internal effects and exceptions used in this module:

  • `Trace corresponds to the effect triggered by trace; and
  • `Emit diag corresponds to the effect triggered by emit; and
  • `Fatal diag corresponds to the exception triggered by fatal.

Note: Diagnostic.string_of_text can be handy for converting a message into a string.

\ No newline at end of file + unit

register_printer p registers a printer p via Printexc.register_printer to convert unhandled internal effects and exceptions into strings for the OCaml runtime system to display. Ideally, all internal effects and exceptions should have been handled by run and there is no need to use this function, but when it is not the case, this function can be helpful for debugging. The functor Logger.Make always registers a simple printer to suggest using run, but you can register new ones to override it. The return type of the printer p should return Some s where s is the resulting string, or None if it chooses not to convert a particular effect or exception. The registered printers are tried in reverse order until one of them returns Some s for some s; that is, the last registered printer is tried first. Note that this function is a wrapper of Printexc.register_printer and all the registered printers (via this function or Printexc.register_printer) are put into the same list.

The input type of the printer p is a variant representation of all internal effects and exceptions used in this module:

  • `Trace corresponds to the effect triggered by trace; and
  • `Emit diag corresponds to the effect triggered by emit; and
  • `Fatal diag corresponds to the exception triggered by fatal.

Note: Diagnostic.string_of_text can be handy for converting a message into a string.

diff --git a/asai/Asai/Lsp/Make/argument-1-Code/index.html b/asai/Asai/Lsp/Make/argument-1-Code/index.html index a386b9d..4ccd9a9 100644 --- a/asai/Asai/Lsp/Make/argument-1-Code/index.html +++ b/asai/Asai/Lsp/Make/argument-1-Code/index.html @@ -1,2 +1,2 @@ -Code (asai.Asai.Lsp.Make.Code)

Parameter Make.Code

type t

The type of all message codes.

val default_severity : t -> Diagnostic.severity

The default severity of the code. The severity of a message is about whether the message is an error or a warning, etc. To clarify, it is about how serious the message is to the end user, not whether the program should stop or continue. The severity may be overwritten at the time of issuing a message to the end user.

val to_string : t -> string

A concise, ideally Google-able string representation of each message code. Detailed or long descriptions of code should be avoided. For example, E001 works better than type-checking error. The shorter, the better.

\ No newline at end of file +Code (asai.Asai.Lsp.Make.Code)

Parameter Make.Code

type t

The type of all message codes.

val default_severity : t -> Diagnostic.severity

The default severity of the code. The severity of a message is about whether the message is an error or a warning, etc. To clarify, it is about how serious the message is to the end user, not whether the program should stop or continue. The severity may be overwritten at the time of issuing a message to the end user.

val to_string : t -> string

A concise, ideally Google-able string representation of each message code. Detailed or long descriptions of code should be avoided. For example, E001 works better than type-checking error. The shorter, the better.

diff --git a/asai/Asai/Lsp/Make/index.html b/asai/Asai/Lsp/Make/index.html index 1437b2b..996d6d1 100644 --- a/asai/Asai/Lsp/Make/index.html +++ b/asai/Asai/Lsp/Make/index.html @@ -1,6 +1,6 @@ -Make (asai.Asai.Lsp.Make)

Module Lsp.Make

This module provides a rudimentary and incomplete implementation of the LSP protocol.

Note: many features are missing and it does not handle positionEncoding.

Parameters

Signature

val start : - source:string option -> - init:(root:string option -> unit) -> - load_file:(display:(Code.t Diagnostic.t -> unit) -> string -> unit) -> - unit

run ~init ~load_file starts the LSP server with the two callbacks init and load_file.

  • parameter source

    The source of a LSP diagnostic, that is, a "human-readable string describing the source of this diagnostic."

  • parameter init

    The callback to initiate the loading of a workspace. The root parameter is the workspace

  • parameter load_file

    The callback to load the file.

\ No newline at end of file +Make (asai.Asai.Lsp.Make)

Module Lsp.Make

This module provides a rudimentary and incomplete implementation of the LSP protocol.

Note: many features are missing and it does not handle positionEncoding.

Parameters

Signature

val start : + source:string option -> + init:(root:string option -> unit) -> + load_file:(display:(Code.t Diagnostic.t -> unit) -> string -> unit) -> + unit

run ~init ~load_file starts the LSP server with the two callbacks init and load_file.

  • parameter source

    The source of a LSP diagnostic, that is, a "human-readable string describing the source of this diagnostic."

  • parameter init

    The callback to initiate the loading of a workspace. The root parameter is the workspace

  • parameter load_file

    The callback to load the file.

diff --git a/asai/Asai/Lsp/index.html b/asai/Asai/Lsp/index.html index 4383566..bff2cae 100644 --- a/asai/Asai/Lsp/index.html +++ b/asai/Asai/Lsp/index.html @@ -1,2 +1,2 @@ -Lsp (asai.Asai.Lsp)

Module Asai.Lsp

An LSP (Language Service Protocol) server for asai

Language Service Protocol

module Make (Code : Diagnostic.Code) : sig ... end

This module provides a rudimentary and incomplete implementation of the LSP protocol.

\ No newline at end of file +Lsp (asai.Asai.Lsp)

Module Asai.Lsp

An LSP (Language Service Protocol) server for asai

Language Service Protocol

module Make (Code : Diagnostic.Code) : sig ... end

This module provides a rudimentary and incomplete implementation of the LSP protocol.

diff --git a/asai/Asai/Span/index.html b/asai/Asai/Span/index.html index 0b00980..ba95c02 100644 --- a/asai/Asai/Span/index.html +++ b/asai/Asai/Span/index.html @@ -1,8 +1,8 @@ -Span (asai.Asai.Span)

Module Asai.Span

Locations and spans.

Types

type position = {
  1. file_path : string;
    (*

    The absolute file path of the file that contains the position.

    *)
  2. offset : int;
    (*

    The 0-indexed byte offset of the position relative to the beginning of the file.

    *)
  3. start_of_line : int;
    (*

    The 0-indexed byte offset pointing to the start of the line that contains the position.

    *)
  4. line_num : int;
    (*

    The 1-indexed line number of the line that contains the position.

    *)
}

The type of positions; this is isomorphic to Lexing.position, but with arguably better field names.

type t

The abstract type of spans.

type 'a located = {
  1. loc : t option;
  2. value : 'a;
}

An auxiliary type to package data with an optional span.

Spans

val make : (position * position) -> t

make (beginning, ending) builds the span [begining, ending) (not including the byte at the ending position) from a pair of positions beginning and ending.

  • raises Invalid_argument

    if the positions do not share the same file path or if end_ comes before begin_. (It is okay if end_ equals to begin_, which means the span is empty.) The comparison of file paths is done by String.equal without any path normalization.

val split : t -> position * position

split span returning the pair of the beginning and ending positions of span. It is the right inverse of make.

val file_path : t -> string

file_path span returns the file path associated with span.

val begin_line_num : t -> int

begin_line_num span returns the 1-indexed line number of the beginning position.

val end_line_num : t -> int

end_line_num span returns the 1-indexed line number of the ending position.

val begin_offset : t -> int

begin_offset span returns the 0-indexed offset of the (inclusive) beginning position.

val end_offset : t -> int

end_offset span returns the 0-indexed offset of the (exclusive) ending position.

val locate_opt : t option -> 'a -> 'a located

locate_opt sp v is {loc = sp; value = v}.

val locate : t -> 'a -> 'a located

locate sp v is {loc = Some sp; value = v}.

Support of Lexing

val of_lex_position : Stdlib.Lexing.position -> position

of_lex_position pos converts an OCaml lexer position pos of type Lexing.position into a position. The input pos must be byte-indexed. (Therefore, the OCaml tool ocamllex is compatible, but the OCaml library sedlex is not because it uses Unicode code points.)

val of_lex_span : (Stdlib.Lexing.position * Stdlib.Lexing.position) -> t

of_lex_span (begining, ending) takes a pair of OCaml lexer positions and creates a span. It is make (of_lex_position begining, of_lex_position ending).

val of_lexbuf : Stdlib.Lexing.lexbuf -> t

of_lexbuf lexbuf constructs a span from the current lexeme that lexbuf points to. It is of_lex_span (Lexing.lexeme_start_p lexbuf, Lexing.lexeme_end_p lexbuf).

val locate_lex : +Span (asai.Asai.Span)

Module Asai.Span

Locations and spans.

Types

type position = {
  1. file_path : string;
    (*

    The absolute file path of the file that contains the position.

    *)
  2. offset : int;
    (*

    The 0-indexed byte offset of the position relative to the beginning of the file.

    *)
  3. start_of_line : int;
    (*

    The 0-indexed byte offset pointing to the start of the line that contains the position.

    *)
  4. line_num : int;
    (*

    The 1-indexed line number of the line that contains the position.

    *)
}

The type of positions; this is isomorphic to Lexing.position, but with arguably better field names.

type t

The abstract type of spans.

type 'a located = {
  1. loc : t option;
  2. value : 'a;
}

An auxiliary type to package data with an optional span.

Spans

val make : (position * position) -> t

make (beginning, ending) builds the span [begining, ending) (not including the byte at the ending position) from a pair of positions beginning and ending.

  • raises Invalid_argument

    if the positions do not share the same file path or if end_ comes before begin_. (It is okay if end_ equals to begin_, which means the span is empty.) The comparison of file paths is done by String.equal without any path normalization.

val split : t -> position * position

split span returning the pair of the beginning and ending positions of span. It is the right inverse of make.

val file_path : t -> string

file_path span returns the file path associated with span.

val begin_line_num : t -> int

begin_line_num span returns the 1-indexed line number of the beginning position.

val end_line_num : t -> int

end_line_num span returns the 1-indexed line number of the ending position.

val begin_offset : t -> int

begin_offset span returns the 0-indexed offset of the (inclusive) beginning position.

val end_offset : t -> int

end_offset span returns the 0-indexed offset of the (exclusive) ending position.

val locate_opt : t option -> 'a -> 'a located

locate_opt sp v is {loc = sp; value = v}.

val locate : t -> 'a -> 'a located

locate sp v is {loc = Some sp; value = v}.

Support of Lexing

val of_lex_position : Stdlib.Lexing.position -> position

of_lex_position pos converts an OCaml lexer position pos of type Lexing.position into a position. The input pos must be byte-indexed. (Therefore, the OCaml tool ocamllex is compatible, but the OCaml library sedlex is not because it uses Unicode code points.)

val of_lex_span : (Stdlib.Lexing.position * Stdlib.Lexing.position) -> t

of_lex_span (begining, ending) takes a pair of OCaml lexer positions and creates a span. It is make (of_lex_position begining, of_lex_position ending).

val of_lexbuf : Stdlib.Lexing.lexbuf -> t

of_lexbuf lexbuf constructs a span from the current lexeme that lexbuf points to. It is of_lex_span (Lexing.lexeme_start_p lexbuf, Lexing.lexeme_end_p lexbuf).

val locate_lex : (Stdlib.Lexing.position * Stdlib.Lexing.position) -> 'a -> 'a located

locate_lex ps v is a helper function to create a value annotated with a span. It is locate (Some (of_lex_span ps)) v and is designed to work with the OCaml parser generator Menhir. You can add the following code to your Menhir grammar to generate annotated data:

%inline
 locate(X):
   | e = X
-    { Asai.Span.locate_lex $loc e }
\ No newline at end of file + { Asai.Span.locate_lex $loc e }
diff --git a/asai/Asai/Tty/Make/argument-1-Code/index.html b/asai/Asai/Tty/Make/argument-1-Code/index.html index 6a76532..b2c54f9 100644 --- a/asai/Asai/Tty/Make/argument-1-Code/index.html +++ b/asai/Asai/Tty/Make/argument-1-Code/index.html @@ -1,2 +1,2 @@ -Code (asai.Asai.Tty.Make.Code)

Parameter Make.Code

type t

The type of all message codes.

val default_severity : t -> Diagnostic.severity

The default severity of the code. The severity of a message is about whether the message is an error or a warning, etc. To clarify, it is about how serious the message is to the end user, not whether the program should stop or continue. The severity may be overwritten at the time of issuing a message to the end user.

val to_string : t -> string

A concise, ideally Google-able string representation of each message code. Detailed or long descriptions of code should be avoided. For example, E001 works better than type-checking error. The shorter, the better.

\ No newline at end of file +Code (asai.Asai.Tty.Make.Code)

Parameter Make.Code

type t

The type of all message codes.

val default_severity : t -> Diagnostic.severity

The default severity of the code. The severity of a message is about whether the message is an error or a warning, etc. To clarify, it is about how serious the message is to the end user, not whether the program should stop or continue. The severity may be overwritten at the time of issuing a message to the end user.

val to_string : t -> string

A concise, ideally Google-able string representation of each message code. Detailed or long descriptions of code should be avoided. For example, E001 works better than type-checking error. The shorter, the better.

diff --git a/asai/Asai/Tty/Make/index.html b/asai/Asai/Tty/Make/index.html index 9349df5..4b269e9 100644 --- a/asai/Asai/Tty/Make/index.html +++ b/asai/Asai/Tty/Make/index.html @@ -1,5 +1,5 @@ -Make (asai.Asai.Tty.Make)

Module Tty.Make

This module provides functions to display or interact with diagnostics in UNIX terminals. A message will look like this:

    🭁 examples/stlc/example.lambda
+Make (asai.Asai.Tty.Make)

Module Tty.Make

This module provides functions to display or interact with diagnostics in UNIX terminals. A message will look like this:

    🭁 examples/stlc/example.lambda
     │
   1 │ (check (λ ä (λ 123
   2 │   sdaf)) (→ ℕ (→ ℕ ℕ)))
@@ -9,10 +9,10 @@
     ┷
  [E002] Why am I checking the term (→ ℕ (→ ℕ ℕ)),
         which looks amazing?

Parameters

Signature

val display : - ?show_backtrace:bool -> - ?line_breaking:[ `Unicode | `Traditional ] -> - ?block_splitting_threshold:int -> - ?tab_size:int -> + ?show_backtrace:bool -> + ?line_breaking:[ `Unicode | `Traditional ] -> + ?block_splitting_threshold:int -> + ?tab_size:int -> Code.t Diagnostic.t -> unit

display d prints the diagnostic d to the standard output, using terminal control characters for formatting. A message will look like this:

    🭁 examples/stlc/example1.lambda
     │
@@ -31,9 +31,9 @@
     │
   8 │ assert (asai is cool)
     ┷
- [E002] Why am I checking the term (→ ℕ (→ ℕ ℕ))?
  • parameter show_backtrace

    Whether the backtrace should be shown. The default is false.

  • parameter line_breaking

    The algorithm to recognize (hard) line breaks. The `Unicode algorithm recognizes all Unicode character sequences in Unicode 15.0.0 Table 5-1 as line breaks. The `Traditional algorithm only recognizes U+000A (LF), U+000D (CR), and U+000D U+000A (CRLF) as line breaks. The default is the `Traditional algorithm.

  • parameter block_splitting_threshold

    The maximum number of consecutive, non-highlighted lines allowed in a block. The function will try to minimize the number of blocks, as long as no block has too many consecutive, non-highlighted lines. A higher threshold will lead to fewer blocks. When the threshold is zero, it means no block can contain any non-highlighted line. The default value is 5.

  • parameter tab_size

    The number of spaces that should be used to replace a horizontal tab. Note that a horizontal tab is always expanded to the same number of spaces. The result should still be visually appealing as long as horizontal tabs are only used at the beginning of lines. The default value is 8.

  • raises Invalid_argument

    if tab_size < 0.

val interactive_trace : - ?line_breaking:[ `Unicode | `Traditional ] -> - ?block_splitting_threshold:int -> - ?tab_size:int -> + [E002] Why am I checking the term (→ ℕ (→ ℕ ℕ))?
val interactive_trace : + ?line_breaking:[ `Unicode | `Traditional ] -> + ?block_splitting_threshold:int -> + ?tab_size:int -> Code.t Diagnostic.t -> - unit

interactive_trace d drops the user in a small interactive terminal app where they can cycle through the message provided in d and its backtrace.

  • parameter line_breaking

    The algorithm to recognize (hard) line breaks. The `Unicode algorithm recognizes all Unicode character sequences in Unicode 15.0.0 Table 5-1 as line breaks. The `Traditional algorithm only recognizes U+000A (LF), U+000D (CR), and U+000D U+000A (CRLF) as line breaks. The default is the `Traditional algorithm.

  • parameter block_splitting_threshold

    The maximum number of consecutive, non-highlighted lines allowed in a block. The function will try to minimize the number of blocks, as long as no block has too many consecutive, non-highlighted lines. A higher threshold will lead to fewer blocks. When the threshold is zero, it means no block can contain any non-highlighted line. The default value is 5.

  • parameter tab_size

    The number of spaces that should be used to replace a horizontal tab. Note that a horizontal tab is always expanded to the same number of spaces. The result should still be visually appealing as long as horizontal tabs are only used at the beginning of lines. The default value is 8.

  • raises Invalid_argument

    if tab_size < 0.

\ No newline at end of file + unit

interactive_trace d drops the user in a small interactive terminal app where they can cycle through the message provided in d and its backtrace.

  • parameter line_breaking

    The algorithm to recognize (hard) line breaks. The `Unicode algorithm recognizes all Unicode character sequences in Unicode 15.0.0 Table 5-1 as line breaks. The `Traditional algorithm only recognizes U+000A (LF), U+000D (CR), and U+000D U+000A (CRLF) as line breaks. The default is the `Traditional algorithm.

  • parameter block_splitting_threshold

    The maximum number of consecutive, non-highlighted lines allowed in a block. The function will try to minimize the number of blocks, as long as no block has too many consecutive, non-highlighted lines. A higher threshold will lead to fewer blocks. When the threshold is zero, it means no block can contain any non-highlighted line. The default value is 5.

  • parameter tab_size

    The number of spaces that should be used to replace a horizontal tab. Note that a horizontal tab is always expanded to the same number of spaces. The result should still be visually appealing as long as horizontal tabs are only used at the beginning of lines. The default value is 8.

  • raises Invalid_argument

    if tab_size < 0.

diff --git a/asai/Asai/Tty/index.html b/asai/Asai/Tty/index.html index 61428d4..f607129 100644 --- a/asai/Asai/Tty/index.html +++ b/asai/Asai/Tty/index.html @@ -1,2 +1,2 @@ -Tty (asai.Asai.Tty)

Module Asai.Tty

Diagnostic display for UNIX terminals.

Display

  • alert unstable The TTY backend will likely change significantly in the future to account for more features.
module Make (Code : Diagnostic.Code) : sig ... end

This module provides functions to display or interact with diagnostics in UNIX terminals. A message will look like this:

\ No newline at end of file +Tty (asai.Asai.Tty)

Module Asai.Tty

Diagnostic display for UNIX terminals.

Display

  • alert unstable The TTY backend will likely change significantly in the future to account for more features.
module Make (Code : Diagnostic.Code) : sig ... end

This module provides functions to display or interact with diagnostics in UNIX terminals. A message will look like this:

diff --git a/asai/Asai/index.html b/asai/Asai/index.html index 2527f56..d4c9e19 100644 --- a/asai/Asai/index.html +++ b/asai/Asai/index.html @@ -1,2 +1,2 @@ -Asai (asai.Asai)

Module Asai

Compiler diagnostics

A diagnostic is a message for the end user, for example a compiler warning or error.

Core API

module Span : sig ... end

Locations and spans.

module Diagnostic : sig ... end

The definition of diagnostics and some utility functions.

module Logger : sig ... end

Generating and handling diagnostics using algebraic effects.

Experimental Backends

module Tty : sig ... end

Diagnostic display for UNIX terminals.

module Lsp : sig ... end

An LSP (Language Service Protocol) server for asai

module GitHub : sig ... end

GitHub Actions workflow commands.

Internals

module Explication : sig ... end

The definition of highlighted text suitable for rendering. You probably do not need this module unless you want to create your own backend.

module Explicator : sig ... end

Turning location information into highlighted text suitable for rendering. You probably do not need this module unless you want to create your own backend.

module FileReader : sig ... end

An implementation of Explicator.Reader using memory-mapped file I/O. You probably do not need this module unless you want to create your own backend.

\ No newline at end of file +Asai (asai.Asai)

Module Asai

Compiler diagnostics

A diagnostic is a message for the end user, for example a compiler warning or error.

Core API

module Span : sig ... end

Locations and spans.

module Diagnostic : sig ... end

The definition of diagnostics and some utility functions.

module Logger : sig ... end

Generating and handling diagnostics using algebraic effects.

Experimental Backends

module Tty : sig ... end

Diagnostic display for UNIX terminals.

module Lsp : sig ... end

An LSP (Language Service Protocol) server for asai

module GitHub : sig ... end

GitHub Actions workflow commands.

Internals

module Explication : sig ... end

The definition of highlighted text suitable for rendering. You probably do not need this module unless you want to create your own backend.

module Explicator : sig ... end

Turning location information into highlighted text suitable for rendering. You probably do not need this module unless you want to create your own backend.

module FileReader : sig ... end

An implementation of Explicator.Reader using memory-mapped file I/O. You probably do not need this module unless you want to create your own backend.

diff --git a/asai/design.html b/asai/design.html index ae9f645..7571e98 100644 --- a/asai/design.html +++ b/asai/design.html @@ -1,2 +1,2 @@ -design (asai.design)

Design Principles

Five Independent Parameters of a Diagnostic

In addition to the main message, the API should allow implementers to easily specify the following five factors of a diagnostic, and it should be possible to specify them independently.

  1. Whether the program terminates after sending the message. This is indicated by the choice between emit (for non-fatal messages) and fatal (for fatal ones).
  2. A message code with a succinct Google-able representation, for example V0003. A succinct representation is useful for an end user to report a bug or ask for help.
  3. How seriously end users should take the message. Is it a warning, an error, or just a hint? See the type severity for available classifications. In practice, messages with the same message code tend to have the same severity, and thus our API requires an implementer to specify a default severity for each message code. While this seems to violate the independence constraint, our API allows overriding the default severity at each call of emit or fatal.
  4. A stack backtrace. There should be a straightforward way to push new stack frames. Our implementation is trace.
  5. Additional messages. It should be possible to attach any numbers of additional related messages. Currently, emit and fatal are taking .

Compositionality: Using Libraries that Use asai

It should be easy for an application to use other libraries who themselves use asai. Our current implementation allows an application to adopt messages from a library.

Unicode Art

There is a long history of using ASCII printable characters and ANSI escape sequences, and recently also non-ASCII Unicode characters, to draw pictures on terminals. To display compiler diagnostics, this technique has been used to assemble line numbers, code from end users, code highlighting, and other pieces of information in a visually pleasing way. Non-ASCII Unicode characters (from implementers or from end users) greatly expand the vocabulary of ASCII art, and we will call the new art form Unicode art to signify the use of non-ASCII characters.

No Column Numbers, Ever

The arrival of non-ASCII Unicode characters imposes new challenges as their visual widths are unpredictable without knowing the exact terminal (or terminal emulator), the exact font, etc. Unicode emoji sequences might be one of the most challenging cases: a pirate flag (🏴‍☠️) may be shown as a single emoji flag on supported platforms but as a sequence with a black flag (🏴) and a skull (☠️) on other platforms. This means the visual width of the pirate flag is unpredictable. (See Unicode Emoji Section 2.2.) The rainbow flag (🏳️‍🌈), skin tones, and many other emoji sequences have the same issue. Other less chaotic but still challenging cases include characters whose East Asian width is Ambiguous. These challenges bear some similarity with the unpredictability of the visual width of horizontal tabulations, but in a much wilder way.

Note: "Unicode characters" are not really defined in the Unicode standard, and here they mean Unicode scalar values, that is, all Unicode code points except the surrogate code points for UTF-16 to represent all scalar values. Although the word "character" has many incompatible meanings and usages, we decided to call scalar values "Unicode characters" anyway because (1) most people are not familiar with the official term "scalar values" and (2) scalar values are the only stable primitive unit one can work with in a programming language.

It is thus wise to think twice before using emoji sequences and other tricky characters in Unicode art. To quantify the degree to which a Unicode art can remain visually pleasing on different platforms, we specify the following four levels of stability. Note that if implementers decide to integrate content from end users into their Unicode art, the end users should have the freedom to include arbitrary emoji sequences and tricky characters in their content. The final Unicode art must remain visually pleasing as defined by the stability levels for any reasonable user content.

  • Level 0 (the least stable): Stability under the assumption that every Unicode character occupies exactly the same visual width. Thankfully, programs meeting only this level are mostly considered outdated.
  • Level 1: Stability under the assumption each Unicode string visually occupies a multiple of some fixed width, where the multiplier is determined by heuristics (such as various implementations of wcwidth and wcswidth). These heuristics are created to help programmers handle more characters, in particular CJK characters, without dramatically changing the code. They however do not solve the core problem (that is, visual width is fundamentally ill-defined) and they often could not handle tricky cases such as emoji sequences. Many compilers are at this level.
  • Level 2a: Stability under very limited assumptions on which characters should have the same widths. For example, if a Unicode art only assumes Unicode box-drawing characters are of the same visual width (which is the case in all conceivable situations), then its stability is at this level. However, the phrase "very limited" is somewhat subjective, and thus we present a more precise version below.
  • Level 2b: Stability under only theses assumptions:

    Level 2b is making explicit what Level 2a means; we might update the details of Level 2b later to better match our understanding of Level 2a. Collectively, Levels 2a and 2b are called "Level 2".

  • Level 3 (the most stable): Stability under only one assumption that equivalent (extended) grapheme clusters have the same visual width (the last assumption of Level 2b). This means that the Unicode art will remain visually pleasing in almost all situations. It can even be rendered with a variable-width font.

Unlike most implementations, which are at Level 1, our terminal backend strives to achieve Level 2. That means we must not make any assumption about the visual width of end users' code and must abandon the idea of column numbers. Our terminal backend never uses column numbers and we consider that as a significant improvement. On the other hand, Level 3 seems to be too restricted for compiler diagnostics because we cannot show line numbers along with the end users' code. (We cannot assume the numbers "10" and "99" will have the same visual width at Level 3.)

Note: a fixed-width font with enough glyphs that covers many Unicode characters is often technically duospaced, not monospaced, because many CJK characters would occupy a double character visual width. Thus, we do not use the terminology "monospaced".

No Support of Bidirectional Text Yet

Proper support of bidirectional text will benefit many potential end users, but unfortunately, we currently do not have the capacity to implement it. The general support of bidirectional text in most system libraries and tools is poor, and without dedicated effort, it is hard to verify whether we manage to avoid common pitfalls.

On a related note, Unicode Source Code Handling suggests that source code should be segmented into atoms and their display order should remain the same to maintain the lexical structure. (This deviation is allowed by the Unicode Bidirectional Algorithm.) Our current implementation cannot handle this because it has no access to such structural information of the content from end users.

Raw Bytes as Positions

All positions should be byte-oriented. We believe other popular alternatives proposals are worse:

  1. Unicode characters (Unicode scalar values): This is a reasonable and technically well-defined choice. The problem is that it may take linear time to count the number of characters from raw bytes without a clever data structure (unless we are using UTF-32), and they often do not match what end users perceive as "characters". In other words, it takes more time to compute and may invite misconceptions about Unicode characters.
  2. Code units used in UTF-16: This is somewhat similar to Unicode characters, but with quirks from UTF-16: a Unicode scalar value above U+FFFF (such as 😎) will require two code units to form a surrogate pair. Therefore, it is arguably worse than just using Unicode characters. This scheme was unfortunately chosen by the Language Service Protocol (LSP) as the default unit, and until LSP version 3.17 was the only choice. The developers of the protocol made this decision probably because Visual Studio Code was written in JavaScript (and TypeScript), whose strings use UTF-16 encoding.
  3. (Extended) grapheme clusters or user-perceived characters. The notion of grapheme clusters can help segment a Unicode text for end users to edit or select part of it in an "intuitive" way. It is not trivial to implement the segmentation algorithm (see the OCaml library uuseg) and the default rules can (and maybe should) be overriden for each application. The complexity and external dependency of grapheme clusters make it an unreliable unit for specifying positions. It also takes at least linear time to count the number of grapheme clusters from raw bytes.
  4. Column numbers, the visual width of a string in display. As analyzed in the above section, this is the most ill-defined unit of all, and a heuristic that can give passable results in most cases still takes linear time.

Know Bug: Our LSP prototype does not handle positionEncoding yet, and because the default unit in LSP is based on UTF-16 (see above), an LSP client may be confused about the byte-oriented ranges returned by this library. A proper LSP implementation should negotiate with the client to determine how to represent column positions (and our current prototype does not). On the other hand, it can be tricky to negotiate with the client to use raw bytes because there is not an official predefined encoding scheme for raw bytes yet.

\ No newline at end of file +design (asai.design)

Design Principles

Five Independent Parameters of a Diagnostic

In addition to the main message, the API should allow implementers to easily specify the following five factors of a diagnostic, and it should be possible to specify them independently.

  1. Whether the program terminates after sending the message. This is indicated by the choice between emit (for non-fatal messages) and fatal (for fatal ones).
  2. A message code with a succinct Google-able representation, for example V0003. A succinct representation is useful for an end user to report a bug or ask for help.
  3. How seriously end users should take the message. Is it a warning, an error, or just a hint? See the type severity for available classifications. In practice, messages with the same message code tend to have the same severity, and thus our API requires an implementer to specify a default severity for each message code. While this seems to violate the independence constraint, our API allows overriding the default severity at each call of emit or fatal.
  4. A stack backtrace. There should be a straightforward way to push new stack frames. Our implementation is trace.
  5. Additional messages. It should be possible to attach any numbers of additional related messages. Currently, emit and fatal are taking .

Compositionality: Using Libraries that Use asai

It should be easy for an application to use other libraries who themselves use asai. Our current implementation allows an application to adopt messages from a library.

Unicode Art

There is a long history of using ASCII printable characters and ANSI escape sequences, and recently also non-ASCII Unicode characters, to draw pictures on terminals. To display compiler diagnostics, this technique has been used to assemble line numbers, code from end users, code highlighting, and other pieces of information in a visually pleasing way. Non-ASCII Unicode characters (from implementers or from end users) greatly expand the vocabulary of ASCII art, and we will call the new art form Unicode art to signify the use of non-ASCII characters.

No Column Numbers, Ever

The arrival of non-ASCII Unicode characters imposes new challenges as their visual widths are unpredictable without knowing the exact terminal (or terminal emulator), the exact font, etc. Unicode emoji sequences might be one of the most challenging cases: a pirate flag (🏴‍☠️) may be shown as a single emoji flag on supported platforms but as a sequence with a black flag (🏴) and a skull (☠️) on other platforms. This means the visual width of the pirate flag is unpredictable. (See Unicode Emoji Section 2.2.) The rainbow flag (🏳️‍🌈), skin tones, and many other emoji sequences have the same issue. Other less chaotic but still challenging cases include characters whose East Asian width is Ambiguous. These challenges bear some similarity with the unpredictability of the visual width of horizontal tabulations, but in a much wilder way.

Note: "Unicode characters" are not really defined in the Unicode standard, and here they mean Unicode scalar values, that is, all Unicode code points except the surrogate code points for UTF-16 to represent all scalar values. Although the word "character" has many incompatible meanings and usages, we decided to call scalar values "Unicode characters" anyway because (1) most people are not familiar with the official term "scalar values" and (2) scalar values are the only stable primitive unit one can work with in a programming language.

It is thus wise to think twice before using emoji sequences and other tricky characters in Unicode art. To quantify the degree to which a Unicode art can remain visually pleasing on different platforms, we specify the following four levels of stability. Note that if implementers decide to integrate content from end users into their Unicode art, the end users should have the freedom to include arbitrary emoji sequences and tricky characters in their content. The final Unicode art must remain visually pleasing as defined by the stability levels for any reasonable user content.

  • Level 0 (the least stable): Stability under the assumption that every Unicode character occupies exactly the same visual width. Thankfully, programs meeting only this level are mostly considered outdated.
  • Level 1: Stability under the assumption each Unicode string visually occupies a multiple of some fixed width, where the multiplier is determined by heuristics (such as various implementations of wcwidth and wcswidth). These heuristics are created to help programmers handle more characters, in particular CJK characters, without dramatically changing the code. They however do not solve the core problem (that is, visual width is fundamentally ill-defined) and they often could not handle tricky cases such as emoji sequences. Many compilers are at this level.
  • Level 2a: Stability under very limited assumptions on which characters should have the same widths. For example, if a Unicode art only assumes Unicode box-drawing characters are of the same visual width (which is the case in all conceivable situations), then its stability is at this level. However, the phrase "very limited" is somewhat subjective, and thus we present a more precise version below.
  • Level 2b: Stability under only theses assumptions:

    Level 2b is making explicit what Level 2a means; we might update the details of Level 2b later to better match our understanding of Level 2a. Collectively, Levels 2a and 2b are called "Level 2".

  • Level 3 (the most stable): Stability under only one assumption that equivalent (extended) grapheme clusters have the same visual width (the last assumption of Level 2b). This means that the Unicode art will remain visually pleasing in almost all situations. It can even be rendered with a variable-width font.

Unlike most implementations, which are at Level 1, our terminal backend strives to achieve Level 2. That means we must not make any assumption about the visual width of end users' code and must abandon the idea of column numbers. Our terminal backend never uses column numbers and we consider that as a significant improvement. On the other hand, Level 3 seems to be too restricted for compiler diagnostics because we cannot show line numbers along with the end users' code. (We cannot assume the numbers "10" and "99" will have the same visual width at Level 3.)

Note: a fixed-width font with enough glyphs that covers many Unicode characters is often technically duospaced, not monospaced, because many CJK characters would occupy a double character visual width. Thus, we do not use the terminology "monospaced".

No Support of Bidirectional Text Yet

Proper support of bidirectional text will benefit many potential end users, but unfortunately, we currently do not have the capacity to implement it. The general support of bidirectional text in most system libraries and tools is poor, and without dedicated effort, it is hard to verify whether we manage to avoid common pitfalls.

On a related note, Unicode Source Code Handling suggests that source code should be segmented into atoms and their display order should remain the same to maintain the lexical structure. (This deviation is allowed by the Unicode Bidirectional Algorithm.) Our current implementation cannot handle this because it has no access to such structural information of the content from end users.

Raw Bytes as Positions

All positions should be byte-oriented. We believe other popular alternatives proposals are worse:

  1. Unicode characters (Unicode scalar values): This is a reasonable and technically well-defined choice. The problem is that it may take linear time to count the number of characters from raw bytes without a clever data structure (unless we are using UTF-32), and they often do not match what end users perceive as "characters". In other words, it takes more time to compute and may invite misconceptions about Unicode characters.
  2. Code units used in UTF-16: This is somewhat similar to Unicode characters, but with quirks from UTF-16: a Unicode scalar value above U+FFFF (such as 😎) will require two code units to form a surrogate pair. Therefore, it is arguably worse than just using Unicode characters. This scheme was unfortunately chosen by the Language Service Protocol (LSP) as the default unit, and until LSP version 3.17 was the only choice. The developers of the protocol made this decision probably because Visual Studio Code was written in JavaScript (and TypeScript), whose strings use UTF-16 encoding.
  3. (Extended) grapheme clusters or user-perceived characters. The notion of grapheme clusters can help segment a Unicode text for end users to edit or select part of it in an "intuitive" way. It is not trivial to implement the segmentation algorithm (see the OCaml library uuseg) and the default rules can (and maybe should) be overriden for each application. The complexity and external dependency of grapheme clusters make it an unreliable unit for specifying positions. It also takes at least linear time to count the number of grapheme clusters from raw bytes.
  4. Column numbers, the visual width of a string in display. As analyzed in the above section, this is the most ill-defined unit of all, and a heuristic that can give passable results in most cases still takes linear time.

Know Bug: Our LSP prototype does not handle positionEncoding yet, and because the default unit in LSP is based on UTF-16 (see above), an LSP client may be confused about the byte-oriented ranges returned by this library. A proper LSP implementation should negotiate with the client to determine how to represent column positions (and our current prototype does not). On the other hand, it can be tricky to negotiate with the client to use raw bytes because there is not an official predefined encoding scheme for raw bytes yet.

diff --git a/asai/index.html b/asai/index.html index 8e0eb15..bc1e8bc 100644 --- a/asai/index.html +++ b/asai/index.html @@ -1,2 +1,2 @@ -index (asai.index)

asai: Compiler Diagnostics

What is "asai"?

"asai" is the transliteration of "浅井", the family name of the character Kei Asai (浅井 ケイ) in the Japanese light novel Sagrada Reset (サクラダリセット, also known in English as Sakurada Reset). His ability is perfect photographic memory that is even immune to the "Reset" ability owned by another main character. This OCaml library should record all messages, just like the character.

\ No newline at end of file +index (asai.index)

asai: Compiler Diagnostics

What is "asai"?

"asai" is the transliteration of "浅井", the family name of the character Kei Asai (浅井 ケイ) in the Japanese light novel Sagrada Reset (サクラダリセット, also known in English as Sakurada Reset). His ability is perfect photographic memory that is even immune to the "Reset" ability owned by another main character. This OCaml library should record all messages, just like the character.

diff --git a/asai/quickstart.html b/asai/quickstart.html index 5039ef4..f725080 100644 --- a/asai/quickstart.html +++ b/asai/quickstart.html @@ -1,5 +1,5 @@ -quickstart (asai.quickstart)

Quickstart Tutorial

This tutorial is for an implementer (you!) to adopt this library as quickly as possible. We will assume you are already familiar with OCaml and are using a typical OCaml package structure.

Define Error Codes

The first step is to create a file Logger.ml with the following template:

module Code =
+quickstart (asai.quickstart)

Quickstart Tutorial

This tutorial is for an implementer (you!) to adopt this library as quickly as possible. We will assume you are already familiar with OCaml and are using a typical OCaml package structure.

Define Error Codes

The first step is to create a file Logger.ml with the following template:

module Code =
 struct
   (** All message codes used in your application. *)
   type t = (* ... *)
@@ -19,16 +19,16 @@
 end
 
 (** Include all the goodies from the asai library. *)
-include Asai.Logger.Make(Code)

The most important step is to decide the message codes. It should be a meaningful classification of all the messages that could be sent to the end users. For example, UndefinedSymbol could be a reasonable code for a message about failing to find the definition of a symbol. Once you define the type of all message codes, you will have to define two functions default_severity and to_string:

  1. default_severity: Severity means how serious an end user should take your message (is it an error or a warning?), and this can be overwritten when a message is sent. It seems messages with the same message code usually come with the same severity, so we want you to define a default severity value for each message code. You can then save some typing later when sending a message.
  2. to_string: This function is to show the message code to the user. Ideally, it should give a short, Google-able string representation. Please do not use long descriptions such as "scope-error: undefined symbols." The library will give you plenty of opportunities to add as many details as you want to a message, but not here. The message code should be unambiguous, easily recognizable, and "machine-readable without ChatGPT."

Once you have filled out the template, run dune build or other tools to check that everything compiles. If so, you are ready for the next step.

Start Sending Messages

Now, go to the places where you want to send a message to end users, be it a warning or an error. If you want to print a message and continue the execution, you can emit a string:

Logger.emit Greeting "Hello!";
-(* continue doing other things *)

where Greeting is the message code of this message. The fancier version is emitf, which formats a message like printf and sends it:

Logger.emitf TypeError "@[<2>This term doesn't look right:@ %a@]" Syntax.pp term;
-(* continue doing other things *)

There is an important limitation of emitf though: you should not include any control character (for example the newline character \n) anywhere when using emitf. Use break hints (such as @, and @ ) and boxes instead. See Stdlib.Format for more information on boxes and break hints.

If you wish to terminate your program after sending a message instead of continuing the execution, use fatal instead of emit. There's also a fancier fatalf that works in the same way as emitf.

Choose a Backend

Now your program is generating lots of messages, and you have to choose a backend to handle them. We will show how to display those messages in a terminal. Suppose your entry point module looks like this:

let () = (* your application code *)

You can use the terminal backend as follows:

module Term = Asai.Tty.Make (Logger.Code)
+include Asai.Logger.Make(Code)

The most important step is to decide the message codes. It should be a meaningful classification of all the messages that could be sent to the end users. For example, UndefinedSymbol could be a reasonable code for a message about failing to find the definition of a symbol. Once you define the type of all message codes, you will have to define two functions default_severity and to_string:

  1. default_severity: Severity means how serious an end user should take your message (is it an error or a warning?), and this can be overwritten when a message is sent. It seems messages with the same message code usually come with the same severity, so we want you to define a default severity value for each message code. You can then save some typing later when sending a message.
  2. to_string: This function is to show the message code to the user. Ideally, it should give a short, Google-able string representation. Please do not use long descriptions such as "scope-error: undefined symbols." The library will give you plenty of opportunities to add as many details as you want to a message, but not here. The message code should be unambiguous, easily recognizable, and "machine-readable without ChatGPT."

Once you have filled out the template, run dune build or other tools to check that everything compiles. If so, you are ready for the next step.

Start Sending Messages

Now, go to the places where you want to send a message to end users, be it a warning or an error. If you want to print a message and continue the execution, you can emit a string:

Logger.emit Greeting "Hello!";
+(* continue doing other things *)

where Greeting is the message code of this message. The fancier version is emitf, which formats a message like printf and sends it:

Logger.emitf TypeError "@[<2>This term doesn't look right:@ %a@]" Syntax.pp term;
+(* continue doing other things *)

There is an important limitation of emitf though: you should not include any control character (for example the newline character \n) anywhere when using emitf. Use break hints (such as @, and @ ) and boxes instead. See Stdlib.Format for more information on boxes and break hints.

If you wish to terminate your program after sending a message instead of continuing the execution, use fatal instead of emit. There's also a fancier fatalf that works in the same way as emitf.

Choose a Backend

Now your program is generating lots of messages, and you have to choose a backend to handle them. We will show how to display those messages in a terminal. Suppose your entry point module looks like this:

let () = (* your application code *)

You can use the terminal backend as follows:

module Term = Asai.Tty.Make (Logger.Code)
 
 let () =
   Logger.run ~emit:Term.display ~fatal:Term.display @@ fun () ->
   (* your application code *)

Add Backtraces

Great messages come with meaningful backtraces. To add backtraces, you will have to "annotate" your code to generate meaningful stack frames. Suppose this is one of the functions whose invocation should be noted in user-facing backtraces:

let f x y =
-  (* very important code *)

Add trace to add a frame to the current backtrace:

let f x y =
+  (* very important code *)

Add trace to add a frame to the current backtrace:

let f x y =
   Logger.trace "When calling f" @@ fun () ->
-  (* very important code *)

Similar to emitf, there is also tracef which allows you to format messages:

let f x y =
+  (* very important code *)

Similar to emitf, there is also tracef which allows you to format messages:

let f x y =
   Logger.tracef "When calling f on %d and %d" x y @@ fun () ->
   (* very important code *)

Note that, by default, the terminal backend will not show backtraces. You have to enable it as follows in your entry-point module:

module Term = Asai.Tty.Make (Logger.Code)
 
@@ -36,11 +36,11 @@
   Logger.run
     ~emit:(Term.display ~show_backtrace:true)
     ~fatal:(Term.display ~show_backtrace:true) @@ fun () ->
-  (* your application code *)

We do not recommend adding trace to every single function. Remember that they have to make sense to end users!

Add Location Information

Good messages also help end users locate the issues in their program or proof. Here, a location is a range of text from a file, which we call span. Many functions in your Logger take an optional location argument loc, including trace, which should be a span highlighting the most relevant text. For example, maybe the term which does not type check should be highlighted. The asai library will take the location information and draw fancy Unicode art on the screen to highlight the text. Here is one snippet showing the usage:

Logger.emit ~loc Greeting "Hello again!";
-(* continue doing other things *)

You can use Span.make to create such a span manually. However, if you are using ocamllex and Menhir, you certainly want to use provided helper functions. One of them is Span.locate; you can add these lines in your Menhir grammar to generated a node annotated with its location:

%inline
+  (* your application code *)

We do not recommend adding trace to every single function. Remember that they have to make sense to end users!

Add Location Information

Good messages also help end users locate the issues in their program or proof. Here, a location is a range of text from a file, which we call span. Many functions in your Logger take an optional location argument loc, including trace, which should be a span highlighting the most relevant text. For example, maybe the term which does not type check should be highlighted. The asai library will take the location information and draw fancy Unicode art on the screen to highlight the text. Here is one snippet showing the usage:

Logger.emit ~loc Greeting "Hello again!";
+(* continue doing other things *)

You can use Span.make to create such a span manually. However, if you are using ocamllex and Menhir, you certainly want to use provided helper functions. One of them is Span.locate; you can add these lines in your Menhir grammar to generated a node annotated with its location:

%inline
 locate(X):
   | e = X
-    { Asai.Span.locate_lex $loc e }

The annotated node will have type data Span.located where data is the output type of X. Another one is Span.of_lexbuf, which comes in handy when reporting a parsing error:

try Grammar.start Lex.token lexbuf with
+    { Asai.Span.locate_lex $loc e }

The annotated node will have type data Span.located where data is the output type of X. Another one is Span.of_lexbuf, which comes in handy when reporting a parsing error:

try Grammar.start Lex.token lexbuf with
 | Lex.SyntaxError token ->
   Logger.fatalf ~loc:(Span.of_lexbuf lexbuf) ParsingError
     {|Unrecognized token `%s'|} (String.escaped token)
@@ -49,7 +49,7 @@
     "Failed to parse the code"

Please take a look at Asai.Span to learn all kinds of ways to create a span!

Note that Logger will remember and reuse the innermost specified location, and thus you do not have to explicitly pass it. For example, in the following code

Logger.trace ~loc "When checking this code" @@ fun () ->
 (* ... *)
 Logger.emit "Wow!" (* using the location [loc] from above *)
-(* ... *)

the inner message "Wow!" will inherit the location loc from the outer trace function call! You can also use merge_loc to "remember" a location for later use, which is helpful when you want to remember a location but not to leave a trace:

Logger.merge_loc (Some loc) @@ fun () ->
+(* ... *)

the inner message "Wow!" will inherit the location loc from the outer trace function call! You can also use merge_loc to "remember" a location for later use, which is helpful when you want to remember a location but not to leave a trace:

Logger.merge_loc (Some loc) @@ fun () ->
 (* ... *)
 Logger.emit "Wow!" (* using the location [loc] from above *)
 (* ... *)

Of course, you can always pass a new location to overwrite the remembered one:

Logger.merge_loc (Some loc) @@ fun () ->
@@ -79,8 +79,8 @@
   try_with
     ~emit:(fun d -> emit_diagnostic {d with severity = Error})
     ~fatal:(fun d -> fatal_diagnostic {d with severity = Error})
-    f

And then use Logger.all_as_errors to turn all messages into errors:

Logger.all_as_errors @@ fun () -> (* any message sent here will be an error *)

Note that turning a message into an error does not abort the computation. all_as_errors only makes the message look scarier and it will not affect the control flow. If you wish to also abort the program the moment any message is sent, replace emit_diagnostic with fatal_diagnostic:

let abort_at_any f =
+    f

And then use Logger.all_as_errors to turn all messages into errors:

Logger.all_as_errors @@ fun () -> (* any message sent here will be an error *)

Note that turning a message into an error does not abort the computation. all_as_errors only makes the message look scarier and it will not affect the control flow. If you wish to also abort the program the moment any message is sent, replace emit_diagnostic with fatal_diagnostic:

let abort_at_any f =
   try_with
     ~emit:(fun d -> fatal_diagnostic {d with severity = Error})
     ~fatal:(fun d -> fatal_diagnostic {d with severity = Error})
-    f

Within abort_at_any, every message will become a fatal error:

Logger.abort_at_any @@ fun () -> (* any message will be an error AND abort the program *)

Recover from Fatal Messages

Just like the usual try ... with in OCaml, you can use Logger.try_with to intercept fatal messages. However, unlike messages sent via emit, there is no way to resume the aborted computation (as what you can do with an OCaml exception). Therefore, you have to provide a new value as a replacement. For example, the code:

Logger.try_with ~fatal:(fun _ -> 42) @@ fun () -> Logger.fatal "abort!"

will give you the number 42 in the end. It intercepts the fatal message and gives 42 instead.

There are More!

We are still expanding this tutorial, but in the meanwhile, you can also check out our 📔 API reference.

\ No newline at end of file + f

Within abort_at_any, every message will become a fatal error:

Logger.abort_at_any @@ fun () -> (* any message will be an error AND abort the program *)

Recover from Fatal Messages

Just like the usual try ... with in OCaml, you can use Logger.try_with to intercept fatal messages. However, unlike messages sent via emit, there is no way to resume the aborted computation (as what you can do with an OCaml exception). Therefore, you have to provide a new value as a replacement. For example, the code:

Logger.try_with ~fatal:(fun _ -> 42) @@ fun () -> Logger.fatal "abort!"

will give you the number 42 in the end. It intercepts the fatal message and gives 42 instead.

There are More!

We are still expanding this tutorial, but in the meanwhile, you can also check out our 📔 API reference.

diff --git a/odoc.support/fonts/fira-mono-v14-latin-500.woff2 b/odoc.support/fonts/fira-mono-v14-latin-500.woff2 new file mode 100644 index 0000000..9d07a63 Binary files /dev/null and b/odoc.support/fonts/fira-mono-v14-latin-500.woff2 differ diff --git a/odoc.support/fonts/fira-mono-v14-latin-regular.woff2 b/odoc.support/fonts/fira-mono-v14-latin-regular.woff2 new file mode 100644 index 0000000..edc71a8 Binary files /dev/null and b/odoc.support/fonts/fira-mono-v14-latin-regular.woff2 differ diff --git a/odoc.support/fonts/fira-sans-v17-latin-500.woff2 b/odoc.support/fonts/fira-sans-v17-latin-500.woff2 new file mode 100644 index 0000000..24bb8f4 Binary files /dev/null and b/odoc.support/fonts/fira-sans-v17-latin-500.woff2 differ diff --git a/odoc.support/fonts/fira-sans-v17-latin-500italic.woff2 b/odoc.support/fonts/fira-sans-v17-latin-500italic.woff2 new file mode 100644 index 0000000..1a8b72d Binary files /dev/null and b/odoc.support/fonts/fira-sans-v17-latin-500italic.woff2 differ diff --git a/odoc.support/fonts/fira-sans-v17-latin-700.woff2 b/odoc.support/fonts/fira-sans-v17-latin-700.woff2 new file mode 100644 index 0000000..40b8a1c Binary files /dev/null and b/odoc.support/fonts/fira-sans-v17-latin-700.woff2 differ diff --git a/odoc.support/fonts/fira-sans-v17-latin-700italic.woff2 b/odoc.support/fonts/fira-sans-v17-latin-700italic.woff2 new file mode 100644 index 0000000..bdf8f5f Binary files /dev/null and b/odoc.support/fonts/fira-sans-v17-latin-700italic.woff2 differ diff --git a/odoc.support/fonts/fira-sans-v17-latin-italic.woff2 b/odoc.support/fonts/fira-sans-v17-latin-italic.woff2 new file mode 100644 index 0000000..b9619dd Binary files /dev/null and b/odoc.support/fonts/fira-sans-v17-latin-italic.woff2 differ diff --git a/odoc.support/fonts/fira-sans-v17-latin-regular.woff2 b/odoc.support/fonts/fira-sans-v17-latin-regular.woff2 new file mode 100644 index 0000000..d31eba8 Binary files /dev/null and b/odoc.support/fonts/fira-sans-v17-latin-regular.woff2 differ diff --git a/odoc.support/fonts/noticia-text-v15-latin-700.woff2 b/odoc.support/fonts/noticia-text-v15-latin-700.woff2 new file mode 100644 index 0000000..536fbe1 Binary files /dev/null and b/odoc.support/fonts/noticia-text-v15-latin-700.woff2 differ diff --git a/odoc.support/fonts/noticia-text-v15-latin-italic.woff2 b/odoc.support/fonts/noticia-text-v15-latin-italic.woff2 new file mode 100644 index 0000000..9b83b07 Binary files /dev/null and b/odoc.support/fonts/noticia-text-v15-latin-italic.woff2 differ diff --git a/odoc.support/fonts/noticia-text-v15-latin-regular.woff2 b/odoc.support/fonts/noticia-text-v15-latin-regular.woff2 new file mode 100644 index 0000000..efff29f Binary files /dev/null and b/odoc.support/fonts/noticia-text-v15-latin-regular.woff2 differ diff --git a/odoc.support/highlight.pack.js b/odoc.support/highlight.pack.js index a373159..7d1bcd0 100644 --- a/odoc.support/highlight.pack.js +++ b/odoc.support/highlight.pack.js @@ -302,7 +302,238 @@ e["after:highlightBlock"](Object.assign({block:t.el},t))})})(e),s.push(e)} },t.versionString="11.7.0",t.regex={concat:p,lookahead:d,either:f,optional:h, anyNumberOfTimes:u};for(const t in A)"object"==typeof A[t]&&e.exports(A[t]) ;return Object.assign(t,A),t})({});return te}() -;"object"==typeof exports&&"undefined"!=typeof module&&(module.exports=hljs);/*! `xml` grammar compiled for Highlight.js 11.7.0 */ +;"object"==typeof exports&&"undefined"!=typeof module&&(module.exports=hljs);/*! `reasonml` grammar compiled for Highlight.js 11.7.0 */ +(()=>{var e=(()=>{"use strict";return e=>{ +const n="~?[a-z$_][0-9a-zA-Z$_]*",a="`?[A-Z$_][0-9a-zA-Z$_]*",s="("+["||","++","**","+.","*","/","*.","/.","..."].map((e=>e.split("").map((e=>"\\"+e)).join(""))).join("|")+"|\\|>|&&|==|===)",i="\\s+"+s+"\\s+",r={ +keyword:"and as asr assert begin class constraint do done downto else end exception external for fun function functor if in include inherit initializer land lazy let lor lsl lsr lxor match method mod module mutable new nonrec object of open or private rec sig struct then to try type val virtual when while with", +built_in:"array bool bytes char exn|5 float int int32 int64 list lazy_t|5 nativeint|5 ref string unit ", +literal:"true false" +},l="\\b(0[xX][a-fA-F0-9_]+[Lln]?|0[oO][0-7_]+[Lln]?|0[bB][01_]+[Lln]?|[0-9][0-9_]*([Lln]|(\\.[0-9_]*)?([eE][-+]?[0-9_]+)?)?)",t={ +className:"number",relevance:0,variants:[{begin:l},{begin:"\\(-"+l+"\\)"}]},c={ +className:"operator",relevance:0,begin:s},o=[{className:"identifier", +relevance:0,begin:n},c,t],g=[e.QUOTE_STRING_MODE,c,{className:"module", +begin:"\\b"+a,returnBegin:!0,relevance:0,end:".",contains:[{ +className:"identifier",begin:a,relevance:0}]}],b=[{className:"module", +begin:"\\b"+a,returnBegin:!0,end:".",relevance:0,contains:[{ +className:"identifier",begin:a,relevance:0}]}],m={className:"function", +relevance:0,keywords:r,variants:[{begin:"\\s(\\(\\.?.*?\\)|"+n+")\\s*=>", +end:"\\s*=>",returnBegin:!0,relevance:0,contains:[{className:"params", +variants:[{begin:n},{ +begin:"~?[a-z$_][0-9a-zA-Z$_]*(\\s*:\\s*[a-z$_][0-9a-z$_]*(\\(\\s*('?[a-z$_][0-9a-z$_]*\\s*(,'?[a-z$_][0-9a-z$_]*\\s*)*)?\\))?){0,2}" +},{begin:/\(\s*\)/}]}]},{begin:"\\s\\(\\.?[^;\\|]*\\)\\s*=>",end:"\\s=>", +returnBegin:!0,relevance:0,contains:[{className:"params",relevance:0,variants:[{ +begin:n,end:"(,|\\n|\\))",relevance:0,contains:[c,{className:"typing",begin:":", +end:"(,|\\n)",returnBegin:!0,relevance:0,contains:b}]}]}]},{ +begin:"\\(\\.\\s"+n+"\\)\\s*=>"}]};g.push(m);const d={className:"constructor", +begin:a+"\\(",end:"\\)",illegal:"\\n",keywords:r, +contains:[e.QUOTE_STRING_MODE,c,{className:"params",begin:"\\b"+n}]},u={ +className:"pattern-match",begin:"\\|",returnBegin:!0,keywords:r,end:"=>", +relevance:0,contains:[d,c,{relevance:0,className:"constructor",begin:a}]},v={ +className:"module-access",keywords:r,returnBegin:!0,variants:[{ +begin:"\\b("+a+"\\.)+"+n},{begin:"\\b("+a+"\\.)+\\(",end:"\\)",returnBegin:!0, +contains:[m,{begin:"\\(",end:"\\)",relevance:0,skip:!0}].concat(g)},{ +begin:"\\b("+a+"\\.)+\\{",end:/\}/}],contains:g};return b.push(v),{ +name:"ReasonML",aliases:["re"],keywords:r,illegal:"(:-|:=|\\$\\{|\\+=)", +contains:[e.COMMENT("/\\*","\\*/",{illegal:"^(#,\\/\\/)"}),{ +className:"character",begin:"'(\\\\[^']+|[^'])'",illegal:"\\n",relevance:0 +},e.QUOTE_STRING_MODE,{className:"literal",begin:"\\(\\)",relevance:0},{ +className:"literal",begin:"\\[\\|",end:"\\|\\]",relevance:0,contains:o},{ +className:"literal",begin:"\\[",end:"\\]",relevance:0,contains:o},d,{ +className:"operator",begin:i,illegal:"--\x3e",relevance:0 +},t,e.C_LINE_COMMENT_MODE,u,m,{className:"module-def", +begin:"\\bmodule\\s+"+n+"\\s+"+a+"\\s+=\\s+\\{",end:/\}/,returnBegin:!0, +keywords:r,relevance:0,contains:[{className:"module",relevance:0,begin:a},{ +begin:/\{/,end:/\}/,relevance:0,skip:!0}].concat(g)},v]}}})() +;hljs.registerLanguage("reasonml",e)})();/*! `javascript` grammar compiled for Highlight.js 11.7.0 */ +(()=>{var e=(()=>{"use strict" +;const e="[A-Za-z$_][0-9A-Za-z$_]*",n=["as","in","of","if","for","while","finally","var","new","function","do","return","void","else","break","catch","instanceof","with","throw","case","default","try","switch","continue","typeof","delete","let","yield","const","class","debugger","async","await","static","import","from","export","extends"],a=["true","false","null","undefined","NaN","Infinity"],t=["Object","Function","Boolean","Symbol","Math","Date","Number","BigInt","String","RegExp","Array","Float32Array","Float64Array","Int8Array","Uint8Array","Uint8ClampedArray","Int16Array","Int32Array","Uint16Array","Uint32Array","BigInt64Array","BigUint64Array","Set","Map","WeakSet","WeakMap","ArrayBuffer","SharedArrayBuffer","Atomics","DataView","JSON","Promise","Generator","GeneratorFunction","AsyncFunction","Reflect","Proxy","Intl","WebAssembly"],s=["Error","EvalError","InternalError","RangeError","ReferenceError","SyntaxError","TypeError","URIError"],r=["setInterval","setTimeout","clearInterval","clearTimeout","require","exports","eval","isFinite","isNaN","parseFloat","parseInt","decodeURI","decodeURIComponent","encodeURI","encodeURIComponent","escape","unescape"],c=["arguments","this","super","console","window","document","localStorage","module","global"],i=[].concat(r,t,s) +;return o=>{const l=o.regex,b=e,d={begin:/<[A-Za-z0-9\\._:-]+/, +end:/\/[A-Za-z0-9\\._:-]+>|\/>/,isTrulyOpeningTag:(e,n)=>{ +const a=e[0].length+e.index,t=e.input[a] +;if("<"===t||","===t)return void n.ignoreMatch();let s +;">"===t&&(((e,{after:n})=>{const a="",M={ +match:[/const|var|let/,/\s+/,b,/\s*/,/=\s*/,/(async\s*)?/,l.lookahead(C)], +keywords:"async",className:{1:"keyword",3:"title.function"},contains:[S]} +;return{name:"Javascript",aliases:["js","jsx","mjs","cjs"],keywords:g,exports:{ +PARAMS_CONTAINS:p,CLASS_REFERENCE:R},illegal:/#(?![$_A-z])/, +contains:[o.SHEBANG({label:"shebang",binary:"node",relevance:5}),{ +label:"use_strict",className:"meta",relevance:10, +begin:/^\s*['"]use (strict|asm)['"]/ +},o.APOS_STRING_MODE,o.QUOTE_STRING_MODE,y,N,_,h,{match:/\$\d+/},E,R,{ +className:"attr",begin:b+l.lookahead(":"),relevance:0},M,{ +begin:"("+o.RE_STARTERS_RE+"|\\b(case|return|throw)\\b)\\s*", +keywords:"return throw case",relevance:0,contains:[h,o.REGEXP_MODE,{ +className:"function",begin:C,returnBegin:!0,end:"\\s*=>",contains:[{ +className:"params",variants:[{begin:o.UNDERSCORE_IDENT_RE,relevance:0},{ +className:null,begin:/\(\s*\)/,skip:!0},{begin:/\(/,end:/\)/,excludeBegin:!0, +excludeEnd:!0,keywords:g,contains:p}]}]},{begin:/,/,relevance:0},{match:/\s+/, +relevance:0},{variants:[{begin:"<>",end:""},{ +match:/<[A-Za-z0-9\\._:-]+\s*\/>/},{begin:d.begin, +"on:begin":d.isTrulyOpeningTag,end:d.end}],subLanguage:"xml",contains:[{ +begin:d.begin,end:d.end,skip:!0,contains:["self"]}]}]},O,{ +beginKeywords:"while if switch catch for"},{ +begin:"\\b(?!function)"+o.UNDERSCORE_IDENT_RE+"\\([^()]*(\\([^()]*(\\([^()]*\\)[^()]*)*\\)[^()]*)*\\)\\s*\\{", +returnBegin:!0,label:"func.def",contains:[S,o.inherit(o.TITLE_MODE,{begin:b, +className:"title.function"})]},{match:/\.\.\./,relevance:0},x,{match:"\\$"+b, +relevance:0},{match:[/\bconstructor(?=\s*\()/],className:{1:"title.function"}, +contains:[S]},k,{relevance:0,match:/\b[A-Z][A-Z_0-9]+\b/, +className:"variable.constant"},w,T,{match:/\$[(.]/}]}}})() +;hljs.registerLanguage("javascript",e)})();/*! `sql` grammar compiled for Highlight.js 11.7.0 */ +(()=>{var e=(()=>{"use strict";return e=>{ +const r=e.regex,t=e.COMMENT("--","$"),n=["true","false","unknown"],a=["bigint","binary","blob","boolean","char","character","clob","date","dec","decfloat","decimal","float","int","integer","interval","nchar","nclob","national","numeric","real","row","smallint","time","timestamp","varchar","varying","varbinary"],i=["abs","acos","array_agg","asin","atan","avg","cast","ceil","ceiling","coalesce","corr","cos","cosh","count","covar_pop","covar_samp","cume_dist","dense_rank","deref","element","exp","extract","first_value","floor","json_array","json_arrayagg","json_exists","json_object","json_objectagg","json_query","json_table","json_table_primitive","json_value","lag","last_value","lead","listagg","ln","log","log10","lower","max","min","mod","nth_value","ntile","nullif","percent_rank","percentile_cont","percentile_disc","position","position_regex","power","rank","regr_avgx","regr_avgy","regr_count","regr_intercept","regr_r2","regr_slope","regr_sxx","regr_sxy","regr_syy","row_number","sin","sinh","sqrt","stddev_pop","stddev_samp","substring","substring_regex","sum","tan","tanh","translate","translate_regex","treat","trim","trim_array","unnest","upper","value_of","var_pop","var_samp","width_bucket"],s=["create table","insert into","primary key","foreign key","not null","alter table","add constraint","grouping sets","on overflow","character set","respect nulls","ignore nulls","nulls first","nulls last","depth first","breadth first"],o=i,c=["abs","acos","all","allocate","alter","and","any","are","array","array_agg","array_max_cardinality","as","asensitive","asin","asymmetric","at","atan","atomic","authorization","avg","begin","begin_frame","begin_partition","between","bigint","binary","blob","boolean","both","by","call","called","cardinality","cascaded","case","cast","ceil","ceiling","char","char_length","character","character_length","check","classifier","clob","close","coalesce","collate","collect","column","commit","condition","connect","constraint","contains","convert","copy","corr","corresponding","cos","cosh","count","covar_pop","covar_samp","create","cross","cube","cume_dist","current","current_catalog","current_date","current_default_transform_group","current_path","current_role","current_row","current_schema","current_time","current_timestamp","current_path","current_role","current_transform_group_for_type","current_user","cursor","cycle","date","day","deallocate","dec","decimal","decfloat","declare","default","define","delete","dense_rank","deref","describe","deterministic","disconnect","distinct","double","drop","dynamic","each","element","else","empty","end","end_frame","end_partition","end-exec","equals","escape","every","except","exec","execute","exists","exp","external","extract","false","fetch","filter","first_value","float","floor","for","foreign","frame_row","free","from","full","function","fusion","get","global","grant","group","grouping","groups","having","hold","hour","identity","in","indicator","initial","inner","inout","insensitive","insert","int","integer","intersect","intersection","interval","into","is","join","json_array","json_arrayagg","json_exists","json_object","json_objectagg","json_query","json_table","json_table_primitive","json_value","lag","language","large","last_value","lateral","lead","leading","left","like","like_regex","listagg","ln","local","localtime","localtimestamp","log","log10","lower","match","match_number","match_recognize","matches","max","member","merge","method","min","minute","mod","modifies","module","month","multiset","national","natural","nchar","nclob","new","no","none","normalize","not","nth_value","ntile","null","nullif","numeric","octet_length","occurrences_regex","of","offset","old","omit","on","one","only","open","or","order","out","outer","over","overlaps","overlay","parameter","partition","pattern","per","percent","percent_rank","percentile_cont","percentile_disc","period","portion","position","position_regex","power","precedes","precision","prepare","primary","procedure","ptf","range","rank","reads","real","recursive","ref","references","referencing","regr_avgx","regr_avgy","regr_count","regr_intercept","regr_r2","regr_slope","regr_sxx","regr_sxy","regr_syy","release","result","return","returns","revoke","right","rollback","rollup","row","row_number","rows","running","savepoint","scope","scroll","search","second","seek","select","sensitive","session_user","set","show","similar","sin","sinh","skip","smallint","some","specific","specifictype","sql","sqlexception","sqlstate","sqlwarning","sqrt","start","static","stddev_pop","stddev_samp","submultiset","subset","substring","substring_regex","succeeds","sum","symmetric","system","system_time","system_user","table","tablesample","tan","tanh","then","time","timestamp","timezone_hour","timezone_minute","to","trailing","translate","translate_regex","translation","treat","trigger","trim","trim_array","true","truncate","uescape","union","unique","unknown","unnest","update","upper","user","using","value","values","value_of","var_pop","var_samp","varbinary","varchar","varying","versioning","when","whenever","where","width_bucket","window","with","within","without","year","add","asc","collation","desc","final","first","last","view"].filter((e=>!i.includes(e))),l={ +begin:r.concat(/\b/,r.either(...o),/\s*\(/),relevance:0,keywords:{built_in:o}} +;return{name:"SQL",case_insensitive:!0,illegal:/[{}]|<\//,keywords:{ +$pattern:/\b[\w\.]+/,keyword:((e,{exceptions:r,when:t}={})=>{const n=t +;return r=r||[],e.map((e=>e.match(/\|\d+$/)||r.includes(e)?e:n(e)?e+"|0":e)) +})(c,{when:e=>e.length<3}),literal:n,type:a, +built_in:["current_catalog","current_date","current_default_transform_group","current_path","current_role","current_schema","current_transform_group_for_type","current_user","session_user","system_time","system_user","current_time","localtime","current_timestamp","localtimestamp"] +},contains:[{begin:r.either(...s),relevance:0,keywords:{$pattern:/[\w\.]+/, +keyword:c.concat(s),literal:n,type:a}},{className:"type", +begin:r.either("double precision","large object","with timezone","without timezone") +},l,{className:"variable",begin:/@[a-z0-9]+/},{className:"string",variants:[{ +begin:/'/,end:/'/,contains:[{begin:/''/}]}]},{begin:/"/,end:/"/,contains:[{ +begin:/""/}]},e.C_NUMBER_MODE,e.C_BLOCK_COMMENT_MODE,t,{className:"operator", +begin:/[-+*/=%^~]|&&?|\|\|?|!=?|<(?:=>?|<|>)?|>[>=]?/,relevance:0}]}}})() +;hljs.registerLanguage("sql",e)})();/*! `bash` grammar compiled for Highlight.js 11.7.0 */ +(()=>{var e=(()=>{"use strict";return e=>{const s=e.regex,t={},n={begin:/\$\{/, +end:/\}/,contains:["self",{begin:/:-/,contains:[t]}]};Object.assign(t,{ +className:"variable",variants:[{ +begin:s.concat(/\$[\w\d#@][\w\d_]*/,"(?![\\w\\d])(?![$])")},n]});const a={ +className:"subst",begin:/\$\(/,end:/\)/,contains:[e.BACKSLASH_ESCAPE]},i={ +begin:/<<-?\s*(?=\w+)/,starts:{contains:[e.END_SAME_AS_BEGIN({begin:/(\w+)/, +end:/(\w+)/,className:"string"})]}},c={className:"string",begin:/"/,end:/"/, +contains:[e.BACKSLASH_ESCAPE,t,a]};a.contains.push(c);const o={begin:/\$?\(\(/, +end:/\)\)/,contains:[{begin:/\d+#[0-9a-f]+/,className:"number"},e.NUMBER_MODE,t] +},r=e.SHEBANG({binary:"(fish|bash|zsh|sh|csh|ksh|tcsh|dash|scsh)",relevance:10 +}),l={className:"function",begin:/\w[\w\d_]*\s*\(\s*\)\s*\{/,returnBegin:!0, +contains:[e.inherit(e.TITLE_MODE,{begin:/\w[\w\d_]*/})],relevance:0};return{ +name:"Bash",aliases:["sh"],keywords:{$pattern:/\b[a-z][a-z0-9._-]+\b/, +keyword:["if","then","else","elif","fi","for","while","in","do","done","case","esac","function"], +literal:["true","false"], +built_in:["break","cd","continue","eval","exec","exit","export","getopts","hash","pwd","readonly","return","shift","test","times","trap","umask","unset","alias","bind","builtin","caller","command","declare","echo","enable","help","let","local","logout","mapfile","printf","read","readarray","source","type","typeset","ulimit","unalias","set","shopt","autoload","bg","bindkey","bye","cap","chdir","clone","comparguments","compcall","compctl","compdescribe","compfiles","compgroups","compquote","comptags","comptry","compvalues","dirs","disable","disown","echotc","echoti","emulate","fc","fg","float","functions","getcap","getln","history","integer","jobs","kill","limit","log","noglob","popd","print","pushd","pushln","rehash","sched","setcap","setopt","stat","suspend","ttyctl","unfunction","unhash","unlimit","unsetopt","vared","wait","whence","where","which","zcompile","zformat","zftp","zle","zmodload","zparseopts","zprof","zpty","zregexparse","zsocket","zstyle","ztcp","chcon","chgrp","chown","chmod","cp","dd","df","dir","dircolors","ln","ls","mkdir","mkfifo","mknod","mktemp","mv","realpath","rm","rmdir","shred","sync","touch","truncate","vdir","b2sum","base32","base64","cat","cksum","comm","csplit","cut","expand","fmt","fold","head","join","md5sum","nl","numfmt","od","paste","ptx","pr","sha1sum","sha224sum","sha256sum","sha384sum","sha512sum","shuf","sort","split","sum","tac","tail","tr","tsort","unexpand","uniq","wc","arch","basename","chroot","date","dirname","du","echo","env","expr","factor","groups","hostid","id","link","logname","nice","nohup","nproc","pathchk","pinky","printenv","printf","pwd","readlink","runcon","seq","sleep","stat","stdbuf","stty","tee","test","timeout","tty","uname","unlink","uptime","users","who","whoami","yes"] +},contains:[r,e.SHEBANG(),l,o,e.HASH_COMMENT_MODE,i,{match:/(\/[a-z._-]+)+/},c,{ +className:"",begin:/\\"/},{className:"string",begin:/'/,end:/'/},t]}}})() +;hljs.registerLanguage("bash",e)})();/*! `shell` grammar compiled for Highlight.js 11.7.0 */ +(()=>{var s=(()=>{"use strict";return s=>({name:"Shell Session", +aliases:["console","shellsession"],contains:[{className:"meta.prompt", +begin:/^\s{0,3}[/~\w\d[\]()@-]*[>%$#][ ]?/,starts:{end:/[^\\](?=\s*$)/, +subLanguage:"bash"}}]})})();hljs.registerLanguage("shell",s)})();/*! `plaintext` grammar compiled for Highlight.js 11.7.0 */ +(()=>{var t=(()=>{"use strict";return t=>({name:"Plain text", +aliases:["text","txt"],disableAutodetect:!0})})() +;hljs.registerLanguage("plaintext",t)})();/*! `graphql` grammar compiled for Highlight.js 11.7.0 */ +(()=>{var e=(()=>{"use strict";return e=>{const a=e.regex;return{name:"GraphQL", +aliases:["gql"],case_insensitive:!0,disableAutodetect:!1,keywords:{ +keyword:["query","mutation","subscription","type","input","schema","directive","interface","union","scalar","fragment","enum","on"], +literal:["true","false","null"]}, +contains:[e.HASH_COMMENT_MODE,e.QUOTE_STRING_MODE,e.NUMBER_MODE,{ +scope:"punctuation",match:/[.]{3}/,relevance:0},{scope:"punctuation", +begin:/[\!\(\)\:\=\[\]\{\|\}]{1}/,relevance:0},{scope:"variable",begin:/\$/, +end:/\W/,excludeEnd:!0,relevance:0},{scope:"meta",match:/@\w+/,excludeEnd:!0},{ +scope:"symbol",begin:a.concat(/[_A-Za-z][_0-9A-Za-z]*/,a.lookahead(/\s*:/)), +relevance:0}],illegal:[/[;<']/,/BEGIN/]}}})();hljs.registerLanguage("graphql",e) +})();/*! `ocaml` grammar compiled for Highlight.js 11.7.0 */ +(()=>{var e=(()=>{"use strict";return e=>({name:"OCaml",aliases:["ml"], +keywords:{$pattern:"[a-z_]\\w*!?", +keyword:"and as assert asr begin class constraint do done downto else end exception external for fun function functor if in include inherit! inherit initializer land lazy let lor lsl lsr lxor match method!|10 method mod module mutable new object of open! open or private rec sig struct then to try type val! val virtual when while with parser value", +built_in:"array bool bytes char exn|5 float int int32 int64 list lazy_t|5 nativeint|5 string unit in_channel out_channel ref", +literal:"true false"},illegal:/\/\/|>>/,contains:[{className:"literal", +begin:"\\[(\\|\\|)?\\]|\\(\\)",relevance:0},e.COMMENT("\\(\\*","\\*\\)",{ +contains:["self"]}),{className:"symbol",begin:"'[A-Za-z_](?!')[\\w']*"},{ +className:"type",begin:"`[A-Z][\\w']*"},{className:"type", +begin:"\\b[A-Z][\\w']*",relevance:0},{begin:"[a-z_]\\w*'[\\w']*",relevance:0 +},e.inherit(e.APOS_STRING_MODE,{className:"string",relevance:0 +}),e.inherit(e.QUOTE_STRING_MODE,{illegal:null}),{className:"number", +begin:"\\b(0[xX][a-fA-F0-9_]+[Lln]?|0[oO][0-7_]+[Lln]?|0[bB][01_]+[Lln]?|[0-9][0-9_]*([Lln]|(\\.[0-9_]*)?([eE][-+]?[0-9_]+)?)?)", +relevance:0},{begin:/->/}]})})();hljs.registerLanguage("ocaml",e)})();/*! `json` grammar compiled for Highlight.js 11.7.0 */ +(()=>{var e=(()=>{"use strict";return e=>{const a=["true","false","null"],n={ +scope:"literal",beginKeywords:a.join(" ")};return{name:"JSON",keywords:{ +literal:a},contains:[{className:"attr",begin:/"(\\.|[^\\"\r\n])*"(?=\s*:)/, +relevance:1.01},{match:/[{}[\],:]/,className:"punctuation",relevance:0 +},e.QUOTE_STRING_MODE,n,e.C_NUMBER_MODE,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE], +illegal:"\\S"}}})();hljs.registerLanguage("json",e)})();/*! `python` grammar compiled for Highlight.js 11.7.0 */ +(()=>{var e=(()=>{"use strict";return e=>{ +const n=e.regex,a=/[\p{XID_Start}_]\p{XID_Continue}*/u,i=["and","as","assert","async","await","break","case","class","continue","def","del","elif","else","except","finally","for","from","global","if","import","in","is","lambda","match","nonlocal|10","not","or","pass","raise","return","try","while","with","yield"],s={ +$pattern:/[A-Za-z]\w+|__\w+__/,keyword:i, +built_in:["__import__","abs","all","any","ascii","bin","bool","breakpoint","bytearray","bytes","callable","chr","classmethod","compile","complex","delattr","dict","dir","divmod","enumerate","eval","exec","filter","float","format","frozenset","getattr","globals","hasattr","hash","help","hex","id","input","int","isinstance","issubclass","iter","len","list","locals","map","max","memoryview","min","next","object","oct","open","ord","pow","print","property","range","repr","reversed","round","set","setattr","slice","sorted","staticmethod","str","sum","super","tuple","type","vars","zip"], +literal:["__debug__","Ellipsis","False","None","NotImplemented","True"], +type:["Any","Callable","Coroutine","Dict","List","Literal","Generic","Optional","Sequence","Set","Tuple","Type","Union"] +},t={className:"meta",begin:/^(>>>|\.\.\.) /},r={className:"subst",begin:/\{/, +end:/\}/,keywords:s,illegal:/#/},l={begin:/\{\{/,relevance:0},b={ +className:"string",contains:[e.BACKSLASH_ESCAPE],variants:[{ +begin:/([uU]|[bB]|[rR]|[bB][rR]|[rR][bB])?'''/,end:/'''/, +contains:[e.BACKSLASH_ESCAPE,t],relevance:10},{ +begin:/([uU]|[bB]|[rR]|[bB][rR]|[rR][bB])?"""/,end:/"""/, +contains:[e.BACKSLASH_ESCAPE,t],relevance:10},{ +begin:/([fF][rR]|[rR][fF]|[fF])'''/,end:/'''/, +contains:[e.BACKSLASH_ESCAPE,t,l,r]},{begin:/([fF][rR]|[rR][fF]|[fF])"""/, +end:/"""/,contains:[e.BACKSLASH_ESCAPE,t,l,r]},{begin:/([uU]|[rR])'/,end:/'/, +relevance:10},{begin:/([uU]|[rR])"/,end:/"/,relevance:10},{ +begin:/([bB]|[bB][rR]|[rR][bB])'/,end:/'/},{begin:/([bB]|[bB][rR]|[rR][bB])"/, +end:/"/},{begin:/([fF][rR]|[rR][fF]|[fF])'/,end:/'/, +contains:[e.BACKSLASH_ESCAPE,l,r]},{begin:/([fF][rR]|[rR][fF]|[fF])"/,end:/"/, +contains:[e.BACKSLASH_ESCAPE,l,r]},e.APOS_STRING_MODE,e.QUOTE_STRING_MODE] +},o="[0-9](_?[0-9])*",c=`(\\b(${o}))?\\.(${o})|\\b(${o})\\.`,d="\\b|"+i.join("|"),g={ +className:"number",relevance:0,variants:[{ +begin:`(\\b(${o})|(${c}))[eE][+-]?(${o})[jJ]?(?=${d})`},{begin:`(${c})[jJ]?`},{ +begin:`\\b([1-9](_?[0-9])*|0+(_?0)*)[lLjJ]?(?=${d})`},{ +begin:`\\b0[bB](_?[01])+[lL]?(?=${d})`},{begin:`\\b0[oO](_?[0-7])+[lL]?(?=${d})` +},{begin:`\\b0[xX](_?[0-9a-fA-F])+[lL]?(?=${d})`},{begin:`\\b(${o})[jJ](?=${d})` +}]},p={className:"comment",begin:n.lookahead(/# type:/),end:/$/,keywords:s, +contains:[{begin:/# type:/},{begin:/#/,end:/\b\B/,endsWithParent:!0}]},m={ +className:"params",variants:[{className:"",begin:/\(\s*\)/,skip:!0},{begin:/\(/, +end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:s, +contains:["self",t,g,b,e.HASH_COMMENT_MODE]}]};return r.contains=[b,g,t],{ +name:"Python",aliases:["py","gyp","ipython"],unicodeRegex:!0,keywords:s, +illegal:/(<\/|->|\?)|=>/,contains:[t,g,{begin:/\bself\b/},{beginKeywords:"if", +relevance:0},b,p,e.HASH_COMMENT_MODE,{match:[/\bdef/,/\s+/,a],scope:{ +1:"keyword",3:"title.function"},contains:[m]},{variants:[{ +match:[/\bclass/,/\s+/,a,/\s*/,/\(\s*/,a,/\s*\)/]},{match:[/\bclass/,/\s+/,a]}], +scope:{1:"keyword",3:"title.class",6:"title.class.inherited"}},{ +className:"meta",begin:/^[\t ]*@/,end:/(?=#)|$/,contains:[g,m,b]}]}}})() +;hljs.registerLanguage("python",e)})();/*! `xml` grammar compiled for Highlight.js 11.7.0 */ (()=>{var e=(()=>{"use strict";return e=>{ const a=e.regex,n=a.concat(/[\p{L}_]/u,a.optional(/[\p{L}0-9_.-]*:/u),/[\p{L}0-9_.-]*/u),s={ className:"symbol",begin:/&[a-z]+;|&#[0-9]+;|&#x[a-f0-9]+;/},t={begin:/\s/, @@ -360,102 +591,44 @@ contains:[{begin:"^( {4}|\\t)",end:"(\\n)$"}],relevance:0}]},{ begin:"^[-\\*]{3,}",end:"$"},a,{begin:/^\[[^\n]+\]:/,returnBegin:!0,contains:[{ className:"symbol",begin:/\[/,end:/\]/,excludeBegin:!0,excludeEnd:!0},{ className:"link",begin:/:\s*/,end:/$/,excludeBegin:!0}]}]}}})() -;hljs.registerLanguage("markdown",e)})();/*! `plaintext` grammar compiled for Highlight.js 11.7.0 */ -(()=>{var t=(()=>{"use strict";return t=>({name:"Plain text", -aliases:["text","txt"],disableAutodetect:!0})})() -;hljs.registerLanguage("plaintext",t)})();/*! `ocaml` grammar compiled for Highlight.js 11.7.0 */ -(()=>{var e=(()=>{"use strict";return e=>({name:"OCaml",aliases:["ml"], -keywords:{$pattern:"[a-z_]\\w*!?", -keyword:"and as assert asr begin class constraint do done downto else end exception external for fun function functor if in include inherit! inherit initializer land lazy let lor lsl lsr lxor match method!|10 method mod module mutable new object of open! open or private rec sig struct then to try type val! val virtual when while with parser value", -built_in:"array bool bytes char exn|5 float int int32 int64 list lazy_t|5 nativeint|5 string unit in_channel out_channel ref", -literal:"true false"},illegal:/\/\/|>>/,contains:[{className:"literal", -begin:"\\[(\\|\\|)?\\]|\\(\\)",relevance:0},e.COMMENT("\\(\\*","\\*\\)",{ -contains:["self"]}),{className:"symbol",begin:"'[A-Za-z_](?!')[\\w']*"},{ -className:"type",begin:"`[A-Z][\\w']*"},{className:"type", -begin:"\\b[A-Z][\\w']*",relevance:0},{begin:"[a-z_]\\w*'[\\w']*",relevance:0 -},e.inherit(e.APOS_STRING_MODE,{className:"string",relevance:0 -}),e.inherit(e.QUOTE_STRING_MODE,{illegal:null}),{className:"number", -begin:"\\b(0[xX][a-fA-F0-9_]+[Lln]?|0[oO][0-7_]+[Lln]?|0[bB][01_]+[Lln]?|[0-9][0-9_]*([Lln]|(\\.[0-9_]*)?([eE][-+]?[0-9_]+)?)?)", -relevance:0},{begin:/->/}]})})();hljs.registerLanguage("ocaml",e)})();/*! `python` grammar compiled for Highlight.js 11.7.0 */ -(()=>{var e=(()=>{"use strict";return e=>{ -const n=e.regex,a=/[\p{XID_Start}_]\p{XID_Continue}*/u,i=["and","as","assert","async","await","break","case","class","continue","def","del","elif","else","except","finally","for","from","global","if","import","in","is","lambda","match","nonlocal|10","not","or","pass","raise","return","try","while","with","yield"],s={ -$pattern:/[A-Za-z]\w+|__\w+__/,keyword:i, -built_in:["__import__","abs","all","any","ascii","bin","bool","breakpoint","bytearray","bytes","callable","chr","classmethod","compile","complex","delattr","dict","dir","divmod","enumerate","eval","exec","filter","float","format","frozenset","getattr","globals","hasattr","hash","help","hex","id","input","int","isinstance","issubclass","iter","len","list","locals","map","max","memoryview","min","next","object","oct","open","ord","pow","print","property","range","repr","reversed","round","set","setattr","slice","sorted","staticmethod","str","sum","super","tuple","type","vars","zip"], -literal:["__debug__","Ellipsis","False","None","NotImplemented","True"], -type:["Any","Callable","Coroutine","Dict","List","Literal","Generic","Optional","Sequence","Set","Tuple","Type","Union"] -},t={className:"meta",begin:/^(>>>|\.\.\.) /},r={className:"subst",begin:/\{/, -end:/\}/,keywords:s,illegal:/#/},l={begin:/\{\{/,relevance:0},b={ -className:"string",contains:[e.BACKSLASH_ESCAPE],variants:[{ -begin:/([uU]|[bB]|[rR]|[bB][rR]|[rR][bB])?'''/,end:/'''/, -contains:[e.BACKSLASH_ESCAPE,t],relevance:10},{ -begin:/([uU]|[bB]|[rR]|[bB][rR]|[rR][bB])?"""/,end:/"""/, -contains:[e.BACKSLASH_ESCAPE,t],relevance:10},{ -begin:/([fF][rR]|[rR][fF]|[fF])'''/,end:/'''/, -contains:[e.BACKSLASH_ESCAPE,t,l,r]},{begin:/([fF][rR]|[rR][fF]|[fF])"""/, -end:/"""/,contains:[e.BACKSLASH_ESCAPE,t,l,r]},{begin:/([uU]|[rR])'/,end:/'/, -relevance:10},{begin:/([uU]|[rR])"/,end:/"/,relevance:10},{ -begin:/([bB]|[bB][rR]|[rR][bB])'/,end:/'/},{begin:/([bB]|[bB][rR]|[rR][bB])"/, -end:/"/},{begin:/([fF][rR]|[rR][fF]|[fF])'/,end:/'/, -contains:[e.BACKSLASH_ESCAPE,l,r]},{begin:/([fF][rR]|[rR][fF]|[fF])"/,end:/"/, -contains:[e.BACKSLASH_ESCAPE,l,r]},e.APOS_STRING_MODE,e.QUOTE_STRING_MODE] -},o="[0-9](_?[0-9])*",c=`(\\b(${o}))?\\.(${o})|\\b(${o})\\.`,d="\\b|"+i.join("|"),g={ -className:"number",relevance:0,variants:[{ -begin:`(\\b(${o})|(${c}))[eE][+-]?(${o})[jJ]?(?=${d})`},{begin:`(${c})[jJ]?`},{ -begin:`\\b([1-9](_?[0-9])*|0+(_?0)*)[lLjJ]?(?=${d})`},{ -begin:`\\b0[bB](_?[01])+[lL]?(?=${d})`},{begin:`\\b0[oO](_?[0-7])+[lL]?(?=${d})` -},{begin:`\\b0[xX](_?[0-9a-fA-F])+[lL]?(?=${d})`},{begin:`\\b(${o})[jJ](?=${d})` -}]},p={className:"comment",begin:n.lookahead(/# type:/),end:/$/,keywords:s, -contains:[{begin:/# type:/},{begin:/#/,end:/\b\B/,endsWithParent:!0}]},m={ -className:"params",variants:[{className:"",begin:/\(\s*\)/,skip:!0},{begin:/\(/, -end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:s, -contains:["self",t,g,b,e.HASH_COMMENT_MODE]}]};return r.contains=[b,g,t],{ -name:"Python",aliases:["py","gyp","ipython"],unicodeRegex:!0,keywords:s, -illegal:/(<\/|->|\?)|=>/,contains:[t,g,{begin:/\bself\b/},{beginKeywords:"if", -relevance:0},b,p,e.HASH_COMMENT_MODE,{match:[/\bdef/,/\s+/,a],scope:{ -1:"keyword",3:"title.function"},contains:[m]},{variants:[{ -match:[/\bclass/,/\s+/,a,/\s*/,/\(\s*/,a,/\s*\)/]},{match:[/\bclass/,/\s+/,a]}], -scope:{1:"keyword",3:"title.class",6:"title.class.inherited"}},{ -className:"meta",begin:/^[\t ]*@/,end:/(?=#)|$/,contains:[g,m,b]}]}}})() -;hljs.registerLanguage("python",e)})();/*! `reasonml` grammar compiled for Highlight.js 11.7.0 */ -(()=>{var e=(()=>{"use strict";return e=>{ -const n="~?[a-z$_][0-9a-zA-Z$_]*",a="`?[A-Z$_][0-9a-zA-Z$_]*",s="("+["||","++","**","+.","*","/","*.","/.","..."].map((e=>e.split("").map((e=>"\\"+e)).join(""))).join("|")+"|\\|>|&&|==|===)",i="\\s+"+s+"\\s+",r={ -keyword:"and as asr assert begin class constraint do done downto else end exception external for fun function functor if in include inherit initializer land lazy let lor lsl lsr lxor match method mod module mutable new nonrec object of open or private rec sig struct then to try type val virtual when while with", -built_in:"array bool bytes char exn|5 float int int32 int64 list lazy_t|5 nativeint|5 ref string unit ", -literal:"true false" -},l="\\b(0[xX][a-fA-F0-9_]+[Lln]?|0[oO][0-7_]+[Lln]?|0[bB][01_]+[Lln]?|[0-9][0-9_]*([Lln]|(\\.[0-9_]*)?([eE][-+]?[0-9_]+)?)?)",t={ -className:"number",relevance:0,variants:[{begin:l},{begin:"\\(-"+l+"\\)"}]},c={ -className:"operator",relevance:0,begin:s},o=[{className:"identifier", -relevance:0,begin:n},c,t],g=[e.QUOTE_STRING_MODE,c,{className:"module", -begin:"\\b"+a,returnBegin:!0,relevance:0,end:".",contains:[{ -className:"identifier",begin:a,relevance:0}]}],b=[{className:"module", -begin:"\\b"+a,returnBegin:!0,end:".",relevance:0,contains:[{ -className:"identifier",begin:a,relevance:0}]}],m={className:"function", -relevance:0,keywords:r,variants:[{begin:"\\s(\\(\\.?.*?\\)|"+n+")\\s*=>", -end:"\\s*=>",returnBegin:!0,relevance:0,contains:[{className:"params", -variants:[{begin:n},{ -begin:"~?[a-z$_][0-9a-zA-Z$_]*(\\s*:\\s*[a-z$_][0-9a-z$_]*(\\(\\s*('?[a-z$_][0-9a-z$_]*\\s*(,'?[a-z$_][0-9a-z$_]*\\s*)*)?\\))?){0,2}" -},{begin:/\(\s*\)/}]}]},{begin:"\\s\\(\\.?[^;\\|]*\\)\\s*=>",end:"\\s=>", -returnBegin:!0,relevance:0,contains:[{className:"params",relevance:0,variants:[{ -begin:n,end:"(,|\\n|\\))",relevance:0,contains:[c,{className:"typing",begin:":", -end:"(,|\\n)",returnBegin:!0,relevance:0,contains:b}]}]}]},{ -begin:"\\(\\.\\s"+n+"\\)\\s*=>"}]};g.push(m);const d={className:"constructor", -begin:a+"\\(",end:"\\)",illegal:"\\n",keywords:r, -contains:[e.QUOTE_STRING_MODE,c,{className:"params",begin:"\\b"+n}]},u={ -className:"pattern-match",begin:"\\|",returnBegin:!0,keywords:r,end:"=>", -relevance:0,contains:[d,c,{relevance:0,className:"constructor",begin:a}]},v={ -className:"module-access",keywords:r,returnBegin:!0,variants:[{ -begin:"\\b("+a+"\\.)+"+n},{begin:"\\b("+a+"\\.)+\\(",end:"\\)",returnBegin:!0, -contains:[m,{begin:"\\(",end:"\\)",relevance:0,skip:!0}].concat(g)},{ -begin:"\\b("+a+"\\.)+\\{",end:/\}/}],contains:g};return b.push(v),{ -name:"ReasonML",aliases:["re"],keywords:r,illegal:"(:-|:=|\\$\\{|\\+=)", -contains:[e.COMMENT("/\\*","\\*/",{illegal:"^(#,\\/\\/)"}),{ -className:"character",begin:"'(\\\\[^']+|[^'])'",illegal:"\\n",relevance:0 -},e.QUOTE_STRING_MODE,{className:"literal",begin:"\\(\\)",relevance:0},{ -className:"literal",begin:"\\[\\|",end:"\\|\\]",relevance:0,contains:o},{ -className:"literal",begin:"\\[",end:"\\]",relevance:0,contains:o},d,{ -className:"operator",begin:i,illegal:"--\x3e",relevance:0 -},t,e.C_LINE_COMMENT_MODE,u,m,{className:"module-def", -begin:"\\bmodule\\s+"+n+"\\s+"+a+"\\s+=\\s+\\{",end:/\}/,returnBegin:!0, -keywords:r,relevance:0,contains:[{className:"module",relevance:0,begin:a},{ -begin:/\{/,end:/\}/,relevance:0,skip:!0}].concat(g)},v]}}})() -;hljs.registerLanguage("reasonml",e)})(); \ No newline at end of file +;hljs.registerLanguage("markdown",e)})();/*! `c` grammar compiled for Highlight.js 11.7.0 */ +(()=>{var e=(()=>{"use strict";return e=>{const n=e.regex,t=e.COMMENT("//","$",{ +contains:[{begin:/\\\n/}] +}),s="[a-zA-Z_]\\w*::",a="(decltype\\(auto\\)|"+n.optional(s)+"[a-zA-Z_]\\w*"+n.optional("<[^<>]+>")+")",r={ +className:"type",variants:[{begin:"\\b[a-z\\d_]*_t\\b"},{ +match:/\batomic_[a-z]{3,6}\b/}]},i={className:"string",variants:[{ +begin:'(u8?|U|L)?"',end:'"',illegal:"\\n",contains:[e.BACKSLASH_ESCAPE]},{ +begin:"(u8?|U|L)?'(\\\\(x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4,8}|[0-7]{3}|\\S)|.)", +end:"'",illegal:"."},e.END_SAME_AS_BEGIN({ +begin:/(?:u8?|U|L)?R"([^()\\ ]{0,16})\(/,end:/\)([^()\\ ]{0,16})"/})]},l={ +className:"number",variants:[{begin:"\\b(0b[01']+)"},{ +begin:"(-?)\\b([\\d']+(\\.[\\d']*)?|\\.[\\d']+)((ll|LL|l|L)(u|U)?|(u|U)(ll|LL|l|L)?|f|F|b|B)" +},{ +begin:"(-?)(\\b0[xX][a-fA-F0-9']+|(\\b[\\d']+(\\.[\\d']*)?|\\.[\\d']+)([eE][-+]?[\\d']+)?)" +}],relevance:0},o={className:"meta",begin:/#\s*[a-z]+\b/,end:/$/,keywords:{ +keyword:"if else elif endif define undef warning error line pragma _Pragma ifdef ifndef include" +},contains:[{begin:/\\\n/,relevance:0},e.inherit(i,{className:"string"}),{ +className:"string",begin:/<.*?>/},t,e.C_BLOCK_COMMENT_MODE]},c={ +className:"title",begin:n.optional(s)+e.IDENT_RE,relevance:0 +},d=n.optional(s)+e.IDENT_RE+"\\s*\\(",u={ +keyword:["asm","auto","break","case","continue","default","do","else","enum","extern","for","fortran","goto","if","inline","register","restrict","return","sizeof","struct","switch","typedef","union","volatile","while","_Alignas","_Alignof","_Atomic","_Generic","_Noreturn","_Static_assert","_Thread_local","alignas","alignof","noreturn","static_assert","thread_local","_Pragma"], +type:["float","double","signed","unsigned","int","short","long","char","void","_Bool","_Complex","_Imaginary","_Decimal32","_Decimal64","_Decimal128","const","static","complex","bool","imaginary"], +literal:"true false NULL", +built_in:"std string wstring cin cout cerr clog stdin stdout stderr stringstream istringstream ostringstream auto_ptr deque list queue stack vector map set pair bitset multiset multimap unordered_set unordered_map unordered_multiset unordered_multimap priority_queue make_pair array shared_ptr abort terminate abs acos asin atan2 atan calloc ceil cosh cos exit exp fabs floor fmod fprintf fputs free frexp fscanf future isalnum isalpha iscntrl isdigit isgraph islower isprint ispunct isspace isupper isxdigit tolower toupper labs ldexp log10 log malloc realloc memchr memcmp memcpy memset modf pow printf putchar puts scanf sinh sin snprintf sprintf sqrt sscanf strcat strchr strcmp strcpy strcspn strlen strncat strncmp strncpy strpbrk strrchr strspn strstr tanh tan vfprintf vprintf vsprintf endl initializer_list unique_ptr" +},g=[o,r,t,e.C_BLOCK_COMMENT_MODE,l,i],m={variants:[{begin:/=/,end:/;/},{ +begin:/\(/,end:/\)/},{beginKeywords:"new throw return else",end:/;/}], +keywords:u,contains:g.concat([{begin:/\(/,end:/\)/,keywords:u, +contains:g.concat(["self"]),relevance:0}]),relevance:0},p={ +begin:"("+a+"[\\*&\\s]+)+"+d,returnBegin:!0,end:/[{;=]/,excludeEnd:!0, +keywords:u,illegal:/[^\w\s\*&:<>.]/,contains:[{begin:"decltype\\(auto\\)", +keywords:u,relevance:0},{begin:d,returnBegin:!0,contains:[e.inherit(c,{ +className:"title.function"})],relevance:0},{relevance:0,match:/,/},{ +className:"params",begin:/\(/,end:/\)/,keywords:u,relevance:0, +contains:[t,e.C_BLOCK_COMMENT_MODE,i,l,r,{begin:/\(/,end:/\)/,keywords:u, +relevance:0,contains:["self",t,e.C_BLOCK_COMMENT_MODE,i,l,r]}] +},r,t,e.C_BLOCK_COMMENT_MODE,o]};return{name:"C",aliases:["h"],keywords:u, +disableAutodetect:!0,illegal:"=]/,contains:[{ +beginKeywords:"final class struct"},e.TITLE_MODE]}]),exports:{preprocessor:o, +strings:i,keywords:u}}}})();hljs.registerLanguage("c",e)})(); diff --git a/odoc.support/odoc.css b/odoc.support/odoc.css index 8b0ed5a..7230f82 100644 --- a/odoc.support/odoc.css +++ b/odoc.support/odoc.css @@ -1,12 +1,97 @@ @charset "UTF-8"; /* Copyright (c) 2016 The odoc contributors. All rights reserved. Distributed under the ISC license, see terms at the end of the file. - odoc 2.2.0 */ + odoc 2.3.0 */ /* Fonts */ -@import url('https://fonts.googleapis.com/css?family=Fira+Mono:400,500'); -@import url('https://fonts.googleapis.com/css?family=Noticia+Text:400,400i,700'); -@import url('https://fonts.googleapis.com/css?family=Fira+Sans:400,400i,500,500i,600,600i,700,700i'); +/* noticia-text-regular - latin */ +@font-face { + font-family: 'Noticia Text'; + font-style: normal; + font-weight: 400; + src: url('fonts/noticia-text-v15-latin-regular.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ +} + +/* noticia-text-italic - latin */ +@font-face { + font-family: 'Noticia Text'; + font-style: italic; + font-weight: 400; + src: url('fonts/noticia-text-v15-latin-italic.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ +} + +/* noticia-text-700 - latin */ +@font-face { + font-family: 'Noticia Text'; + font-style: normal; + font-weight: 700; + src: url('fonts/noticia-text-v15-latin-700.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ +} + +/* fira-mono-regular - latin */ +@font-face { + font-family: 'Fira Mono'; + font-style: normal; + font-weight: 400; + src: url('fonts/fira-mono-v14-latin-regular.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ +} + +/* fira-mono-500 - latin */ +@font-face { + font-family: 'Fira Mono'; + font-style: normal; + font-weight: 500; + src: url('fonts/fira-mono-v14-latin-500.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ +} + +/* fira-sans-regular - latin */ +@font-face { + font-family: 'Fira Sans'; + font-style: normal; + font-weight: 400; + src: url('fonts/fira-sans-v17-latin-regular.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ +} + +/* fira-sans-italic - latin */ +@font-face { + font-family: 'Fira Sans'; + font-style: italic; + font-weight: 400; + src: url('fonts/fira-sans-v17-latin-italic.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ +} + +/* fira-sans-500 - latin */ +@font-face { + font-family: 'Fira Sans'; + font-style: normal; + font-weight: 500; + src: url('fonts/fira-sans-v17-latin-500.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ +} + +/* fira-sans-500italic - latin */ +@font-face { + font-family: 'Fira Sans'; + font-style: italic; + font-weight: 500; + src: url('fonts/fira-sans-v17-latin-500italic.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ +} + +/* fira-sans-700 - latin */ +@font-face { + font-family: 'Fira Sans'; + font-style: normal; + font-weight: 700; + src: url('fonts/fira-sans-v17-latin-700.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ +} + +/* fira-sans-700italic - latin */ +@font-face { + font-family: 'Fira Sans'; + font-style: italic; + font-weight: 700; + src: url('fonts/fira-sans-v17-latin-700italic.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ +} + :root, .light:root { @@ -14,6 +99,7 @@ --color: #333333; --link-color: #2C94BD; + --source-color: grey; --anchor-hover: #555; --anchor-color: #d5d5d5; --xref-shadow: #cc6666; @@ -33,6 +119,7 @@ --toc-list-border: #ccc; --spec-summary-border-color: #5c9cf5; + --spec-label-color: green; --spec-summary-background: var(--code-background); --spec-summary-hover-background: #ebeff2; --spec-details-after-background: rgba(0, 4, 15, 0.05); @@ -72,6 +159,8 @@ --hljs-type: #ac885b; --hljs-meta: #82aaff; --hljs-variable: #cf6a4c; + + --spec-label-color: lightgreen; } @media (prefers-color-scheme: dark) { @@ -118,6 +207,8 @@ --hljs-type: #ac885b; --hljs-meta: #82aaff; --hljs-variable: #cf6a4c; + + --spec-label-color: lightgreen; } } @@ -142,6 +233,7 @@ table { html { font-size: 15px; + scroll-behavior: smooth; } body { @@ -149,16 +241,23 @@ body { background: #FFFFFF; color: var(--color); background-color: var(--main-background); + font-family: "Noticia Text", Georgia, serif; + line-height: 1.5; } body { - max-width: 100ex; margin-left: calc(10vw + 20ex); margin-right: 4ex; margin-top: 20px; margin-bottom: 50px; - font-family: "Noticia Text", Georgia, serif; - line-height: 1.5; +} + +body.odoc { + max-width: 100ex; +} + +body.odoc-src { + margin-right: calc(10vw + 20ex); } header { @@ -238,6 +337,10 @@ a { color: var(--link-color); } +.odoc-src pre a { + color: inherit; +} + a:hover { box-shadow: 0 1px 0 0 var(--link-color); } @@ -289,6 +392,14 @@ a.anchor { box-shadow: 0 1px 0 0 var(--xref-shadow); } +/* Source links float inside preformated text or headings. */ +a.source_link { + float: right; + color: var(--source-color); + font-family: "Fira Sans", Helvetica, Arial, sans-serif; + font-size: initial; +} + /* Section and document divisions. Until at least 4.03 many of the modules of the stdlib start at .h7, we restart the sequence there like h2 */ @@ -372,32 +483,32 @@ tt, code, pre { font-weight: 400; } -pre { +.odoc pre { padding: 0.1em; border: 1px solid var(--pre-border-color); border-radius: 5px; overflow-x: auto; } -p code, -li code { +.odoc p code, +.odoc li code { background-color: var(--li-code-background); color: var(--li-code-color); border-radius: 3px; padding: 0 0.3ex; } -p a > code { +p a > code, li a > code { color: var(--link-color); } -code { +.odoc code { white-space: pre-wrap; } /* Code blocks (e.g. Examples) */ -pre code { +.odoc pre code { font-size: 0.893rem; } @@ -419,6 +530,10 @@ pre code { padding: 0.35em 0.5em; } +.spec .label, .spec .optlabel { + color: var(--spec-label-color); +} + li:not(:last-child) > .def-doc { margin-bottom: 15px; } @@ -536,6 +651,12 @@ td.def-doc *:first-child { .at-tags li { padding-left: 3ex; text-indent: -3ex; } .at-tags .at-tag { text-transform: capitalize } +/* Alert emoji */ + +.alert::before, .deprecated::before { + content: '⚠️ '; +} + /* Lists of modules */ .modules { list-style-type: none; margin-left: -3ex; } @@ -674,10 +795,26 @@ td.def-doc *:first-child { padding-left: 12px; } +/* Tables */ + +.odoc-table { + margin: 1em; +} + +.odoc-table td, .odoc-table th { + padding-left: 0.5em; + padding-right: 0.5em; + border: 1px solid black; +} + +.odoc-table th { + font-weight: bold; +} + /* Mobile adjustements. */ -@media only screen and (max-width: 95ex) { - body.odoc { +@media only screen and (max-width: 110ex) { + body { margin: 2em; } .odoc-toc { @@ -704,6 +841,47 @@ td.def-doc *:first-child { } } +/* Source code. */ + +.source_container { + display: flex; +} + +.source_line_column { + padding-right: 0.5em; + text-align: right; + background: #eee8d5; +} + +.source_line { + padding: 0 1em; +} + +.source_code { + flex-grow: 1; + background: #fdf6e3; + padding: 0 0.3em; + color: #657b83; +} + +/* Source directories */ + +.odoc-directory::before { + content: "📁"; + margin: 0.3em; + font-size: 1.3em; +} + +.odoc-file::before { + content: "📄"; + margin: 0.3em; + font-size: 1.3em; +} + +.odoc-folder-list { + list-style: none; +} + /* Syntax highlighting (based on github-gist) */ .hljs { @@ -777,6 +955,34 @@ td.def-doc *:first-child { text-decoration: underline; } +.VAL, .TYPE, .LET, .REC, .IN, .OPEN, .NONREC, .MODULE, .METHOD, .LETOP, .INHERIT, .INCLUDE, .FUNCTOR, .EXTERNAL, .CONSTRAINT, .ASSERT, .AND, .END, .CLASS, .STRUCT, .SIG { + color: #859900;; +} + +.WITH, .WHILE, .WHEN, .VIRTUAL, .TRY, .TO, .THEN, .PRIVATE, .OF, .NEW, .MUTABLE, .MATCH, .LAZY, .IF, .FUNCTION, .FUN, .FOR, .EXCEPTION, .ELSE, .TO, .DOWNTO, .DO, .DONE, .BEGIN, .AS { + color: #cb4b16; +} + +.TRUE, .FALSE { + color: #b58900; +} + +.failwith, .INT, .SEMISEMI, .LIDENT { + color: #2aa198; +} + +.STRING, .CHAR, .UIDENT { + color: #b58900; +} + +.DOCSTRING { + color: #268bd2; +} + +.COMMENT { + color: #93a1a1; +} + /*--------------------------------------------------------------------------- Copyright (c) 2016 The odoc contributors