2019-05-13 00:46:25 +04:00
|
|
|
(* Regions of a file *)
|
|
|
|
|
2019-12-06 14:49:19 +04:00
|
|
|
(* A shorthand *)
|
|
|
|
|
2019-05-13 00:46:25 +04:00
|
|
|
let sprintf = Printf.sprintf
|
|
|
|
|
2019-12-06 14:49:19 +04:00
|
|
|
(* The object type for regions *)
|
|
|
|
|
2019-05-13 00:46:25 +04:00
|
|
|
type t = <
|
|
|
|
start : Pos.t;
|
|
|
|
stop : Pos.t;
|
|
|
|
|
|
|
|
(* Setters *)
|
|
|
|
|
|
|
|
shift_bytes : int -> t;
|
|
|
|
shift_one_uchar : int -> t;
|
|
|
|
set_file : string -> t;
|
|
|
|
|
|
|
|
(* Getters *)
|
|
|
|
|
|
|
|
file : string;
|
|
|
|
pos : Pos.t * Pos.t;
|
|
|
|
byte_pos : Lexing.position * Lexing.position;
|
|
|
|
|
|
|
|
(* Predicates *)
|
|
|
|
|
|
|
|
is_ghost : bool;
|
|
|
|
|
|
|
|
(* Conversions to [string] *)
|
|
|
|
|
|
|
|
to_string : ?file:bool -> ?offsets:bool -> [`Byte | `Point] -> string;
|
|
|
|
compact : ?file:bool -> ?offsets:bool -> [`Byte | `Point] -> string
|
|
|
|
>
|
|
|
|
|
2019-12-06 14:49:19 +04:00
|
|
|
(* A synonym *)
|
|
|
|
|
2019-05-13 00:46:25 +04:00
|
|
|
type region = t
|
|
|
|
|
2019-12-06 14:49:19 +04:00
|
|
|
(* A convenience *)
|
|
|
|
|
2019-05-13 00:46:25 +04:00
|
|
|
type 'a reg = {region: t; value: 'a}
|
|
|
|
|
|
|
|
(* Injections *)
|
|
|
|
|
|
|
|
exception Invalid
|
|
|
|
|
|
|
|
let make ~(start: Pos.t) ~(stop: Pos.t) =
|
|
|
|
if start#file <> stop#file || start#byte_offset > stop#byte_offset
|
|
|
|
then raise Invalid
|
|
|
|
else
|
|
|
|
object
|
|
|
|
val start = start
|
|
|
|
method start = start
|
|
|
|
val stop = stop
|
|
|
|
method stop = stop
|
|
|
|
|
|
|
|
method shift_bytes len =
|
|
|
|
let start = start#shift_bytes len
|
|
|
|
and stop = stop#shift_bytes len
|
|
|
|
in {< start = start; stop = stop >}
|
|
|
|
|
|
|
|
method shift_one_uchar len =
|
|
|
|
let start = start#shift_one_uchar len
|
|
|
|
and stop = stop#shift_one_uchar len
|
|
|
|
in {< start = start; stop = stop >}
|
|
|
|
|
|
|
|
method set_file name =
|
|
|
|
let start = start#set_file name
|
|
|
|
and stop = stop#set_file name
|
|
|
|
in {< start = start; stop = stop >}
|
|
|
|
|
|
|
|
(* Getters *)
|
|
|
|
|
|
|
|
method file = start#file
|
|
|
|
method pos = start, stop
|
|
|
|
method byte_pos = start#byte, stop#byte
|
|
|
|
|
|
|
|
(* Predicates *)
|
|
|
|
|
|
|
|
method is_ghost = start#is_ghost && stop#is_ghost
|
|
|
|
|
|
|
|
(* Conversions to strings *)
|
|
|
|
|
|
|
|
method to_string ?(file=true) ?(offsets=true) mode =
|
2019-05-24 21:31:03 +04:00
|
|
|
let horizontal = if offsets then "character" else "column"
|
2019-05-13 00:46:25 +04:00
|
|
|
and start_offset =
|
|
|
|
if offsets then start#offset mode else start#column mode
|
|
|
|
and stop_offset =
|
|
|
|
if offsets then stop#offset mode else stop#column mode in
|
|
|
|
let info =
|
|
|
|
if file
|
|
|
|
then sprintf "in file \"%s\", line %i, %s"
|
|
|
|
(String.escaped start#file) start#line horizontal
|
|
|
|
else sprintf "at line %i, %s" start#line horizontal
|
|
|
|
in if stop#line = start#line
|
|
|
|
then sprintf "%ss %i-%i" info start_offset stop_offset
|
|
|
|
else sprintf "%s %i to line %i, %s %i"
|
|
|
|
info start_offset stop#line horizontal stop_offset
|
|
|
|
|
|
|
|
method compact ?(file=true) ?(offsets=true) mode =
|
2019-11-06 20:23:49 +04:00
|
|
|
let prefix = if file then start#file ^ ":" else ""
|
|
|
|
and start_str = start#anonymous ~offsets mode
|
2019-05-13 00:46:25 +04:00
|
|
|
and stop_str = stop#anonymous ~offsets mode in
|
|
|
|
if start#file = stop#file then
|
2019-11-06 20:23:49 +04:00
|
|
|
if start#line = stop#line then
|
|
|
|
sprintf "%s%s-%i" prefix start_str
|
|
|
|
(if offsets then stop#offset mode
|
|
|
|
else stop#column mode)
|
Refactoring of Ligodity (CameLIGO) and making an AST pretty-printer
- AST.ml/AST.mli:
- The AST now distinguishes the constructors `None` and `Some` as being
predefined, as in PascaLIGO. See type `AST.constr_pattern`.
- I removed the nodes specific to Liquidity,
e.g. `let%entry`, and, in particular, the natural literals
ending with `p`. Now it should be `n`, as in `10n`.
- I renamed the node `TAlias` to `TVar`.
- I have applied the rule of expanding type expressions after `of` when
those were not records.
- The type of the argument to a data constructor is now
`type_expr`, instead of `cartesian`.
- I added the patterns for bytes (`PBytes`) and natural literals (`PNat`).
- I renamed the node `Sugar` into
`PListComp` (meaning "pattern of list comprehension").
- Record types in CameLIGO now must have at least one field declaration.
- Replaced the type `closing` and `opening` with one type `compound`,
which captures only the right combinations of opening and closing.
- Components of tuples in a selection must not be written
between parentheses. For example, `a.b.(1).(0)` is now
`a.b.1.0`, as in PascaLIGO.
- LexToken.mli/LexToken.mll
- I renamed the string literal `Str` into `String`.
- I added the tokens `C_None` and `C_Some` (to distinguish the
constructors `None` and `Some`. See AST.ml)
- Fixed the function `mk_sym` so it does not fail with `failwith`, but
with `Error Invalid_symbol`.
- Lexer.mll (shared)
- I removed the character `%` from the identifiers (used to
support Liquidity, like `entry%point` and `match%nat`).
- I adde to the hint on broken strings: "or insert a backslash"
(from a Gitlab issue).
- ParToken.mly
- I added the tokens `C_None` and `C_Some` (to distinguish the
constructors `None` and `Some`. See AST.ml and LexToken.mll)
- Parser.mly
- Fixed the order of declarations in the AST (it was reversed).
- I removed syntax support for Liquidity.
- I added user-defined constructor applications to irrefutable
patterns (the ones afer a `let`), even though only the type
checker can decide that they are truly irrefutable because they
are the only constructors of their types.
- I added natural numbers and bytes to patterns.
- Access of tuple components do not require parentheses now, like
`a.b.1.0`.
- I refactored the semantic actions.
- I added the empty sequence `begin end`.
- ParserLog.ml/ParserLog.mli
- I added a pretty-printer for the AST (with source locations).
- ParserMain.ml
- The CLI for the pretty-printer is now `--verbose=ast`.
- The old CLI `--verbose=ast` is now `--verbose=ast-tokens`.
- ligodity.ml (simplifier)
- I removed the constructions of sets, lists and maps with
`Set [...]`, `List [...]` and `Map [...]`, as there are already
better ways (that is, more like the OCaml's way), like
`Set.literal [...]` and `Map.literal [...]`. (The case for lists
was entirely redundant with the rest of the language as it is.)
- Everywhere there is now a non-empty list of elements, I made a
change. In particular, I removed a corner case ("let without
binding"), thanks to more precise OCaml types for non-empty
lists.
- I ported all the changes to the AST above.
- region.ml (vendors)
- I changed the method `compact` so the end-line is not repeated
if it is the same as the start line: this is even more compact. I
use this in the new pretty-printer for the AST (see above)
- I updated all the CameLIGO contracts.
2019-11-05 02:51:47 +04:00
|
|
|
else
|
2019-11-06 20:23:49 +04:00
|
|
|
sprintf "%s%s-%s" prefix start_str stop_str
|
|
|
|
else sprintf "%s:%s-%s:%s"
|
|
|
|
start#file start_str stop#file stop_str
|
2019-05-13 00:46:25 +04:00
|
|
|
end
|
|
|
|
|
|
|
|
(* Special regions *)
|
|
|
|
|
|
|
|
let ghost = make ~start:Pos.ghost ~stop:Pos.ghost
|
|
|
|
|
2019-11-18 19:10:48 +04:00
|
|
|
let wrap_ghost value = {value ; region = ghost}
|
|
|
|
|
2019-05-13 00:46:25 +04:00
|
|
|
let min = make ~start:Pos.min ~stop:Pos.min
|
|
|
|
|
|
|
|
(* Comparisons *)
|
|
|
|
|
|
|
|
let equal r1 r2 =
|
|
|
|
r1#file = r2#file
|
|
|
|
&& Pos.equal r1#start r2#start
|
|
|
|
&& Pos.equal r1#stop r2#stop
|
|
|
|
|
|
|
|
let lt r1 r2 =
|
|
|
|
r1#file = r2#file
|
|
|
|
&& not r1#is_ghost
|
|
|
|
&& not r2#is_ghost
|
|
|
|
&& Pos.lt r1#start r2#start
|
|
|
|
&& Pos.lt r1#stop r2#stop
|
|
|
|
|
|
|
|
let cover r1 r2 =
|
|
|
|
if r1#is_ghost
|
|
|
|
then r2
|
|
|
|
else if r2#is_ghost
|
|
|
|
then r1
|
|
|
|
else if lt r1 r2
|
|
|
|
then make ~start:r1#start ~stop:r2#stop
|
|
|
|
else make ~start:r2#start ~stop:r1#stop
|