Eased the translation from Ligodity AST to Liquidity AST.
More precisely, * I commented out the operator "@" on lists in Ligodity (it can be implemented as a function, as a workaround). * I removed the parallel "let" construct (hence the "and" keyword). * I renamed the type "field_assignment" into "field_assign", in order to match Pascaligo AST. * The reading of the command-line options is now done by calling the function [EvalOpt.read], instead of an ugly side-effect when loading the binary of the module. Options are now found in a record of type [EvalOpt.options]. * I added support in the Ligodity lexer for #include CPP directives.
This commit is contained in:
parent
fdf7704a7c
commit
af8d1083b7
@ -109,14 +109,12 @@ type t = {
|
|||||||
and ast = t
|
and ast = t
|
||||||
|
|
||||||
and declaration =
|
and declaration =
|
||||||
Let of (kwd_let * let_bindings) reg
|
Let of (kwd_let * let_binding) reg
|
||||||
| LetEntry of (kwd_let_entry * let_binding) reg
|
| LetEntry of (kwd_let_entry * let_binding) reg
|
||||||
| TypeDecl of type_decl reg
|
| TypeDecl of type_decl reg
|
||||||
|
|
||||||
(* Non-recursive values *)
|
(* Non-recursive values *)
|
||||||
|
|
||||||
and let_bindings = (let_binding, kwd_and) Utils.nsepseq
|
|
||||||
|
|
||||||
and let_binding = {
|
and let_binding = {
|
||||||
pattern : pattern;
|
pattern : pattern;
|
||||||
lhs_type : (colon * type_expr) option;
|
lhs_type : (colon * type_expr) option;
|
||||||
@ -238,7 +236,7 @@ and closing =
|
|||||||
and list_expr =
|
and list_expr =
|
||||||
Cons of cons bin_op reg
|
Cons of cons bin_op reg
|
||||||
| List of expr injection reg
|
| List of expr injection reg
|
||||||
| Append of (expr * append * expr) reg
|
(*| Append of (expr * append * expr) reg*)
|
||||||
|
|
||||||
and string_expr =
|
and string_expr =
|
||||||
Cat of cat bin_op reg
|
Cat of cat bin_op reg
|
||||||
@ -295,9 +293,9 @@ and selection =
|
|||||||
FieldName of variable
|
FieldName of variable
|
||||||
| Component of (string * Z.t) reg par reg
|
| Component of (string * Z.t) reg par reg
|
||||||
|
|
||||||
and record_expr = field_assignment reg injection reg
|
and record_expr = field_assign reg injection reg
|
||||||
|
|
||||||
and field_assignment = {
|
and field_assign = {
|
||||||
field_name : field_name;
|
field_name : field_name;
|
||||||
assignment : equal;
|
assignment : equal;
|
||||||
field_expr : expr
|
field_expr : expr
|
||||||
@ -320,7 +318,7 @@ and 'a case_clause = {
|
|||||||
rhs : 'a
|
rhs : 'a
|
||||||
}
|
}
|
||||||
|
|
||||||
and let_in = kwd_let * let_bindings * kwd_in * expr
|
and let_in = kwd_let * let_binding * kwd_in * expr
|
||||||
|
|
||||||
and fun_expr = (kwd_fun * variable * arrow * expr) reg
|
and fun_expr = (kwd_fun * variable * arrow * expr) reg
|
||||||
|
|
||||||
@ -372,7 +370,8 @@ let region_of_string_expr = function
|
|||||||
String {region;_} | Cat {region;_} -> region
|
String {region;_} | Cat {region;_} -> region
|
||||||
|
|
||||||
let region_of_list_expr = function
|
let region_of_list_expr = function
|
||||||
Cons {region; _} | List {region; _} | Append {region; _} -> region
|
Cons {region; _} | List {region; _}
|
||||||
|
(* | Append {region; _}*) -> region
|
||||||
|
|
||||||
let region_of_expr = function
|
let region_of_expr = function
|
||||||
ELogic e -> region_of_logic_expr e
|
ELogic e -> region_of_logic_expr e
|
||||||
@ -397,12 +396,12 @@ let norm_fun region kwd_fun pattern eq expr =
|
|||||||
let value =
|
let value =
|
||||||
match pattern with
|
match pattern with
|
||||||
PVar v -> kwd_fun, v, eq, expr
|
PVar v -> kwd_fun, v, eq, expr
|
||||||
| _ -> let value = Utils.gen_sym () in
|
| _ -> let value = Utils.gen_sym () in
|
||||||
let fresh = Region.{region=Region.ghost; value} in
|
let fresh = Region.{region=Region.ghost; value} in
|
||||||
let bindings = {pattern; eq;
|
let binding = {pattern; eq;
|
||||||
lhs_type=None; let_rhs = EVar fresh}, [] in
|
lhs_type=None; let_rhs = EVar fresh} in
|
||||||
let let_in = ghost_let, bindings, ghost_in, expr in
|
let let_in = ghost_let, binding, ghost_in, expr in
|
||||||
let expr = ELetIn {value=let_in; region=Region.ghost}
|
let expr = ELetIn {value=let_in; region=Region.ghost}
|
||||||
in kwd_fun, fresh, ghost_arrow, expr
|
in kwd_fun, fresh, ghost_arrow, expr
|
||||||
in Region.{region; value}
|
in Region.{region; value}
|
||||||
|
|
||||||
@ -433,7 +432,7 @@ let rec unparse' = function
|
|||||||
EFun {value=_,var,arrow,expr; _} ->
|
EFun {value=_,var,arrow,expr; _} ->
|
||||||
if var.region#is_ghost then
|
if var.region#is_ghost then
|
||||||
match expr with
|
match expr with
|
||||||
ELetIn {value = _,({pattern;eq;_},[]),_,expr; _} ->
|
ELetIn {value = _,{pattern;eq;_},_,expr; _} ->
|
||||||
if eq#is_ghost then
|
if eq#is_ghost then
|
||||||
let patterns, sep, e = unparse' expr
|
let patterns, sep, e = unparse' expr
|
||||||
in Utils.nseq_cons pattern patterns, sep, e
|
in Utils.nseq_cons pattern patterns, sep, e
|
||||||
@ -485,9 +484,9 @@ let rec print_tokens ?(undo=false) {decl;eof} =
|
|||||||
Utils.nseq_iter (print_statement undo) decl; print_token eof "EOF"
|
Utils.nseq_iter (print_statement undo) decl; print_token eof "EOF"
|
||||||
|
|
||||||
and print_statement undo = function
|
and print_statement undo = function
|
||||||
Let {value=kwd_let, let_bindings; _} ->
|
Let {value=kwd_let, let_binding; _} ->
|
||||||
print_token kwd_let "let";
|
print_token kwd_let "let";
|
||||||
print_let_bindings undo let_bindings
|
print_let_binding undo let_binding
|
||||||
| LetEntry {value=kwd_let_entry, let_binding; _} ->
|
| LetEntry {value=kwd_let_entry, let_binding; _} ->
|
||||||
print_token kwd_let_entry "let%entry";
|
print_token kwd_let_entry "let%entry";
|
||||||
print_let_binding undo let_binding
|
print_let_binding undo let_binding
|
||||||
@ -588,8 +587,6 @@ and print_terminator = function
|
|||||||
Some semi -> print_token semi ";"
|
Some semi -> print_token semi ";"
|
||||||
| None -> ()
|
| None -> ()
|
||||||
|
|
||||||
and print_let_bindings undo = print_nsepseq "and" (print_let_binding undo)
|
|
||||||
|
|
||||||
and print_let_binding undo {pattern; lhs_type; eq; let_rhs} =
|
and print_let_binding undo {pattern; lhs_type; eq; let_rhs} =
|
||||||
print_pattern pattern;
|
print_pattern pattern;
|
||||||
(match lhs_type with
|
(match lhs_type with
|
||||||
@ -706,10 +703,10 @@ and print_list_expr undo = function
|
|||||||
print_token op "::";
|
print_token op "::";
|
||||||
print_expr undo arg2
|
print_expr undo arg2
|
||||||
| List e -> print_injection (print_expr undo) e
|
| List e -> print_injection (print_expr undo) e
|
||||||
| Append {value=e1,append,e2; _} ->
|
(*| Append {value=e1,append,e2; _} ->
|
||||||
print_expr undo e1;
|
print_expr undo e1;
|
||||||
print_token append "@";
|
print_token append "@";
|
||||||
print_expr undo e2
|
print_expr undo e2 *)
|
||||||
|
|
||||||
and print_arith_expr undo = function
|
and print_arith_expr undo = function
|
||||||
Add {value={arg1;op;arg2}; _} ->
|
Add {value={arg1;op;arg2}; _} ->
|
||||||
@ -763,9 +760,9 @@ and print_comp_expr undo = function
|
|||||||
print_expr undo arg1; print_token op "="; print_expr undo arg2
|
print_expr undo arg1; print_token op "="; print_expr undo arg2
|
||||||
|
|
||||||
and print_record_expr undo e =
|
and print_record_expr undo e =
|
||||||
print_injection (print_field_assignment undo) e
|
print_injection (print_field_assign undo) e
|
||||||
|
|
||||||
and print_field_assignment undo {value; _} =
|
and print_field_assign undo {value; _} =
|
||||||
let {field_name; assignment; field_expr} = value in
|
let {field_name; assignment; field_expr} = value in
|
||||||
print_var field_name;
|
print_var field_name;
|
||||||
print_token assignment "=";
|
print_token assignment "=";
|
||||||
@ -796,9 +793,9 @@ and print_case_clause undo {value; _} =
|
|||||||
print_token arrow "->";
|
print_token arrow "->";
|
||||||
print_expr undo rhs
|
print_expr undo rhs
|
||||||
|
|
||||||
and print_let_in undo (kwd_let, let_bindings, kwd_in, expr) =
|
and print_let_in undo (kwd_let, let_binding, kwd_in, expr) =
|
||||||
print_token kwd_let "let";
|
print_token kwd_let "let";
|
||||||
print_let_bindings undo let_bindings;
|
print_let_binding undo let_binding;
|
||||||
print_token kwd_in "in";
|
print_token kwd_in "in";
|
||||||
print_expr undo expr
|
print_expr undo expr
|
||||||
|
|
||||||
@ -819,3 +816,7 @@ and print_conditional undo {value; _} =
|
|||||||
print_token kwd_else "else";
|
print_token kwd_else "else";
|
||||||
print_expr undo ifnot;
|
print_expr undo ifnot;
|
||||||
print_token ghost ")"
|
print_token ghost ")"
|
||||||
|
|
||||||
|
let rec unpar = function
|
||||||
|
EPar {value={inside=expr;_}; _} -> unpar expr
|
||||||
|
| e -> e
|
||||||
|
@ -118,16 +118,13 @@ and ast = t
|
|||||||
and eof = Region.t
|
and eof = Region.t
|
||||||
|
|
||||||
and declaration =
|
and declaration =
|
||||||
Let of (kwd_let * let_bindings) reg (* let p = e and ... *)
|
Let of (kwd_let * let_binding) reg (* let p = e *)
|
||||||
| LetEntry of (kwd_let_entry * let_binding) reg (* let%entry p = e and ... *)
|
| LetEntry of (kwd_let_entry * let_binding) reg (* let%entry p = e *)
|
||||||
| TypeDecl of type_decl reg (* type ... *)
|
| TypeDecl of type_decl reg (* type ... *)
|
||||||
|
|
||||||
(* Non-recursive values *)
|
(* Non-recursive values *)
|
||||||
|
|
||||||
and let_bindings =
|
and let_binding = { (* p = e p : t = e *)
|
||||||
(let_binding, kwd_and) Utils.nsepseq (* p1 = e1 and p2 = e2 ... *)
|
|
||||||
|
|
||||||
and let_binding = { (* p = e p : t = e *)
|
|
||||||
pattern : pattern;
|
pattern : pattern;
|
||||||
lhs_type : (colon * type_expr) option;
|
lhs_type : (colon * type_expr) option;
|
||||||
eq : equal;
|
eq : equal;
|
||||||
@ -248,7 +245,7 @@ and closing =
|
|||||||
and list_expr =
|
and list_expr =
|
||||||
Cons of cat bin_op reg (* e1 :: e3 *)
|
Cons of cat bin_op reg (* e1 :: e3 *)
|
||||||
| List of expr injection reg (* [e1; e2; ...] *)
|
| List of expr injection reg (* [e1; e2; ...] *)
|
||||||
| Append of (expr * append * expr) reg (* e1 @ e2 *)
|
(*| Append of (expr * append * expr) reg *) (* e1 @ e2 *)
|
||||||
|
|
||||||
and string_expr =
|
and string_expr =
|
||||||
Cat of cat bin_op reg (* e1 ^ e2 *)
|
Cat of cat bin_op reg (* e1 ^ e2 *)
|
||||||
@ -305,9 +302,9 @@ and selection =
|
|||||||
FieldName of variable
|
FieldName of variable
|
||||||
| Component of (string * Z.t) reg par reg
|
| Component of (string * Z.t) reg par reg
|
||||||
|
|
||||||
and record_expr = field_assignment reg injection reg
|
and record_expr = field_assign reg injection reg
|
||||||
|
|
||||||
and field_assignment = {
|
and field_assign = {
|
||||||
field_name : field_name;
|
field_name : field_name;
|
||||||
assignment : equal;
|
assignment : equal;
|
||||||
field_expr : expr
|
field_expr : expr
|
||||||
@ -330,7 +327,7 @@ and 'a case_clause = {
|
|||||||
rhs : 'a
|
rhs : 'a
|
||||||
}
|
}
|
||||||
|
|
||||||
and let_in = kwd_let * let_bindings * kwd_in * expr
|
and let_in = kwd_let * let_binding * kwd_in * expr
|
||||||
|
|
||||||
and fun_expr = (kwd_fun * variable * arrow * expr) reg
|
and fun_expr = (kwd_fun * variable * arrow * expr) reg
|
||||||
|
|
||||||
@ -479,3 +476,11 @@ val print_tokens : ?undo:bool -> ast -> unit
|
|||||||
|
|
||||||
val region_of_pattern : pattern -> Region.t
|
val region_of_pattern : pattern -> Region.t
|
||||||
val region_of_expr : expr -> Region.t
|
val region_of_expr : expr -> Region.t
|
||||||
|
|
||||||
|
(* Simplifications *)
|
||||||
|
|
||||||
|
(* The call [unpar e] is the expression [e] if [e] is not
|
||||||
|
parenthesised, otherwise it is the non-parenthesised expressions it
|
||||||
|
contains. *)
|
||||||
|
|
||||||
|
val unpar : expr -> expr
|
||||||
|
@ -1,5 +1,14 @@
|
|||||||
(* Parsing the command-line option for the Mini-ML compiler/interpreter *)
|
(* Parsing the command-line option for the Mini-ML compiler/interpreter *)
|
||||||
|
|
||||||
|
type options = {
|
||||||
|
input : string option;
|
||||||
|
eval : bool;
|
||||||
|
compile : string option;
|
||||||
|
libs : string list;
|
||||||
|
verbose : Utils.String.Set.t;
|
||||||
|
raw_edits : bool
|
||||||
|
}
|
||||||
|
|
||||||
let abort msg =
|
let abort msg =
|
||||||
Utils.highlight (Printf.sprintf "Command-line error: %s" msg); exit 1
|
Utils.highlight (Printf.sprintf "Command-line error: %s" msg); exit 1
|
||||||
|
|
||||||
@ -37,6 +46,8 @@ and verbose = ref Utils.String.Set.empty
|
|||||||
and libs = ref []
|
and libs = ref []
|
||||||
and raw_edits = ref false
|
and raw_edits = ref false
|
||||||
|
|
||||||
|
let verb_str = ref ""
|
||||||
|
|
||||||
let set_opt var err =
|
let set_opt var err =
|
||||||
Some (fun x -> if !var = None then var := Some x else raise (Getopt.Error err))
|
Some (fun x -> if !var = None then var := Some x else raise (Getopt.Error err))
|
||||||
|
|
||||||
@ -69,11 +80,6 @@ let anonymous arg =
|
|||||||
None -> input := Some arg
|
None -> input := Some arg
|
||||||
| Some _ -> abort (sprintf "Multiple inputs")
|
| Some _ -> abort (sprintf "Multiple inputs")
|
||||||
|
|
||||||
(* Parsing the command-line options *)
|
|
||||||
|
|
||||||
let () = try Getopt.parse_cmdline specs anonymous with
|
|
||||||
Getopt.Error msg -> abort msg
|
|
||||||
|
|
||||||
(* Checking options *)
|
(* Checking options *)
|
||||||
|
|
||||||
let string_of convert = function
|
let string_of convert = function
|
||||||
@ -86,56 +92,53 @@ let string_of_path p =
|
|||||||
|
|
||||||
let quote s = Printf.sprintf "\"%s\"" s
|
let quote s = Printf.sprintf "\"%s\"" s
|
||||||
|
|
||||||
let verb_str =
|
|
||||||
let apply e a =
|
|
||||||
if a <> "" then Printf.sprintf "%s, %s" e a else e
|
|
||||||
in Utils.String.Set.fold apply !verbose ""
|
|
||||||
|
|
||||||
let print_opt () =
|
let print_opt () =
|
||||||
printf "COMMAND LINE\n";
|
printf "COMMAND LINE\n";
|
||||||
printf "input = %s\n" (string_of quote !input);
|
printf "input = %s\n" (string_of quote !input);
|
||||||
printf "compile = %s\n" (string_of quote !compile);
|
printf "compile = %s\n" (string_of quote !compile);
|
||||||
printf "eval = %B\n" !eval;
|
printf "eval = %B\n" !eval;
|
||||||
printf "raw_edits = %b\n" !raw_edits;
|
printf "raw_edits = %b\n" !raw_edits;
|
||||||
printf "verbose = %s\n" verb_str;
|
printf "verbose = %s\n" !verb_str;
|
||||||
printf "libs = %s\n" (string_of_path !libs)
|
printf "libs = %s\n" (string_of_path !libs)
|
||||||
|
|
||||||
let () = if Utils.String.Set.mem "cmdline" !verbose then print_opt ()
|
let check () =
|
||||||
|
let () =
|
||||||
|
if Utils.String.Set.mem "cmdline" !verbose then print_opt () in
|
||||||
|
|
||||||
let input =
|
let input =
|
||||||
match !input with
|
match !input with
|
||||||
None | Some "-" ->
|
None | Some "-" ->
|
||||||
if !compile <> None then
|
if !compile <> None then
|
||||||
abort "An input file is missing (for compilation)."
|
abort "An input file is missing (for compilation)."
|
||||||
else !input
|
else !input
|
||||||
| Some file_path ->
|
| Some file_path ->
|
||||||
if Filename.check_suffix file_path ".mml"
|
if Filename.check_suffix file_path ".mml"
|
||||||
then if Sys.file_exists file_path
|
then if Sys.file_exists file_path
|
||||||
then Some file_path
|
then Some file_path
|
||||||
else abort "Source file not found."
|
else abort "Source file not found."
|
||||||
else abort "Source file lacks the extension .mml."
|
else abort "Source file lacks the extension .mml." in
|
||||||
|
|
||||||
let compile =
|
let compile =
|
||||||
match !compile with
|
match !compile with
|
||||||
Some _ when !eval -> abort "Options -e and -c are mutually exclusive."
|
Some _ when !eval -> abort "Options -e and -c are mutually exclusive."
|
||||||
| None | Some "-" -> !compile
|
| None | Some "-" -> !compile
|
||||||
| Some "" ->
|
| Some "" ->
|
||||||
(match input with
|
(match input with
|
||||||
None | Some "-" -> abort "The target OCaml filename is missing."
|
None | Some "-" -> abort "The target OCaml filename is missing."
|
||||||
| Some file -> Some (Filename.remove_extension file ^ ".ml"))
|
| Some file -> Some (Filename.remove_extension file ^ ".ml"))
|
||||||
| Some compile' ->
|
| Some compile' ->
|
||||||
if Filename.check_suffix compile' ".ml"
|
if Filename.check_suffix compile' ".ml"
|
||||||
then !compile
|
then !compile
|
||||||
else abort "The extension of the target OCaml file is not .ml"
|
else abort "The extension of the target OCaml file is not .ml" in
|
||||||
|
|
||||||
(* Exporting remaining options as non-mutable values *)
|
(* Exporting remaining options as non-mutable values *)
|
||||||
|
|
||||||
let eval = !eval
|
let eval = !eval
|
||||||
and verbose = !verbose
|
and verbose = !verbose
|
||||||
and libs = !libs
|
and libs = !libs
|
||||||
and raw_edits = !raw_edits
|
and raw_edits = !raw_edits in
|
||||||
|
|
||||||
let () =
|
let () =
|
||||||
if Utils.String.Set.mem "cmdline" verbose then
|
if Utils.String.Set.mem "cmdline" verbose then
|
||||||
begin
|
begin
|
||||||
printf "\nEXPORTED COMMAND LINE\n";
|
printf "\nEXPORTED COMMAND LINE\n";
|
||||||
@ -143,6 +146,20 @@ let () =
|
|||||||
printf "compile = %s\n" (string_of quote compile);
|
printf "compile = %s\n" (string_of quote compile);
|
||||||
printf "eval = %B\n" eval;
|
printf "eval = %B\n" eval;
|
||||||
printf "raw_edits = %B\n" raw_edits;
|
printf "raw_edits = %B\n" raw_edits;
|
||||||
printf "verbose = %s\n" verb_str;
|
printf "verbose = %s\n" !verb_str;
|
||||||
printf "I = %s\n" (string_of_path libs)
|
printf "I = %s\n" (string_of_path libs)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
in {input; eval; compile; libs; verbose; raw_edits}
|
||||||
|
|
||||||
|
(* Parsing the command-line options *)
|
||||||
|
|
||||||
|
let read () =
|
||||||
|
try
|
||||||
|
Getopt.parse_cmdline specs anonymous;
|
||||||
|
(verb_str :=
|
||||||
|
let apply e a =
|
||||||
|
if a <> "" then Printf.sprintf "%s, %s" e a else e
|
||||||
|
in Utils.String.Set.fold apply !verbose "");
|
||||||
|
check ()
|
||||||
|
with Getopt.Error msg -> abort msg
|
||||||
|
@ -5,8 +5,6 @@
|
|||||||
[Some "-"] or [None], the source file is read from standard
|
[Some "-"] or [None], the source file is read from standard
|
||||||
input. *)
|
input. *)
|
||||||
|
|
||||||
val input : string option
|
|
||||||
|
|
||||||
(* The Mini-ML source file can be processed in two mutually exclusive
|
(* The Mini-ML source file can be processed in two mutually exclusive
|
||||||
manners: if the value [eval] is set to [true], the source is
|
manners: if the value [eval] is set to [true], the source is
|
||||||
interpreted; if the value [compile] is not [None], the source is
|
interpreted; if the value [compile] is not [None], the source is
|
||||||
@ -14,11 +12,13 @@ val input : string option
|
|||||||
nothing is done with the source. Note: if [compile] is [Some "-"],
|
nothing is done with the source. Note: if [compile] is [Some "-"],
|
||||||
the compiled code is sent to standard output. *)
|
the compiled code is sent to standard output. *)
|
||||||
|
|
||||||
val eval : bool
|
type options = {
|
||||||
val compile : string option
|
input : string option;
|
||||||
|
eval : bool;
|
||||||
|
compile : string option;
|
||||||
|
libs : string list;
|
||||||
|
verbose : Utils.String.Set.t;
|
||||||
|
raw_edits : bool
|
||||||
|
}
|
||||||
|
|
||||||
(* TODO *)
|
val read : unit -> options
|
||||||
|
|
||||||
val libs : string list
|
|
||||||
val verbose : Utils.String.Set.t
|
|
||||||
val raw_edits : bool
|
|
||||||
|
@ -17,20 +17,22 @@ exception Error of message Region.reg
|
|||||||
tokens to the given channel. If no logger is given to [get_token],
|
tokens to the given channel. If no logger is given to [get_token],
|
||||||
no printing takes place while the lexer runs.
|
no printing takes place while the lexer runs.
|
||||||
|
|
||||||
The call [reset ~file ~line buffer] modifies in-place the lexing
|
The call [reset ~file ~line ~offset buffer] modifies in-place the
|
||||||
buffer [buffer] so the lexing engine records that the file
|
lexing buffer [buffer] so the lexing engine records that the file
|
||||||
associated with [buffer] is named [file], and the current line is
|
associated with [buffer] is named [file], the current line is
|
||||||
[line]. This function is useful when lexing a file that has been
|
[line] and the offset on that line is [offset]. This function is
|
||||||
previously preprocessed by the C preprocessor, in which case the
|
useful when lexing a file that has been previously preprocessed by
|
||||||
argument [file] is the name of the file that was preprocessed,
|
the C preprocessor, in which case the argument [file] is the name
|
||||||
_not_ the preprocessed file (of which the user is not normally
|
of the file that was preprocessed, _not_ the preprocessed file (of
|
||||||
aware). By default, the [line] argument is [1].
|
which the user is not normally aware). By default, the [line]
|
||||||
|
argument is [1].
|
||||||
*)
|
*)
|
||||||
|
|
||||||
type logger = out_channel * (out_channel -> Token.t -> unit)
|
type logger = out_channel * (out_channel -> Token.t -> unit)
|
||||||
|
|
||||||
val get_token : ?log:logger -> Lexing.lexbuf -> Token.t
|
val get_token : ?log:logger -> Lexing.lexbuf -> Token.t
|
||||||
val reset : file:string -> ?line:int -> Lexing.lexbuf -> unit
|
val reset : ?file:string -> ?line:int -> ?offset:int -> Lexing.lexbuf -> unit
|
||||||
|
val reset_file : file:string -> Lexing.lexbuf -> unit
|
||||||
|
|
||||||
(* Debugging *)
|
(* Debugging *)
|
||||||
|
|
||||||
|
@ -78,7 +78,6 @@ let fail region value = raise (Error Region.{region; value})
|
|||||||
(* KEYWORDS *)
|
(* KEYWORDS *)
|
||||||
|
|
||||||
let keywords = Token.[
|
let keywords = Token.[
|
||||||
"and", Some And;
|
|
||||||
"begin", Some Begin;
|
"begin", Some Begin;
|
||||||
"else", Some Else;
|
"else", Some Else;
|
||||||
"false", Some False;
|
"false", Some False;
|
||||||
@ -99,6 +98,7 @@ let keywords = Token.[
|
|||||||
|
|
||||||
(* Reserved *)
|
(* Reserved *)
|
||||||
|
|
||||||
|
"and", None;
|
||||||
"as", None;
|
"as", None;
|
||||||
"asr", None;
|
"asr", None;
|
||||||
"assert", None;
|
"assert", None;
|
||||||
@ -152,12 +152,28 @@ let reset_file ~file buffer =
|
|||||||
let open Lexing in
|
let open Lexing in
|
||||||
buffer.lex_curr_p <- {buffer.lex_curr_p with pos_fname = file}
|
buffer.lex_curr_p <- {buffer.lex_curr_p with pos_fname = file}
|
||||||
|
|
||||||
let reset_line lnum buffer =
|
let reset_line ~line buffer =
|
||||||
let open Lexing in
|
let open Lexing in
|
||||||
buffer.lex_curr_p <- {buffer.lex_curr_p with pos_lnum = lnum}
|
buffer.lex_curr_p <- {buffer.lex_curr_p with pos_lnum = line}
|
||||||
|
|
||||||
let reset ~file ?(line=1) buffer =
|
let reset_offset ~offset buffer =
|
||||||
reset_file ~file buffer; reset_line line buffer
|
assert (offset >= 0);
|
||||||
|
let open Lexing in
|
||||||
|
let bol = buffer.lex_curr_p.pos_bol in
|
||||||
|
buffer.lex_curr_p <- {buffer.lex_curr_p with pos_cnum = bol + offset }
|
||||||
|
|
||||||
|
let reset ?file ?line ?offset buffer =
|
||||||
|
let () =
|
||||||
|
match file with
|
||||||
|
Some file -> reset_file ~file buffer
|
||||||
|
| None -> () in
|
||||||
|
let () =
|
||||||
|
match line with
|
||||||
|
Some line -> reset_line ~line buffer
|
||||||
|
| None -> () in
|
||||||
|
match offset with
|
||||||
|
Some offset -> reset_offset ~offset buffer
|
||||||
|
| None -> ()
|
||||||
|
|
||||||
(* Hack to roll back one lexeme in the current semantic action *)
|
(* Hack to roll back one lexeme in the current semantic action *)
|
||||||
(*
|
(*
|
||||||
@ -222,7 +238,7 @@ rule scan = parse
|
|||||||
| "->" { Token.ARROW }
|
| "->" { Token.ARROW }
|
||||||
| "::" { Token.CONS }
|
| "::" { Token.CONS }
|
||||||
| "^" { Token.CAT }
|
| "^" { Token.CAT }
|
||||||
| "@" { Token.APPEND }
|
(*| "@" { Token.APPEND }*)
|
||||||
|
|
||||||
| "=" { Token.EQ }
|
| "=" { Token.EQ }
|
||||||
| "<>" { Token.NE }
|
| "<>" { Token.NE }
|
||||||
@ -294,10 +310,54 @@ rule scan = parse
|
|||||||
let () = ignore thread
|
let () = ignore thread
|
||||||
in scan lexbuf }
|
in scan lexbuf }
|
||||||
|
|
||||||
|
(* Management of #include CPP directives
|
||||||
|
|
||||||
|
An input LIGO program may contain GNU CPP (C preprocessor)
|
||||||
|
directives, and the entry modules (named *Main.ml) run CPP on them
|
||||||
|
in traditional mode:
|
||||||
|
|
||||||
|
https://gcc.gnu.org/onlinedocs/cpp/Traditional-Mode.html
|
||||||
|
|
||||||
|
The main interest in using CPP is that it can stand for a poor
|
||||||
|
man's (flat) module system for LIGO thanks to #include
|
||||||
|
directives, and the traditional mode leaves the markup mostly
|
||||||
|
undisturbed.
|
||||||
|
|
||||||
|
Some of the #line resulting from processing #include directives
|
||||||
|
deal with system file headers and thus have to be ignored for our
|
||||||
|
purpose. Moreover, these #line directives may also carry some
|
||||||
|
additional flags:
|
||||||
|
|
||||||
|
https://gcc.gnu.org/onlinedocs/cpp/Preprocessor-Output.html
|
||||||
|
|
||||||
|
of which 1 and 2 indicate, respectively, the start of a new file
|
||||||
|
and the return from a file (after its inclusion has been
|
||||||
|
processed).
|
||||||
|
*)
|
||||||
|
|
||||||
|
| '#' blank* ("line" blank+)? (integer as line) blank+
|
||||||
|
'"' (string as file) '"' {
|
||||||
|
let flags = scan_flags [] lexbuf in
|
||||||
|
let () = ignore flags in
|
||||||
|
let line = int_of_string line
|
||||||
|
and file = Filename.basename file in
|
||||||
|
let () = reset ~file ~line ~offset:0 lexbuf
|
||||||
|
in scan lexbuf
|
||||||
|
}
|
||||||
|
|
||||||
| _ as c { let msg = sprintf "Invalid character '%s'."
|
| _ as c { let msg = sprintf "Invalid character '%s'."
|
||||||
(Char.escaped c)
|
(Char.escaped c)
|
||||||
in error lexbuf msg }
|
in error lexbuf msg }
|
||||||
|
|
||||||
|
(* Scanning CPP #include flags *)
|
||||||
|
|
||||||
|
and scan_flags acc = parse
|
||||||
|
blank+ { scan_flags acc lexbuf }
|
||||||
|
| integer as code { let acc = int_of_string code :: acc
|
||||||
|
in scan_flags acc lexbuf }
|
||||||
|
| nl { Lexing.new_line lexbuf; List.rev acc }
|
||||||
|
| eof { List.rev acc }
|
||||||
|
|
||||||
(* Finishing a string *)
|
(* Finishing a string *)
|
||||||
|
|
||||||
and scan_string thread = parse
|
and scan_string thread = parse
|
||||||
@ -326,11 +386,11 @@ and scan_block thread = parse
|
|||||||
else scan_block in
|
else scan_block in
|
||||||
let thread = next thread lexbuf in
|
let thread = next thread lexbuf in
|
||||||
let thread = {thread with opening}
|
let thread = {thread with opening}
|
||||||
in scan_block thread lexbuf }
|
in scan_block thread lexbuf }
|
||||||
| "*)" { push_string (Lexing.lexeme lexbuf) thread }
|
| "*)" { push_string (Lexing.lexeme lexbuf) thread }
|
||||||
| nl { Lexing.new_line lexbuf; scan_block thread lexbuf }
|
| nl { Lexing.new_line lexbuf; scan_block thread lexbuf }
|
||||||
| eof { fail thread.opening "Open comment." }
|
| eof { fail thread.opening "Open comment." }
|
||||||
| _ as c { scan_block (push_char c thread) lexbuf }
|
| _ as c { scan_block (push_char c thread) lexbuf }
|
||||||
|
|
||||||
(* END LEXER DEFINITION *)
|
(* END LEXER DEFINITION *)
|
||||||
|
|
||||||
@ -371,8 +431,8 @@ let iter action file_opt =
|
|||||||
try
|
try
|
||||||
let cin, reset =
|
let cin, reset =
|
||||||
match file_opt with
|
match file_opt with
|
||||||
None | Some "-" -> stdin, fun ?(line=1) _ -> ignore line
|
None | Some "-" -> stdin, ignore
|
||||||
| Some file -> open_in file, reset ~file in
|
| Some file -> open_in file, reset_file ~file in
|
||||||
let buffer = Lexing.from_channel cin in
|
let buffer = Lexing.from_channel cin in
|
||||||
let rec iter () =
|
let rec iter () =
|
||||||
try
|
try
|
||||||
|
@ -6,7 +6,11 @@ Printexc.record_backtrace true;;
|
|||||||
|
|
||||||
(* Running the lexer on the source *)
|
(* Running the lexer on the source *)
|
||||||
|
|
||||||
if Utils.String.Set.mem "lexer" EvalOpt.verbose then
|
let options = EvalOpt.read ();;
|
||||||
Lexer.trace EvalOpt.input
|
|
||||||
else Lexer.iter (fun _lexbuf _out _token -> ()) EvalOpt.input
|
open EvalOpt;;
|
||||||
|
|
||||||
|
if Utils.String.Set.mem "lexer" options.verbose then
|
||||||
|
Lexer.trace options.input
|
||||||
|
else Lexer.iter (fun _lexbuf _out _token -> ()) options.input
|
||||||
;;
|
;;
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
%token ARROW
|
%token ARROW
|
||||||
%token CONS
|
%token CONS
|
||||||
%token CAT
|
%token CAT
|
||||||
%token APPEND
|
(*%token APPEND*)
|
||||||
%token DOT
|
%token DOT
|
||||||
|
|
||||||
%token COMMA
|
%token COMMA
|
||||||
@ -46,7 +46,7 @@
|
|||||||
%token <string * Z.t> Mtz
|
%token <string * Z.t> Mtz
|
||||||
%token <string * Z.t> Nat
|
%token <string * Z.t> Nat
|
||||||
|
|
||||||
%token And
|
(*%token And*)
|
||||||
%token Begin
|
%token Begin
|
||||||
%token Else
|
%token Else
|
||||||
%token End
|
%token End
|
||||||
|
@ -149,8 +149,8 @@ program:
|
|||||||
nseq(declaration) eof { {decl=$1; eof=$2} }
|
nseq(declaration) eof { {decl=$1; eof=$2} }
|
||||||
|
|
||||||
declaration:
|
declaration:
|
||||||
reg(kwd(Let) let_bindings {$1,$2}) { Let $1 }
|
reg(kwd(Let) let_binding {$1,$2}) { Let $1 }
|
||||||
| reg(kwd(LetEntry) let_binding {$1,$2}) { LetEntry $1 }
|
| reg(kwd(LetEntry) let_binding {$1,$2}) { LetEntry $1 }
|
||||||
| reg(type_decl) { TypeDecl $1 }
|
| reg(type_decl) { TypeDecl $1 }
|
||||||
|
|
||||||
(* Type declarations *)
|
(* Type declarations *)
|
||||||
@ -234,9 +234,6 @@ field_decl:
|
|||||||
|
|
||||||
(* Non-recursive definitions *)
|
(* Non-recursive definitions *)
|
||||||
|
|
||||||
let_bindings:
|
|
||||||
nsepseq(let_binding, kwd(And)) { $1 }
|
|
||||||
|
|
||||||
let_binding:
|
let_binding:
|
||||||
ident nseq(sub_irrefutable) type_annotation? eq expr {
|
ident nseq(sub_irrefutable) type_annotation? eq expr {
|
||||||
let let_rhs = EFun (norm $2 $4 $5) in
|
let let_rhs = EFun (norm $2 $4 $5) in
|
||||||
@ -389,7 +386,7 @@ case_clause(right_expr):
|
|||||||
pattern arrow right_expr { {pattern=$1; arrow=$2; rhs=$3} }
|
pattern arrow right_expr { {pattern=$1; arrow=$2; rhs=$3} }
|
||||||
|
|
||||||
let_expr(right_expr):
|
let_expr(right_expr):
|
||||||
reg(kwd(Let) let_bindings kwd(In) right_expr {$1,$2,$3,$4}) {
|
reg(kwd(Let) let_binding kwd(In) right_expr {$1,$2,$3,$4}) {
|
||||||
ELetIn $1 }
|
ELetIn $1 }
|
||||||
|
|
||||||
fun_expr(right_expr):
|
fun_expr(right_expr):
|
||||||
@ -447,14 +444,16 @@ ne_expr:
|
|||||||
|
|
||||||
cat_expr_level:
|
cat_expr_level:
|
||||||
reg(cat_expr) { EString (Cat $1) }
|
reg(cat_expr) { EString (Cat $1) }
|
||||||
| reg(append_expr) { EList (Append $1) }
|
(*| reg(append_expr) { EList (Append $1) } *)
|
||||||
| cons_expr_level { $1 }
|
| cons_expr_level { $1 }
|
||||||
|
|
||||||
cat_expr:
|
cat_expr:
|
||||||
bin_op(cons_expr_level, sym(CAT), cat_expr_level) { $1 }
|
bin_op(cons_expr_level, sym(CAT), cat_expr_level) { $1 }
|
||||||
|
|
||||||
|
(*
|
||||||
append_expr:
|
append_expr:
|
||||||
cons_expr_level sym(APPEND) cat_expr_level { $1,$2,$3 }
|
cons_expr_level sym(APPEND) cat_expr_level { $1,$2,$3 }
|
||||||
|
*)
|
||||||
|
|
||||||
cons_expr_level:
|
cons_expr_level:
|
||||||
reg(cons_expr) { EList (Cons $1) }
|
reg(cons_expr) { EList (Cons $1) }
|
||||||
|
@ -4,10 +4,16 @@
|
|||||||
|
|
||||||
Printexc.record_backtrace true;;
|
Printexc.record_backtrace true;;
|
||||||
|
|
||||||
|
(* Reading the command-line options *)
|
||||||
|
|
||||||
|
let options = EvalOpt.read ()
|
||||||
|
|
||||||
|
open EvalOpt
|
||||||
|
|
||||||
(* Path to the Mini-ML standard library *)
|
(* Path to the Mini-ML standard library *)
|
||||||
|
|
||||||
let lib_path =
|
let lib_path =
|
||||||
match EvalOpt.libs with
|
match options.libs with
|
||||||
[] -> ""
|
[] -> ""
|
||||||
| libs -> let mk_I dir path = Printf.sprintf " -I %s%s" dir path
|
| libs -> let mk_I dir path = Printf.sprintf " -I %s%s" dir path
|
||||||
in List.fold_right mk_I libs ""
|
in List.fold_right mk_I libs ""
|
||||||
@ -15,9 +21,9 @@ let lib_path =
|
|||||||
(* Opening the input channel and setting the lexing engine *)
|
(* Opening the input channel and setting the lexing engine *)
|
||||||
|
|
||||||
let cin, reset =
|
let cin, reset =
|
||||||
match EvalOpt.input with
|
match options.input with
|
||||||
None | Some "-" -> stdin, fun ?(line=1) _buffer -> ignore line
|
None | Some "-" -> stdin, ignore
|
||||||
| Some file -> open_in file, Lexer.reset ~file
|
| Some file -> open_in file, Lexer.reset_file ~file
|
||||||
|
|
||||||
let buffer = Lexing.from_channel cin
|
let buffer = Lexing.from_channel cin
|
||||||
let () = reset buffer
|
let () = reset buffer
|
||||||
@ -25,14 +31,14 @@ let () = reset buffer
|
|||||||
(* Tokeniser *)
|
(* Tokeniser *)
|
||||||
|
|
||||||
let tokeniser =
|
let tokeniser =
|
||||||
if Utils.String.Set.mem "lexer" EvalOpt.verbose then
|
if Utils.String.Set.mem "lexer" options.verbose then
|
||||||
Lexer.get_token ~log:(stdout, Lexer.output_token buffer)
|
Lexer.get_token ~log:(stdout, Lexer.output_token buffer)
|
||||||
else Lexer.get_token ?log:None
|
else Lexer.get_token ?log:None
|
||||||
|
|
||||||
let () =
|
let () =
|
||||||
try
|
try
|
||||||
let ast = Parser.program tokeniser buffer in
|
let ast = Parser.program tokeniser buffer in
|
||||||
if Utils.String.Set.mem "unparsing" EvalOpt.verbose then
|
if Utils.String.Set.mem "unparsing" options.verbose then
|
||||||
AST.print_tokens ~undo:true ast
|
AST.print_tokens ~undo:true ast
|
||||||
else () (* AST.print_tokens ast *)
|
else () (* AST.print_tokens ast *)
|
||||||
with
|
with
|
||||||
|
@ -6,7 +6,7 @@ type t =
|
|||||||
ARROW
|
ARROW
|
||||||
| CONS
|
| CONS
|
||||||
| CAT
|
| CAT
|
||||||
| APPEND
|
(*| APPEND*)
|
||||||
| MINUS
|
| MINUS
|
||||||
| PLUS
|
| PLUS
|
||||||
| SLASH
|
| SLASH
|
||||||
@ -44,7 +44,7 @@ type t =
|
|||||||
|
|
||||||
(* Keywords *)
|
(* Keywords *)
|
||||||
|
|
||||||
| And
|
(*| And*)
|
||||||
| Begin
|
| Begin
|
||||||
| Else
|
| Else
|
||||||
| End
|
| End
|
||||||
@ -87,7 +87,7 @@ let to_string = function
|
|||||||
ARROW -> "->"
|
ARROW -> "->"
|
||||||
| CONS -> "::"
|
| CONS -> "::"
|
||||||
| CAT -> "^"
|
| CAT -> "^"
|
||||||
| APPEND -> "@"
|
(*| APPEND -> "@"*)
|
||||||
| MINUS -> "-"
|
| MINUS -> "-"
|
||||||
| PLUS -> "+"
|
| PLUS -> "+"
|
||||||
| SLASH -> "/"
|
| SLASH -> "/"
|
||||||
@ -119,7 +119,7 @@ let to_string = function
|
|||||||
| Mtz (lex,z) -> sprintf "Mtz %s (%s)" lex (Z.to_string z)
|
| Mtz (lex,z) -> sprintf "Mtz %s (%s)" lex (Z.to_string z)
|
||||||
| Str n -> sprintf "Str \"%s\"" n
|
| Str n -> sprintf "Str \"%s\"" n
|
||||||
| Bytes (lex,h) -> sprintf "Bytes %s (0x%s)" lex (Hex.to_string h)
|
| Bytes (lex,h) -> sprintf "Bytes %s (0x%s)" lex (Hex.to_string h)
|
||||||
| And -> "and"
|
(*| And -> "and"*)
|
||||||
| Begin -> "begin"
|
| Begin -> "begin"
|
||||||
| Else -> "else"
|
| Else -> "else"
|
||||||
| End -> "end"
|
| End -> "end"
|
||||||
|
@ -6,7 +6,7 @@ type t =
|
|||||||
ARROW (* "->" *)
|
ARROW (* "->" *)
|
||||||
| CONS (* "::" *)
|
| CONS (* "::" *)
|
||||||
| CAT (* "^" *)
|
| CAT (* "^" *)
|
||||||
| APPEND (* "@" *)
|
(*| APPEND (* "@" *)*)
|
||||||
|
|
||||||
(* Arithmetics *)
|
(* Arithmetics *)
|
||||||
|
|
||||||
@ -60,7 +60,7 @@ type t =
|
|||||||
|
|
||||||
(* Keywords *)
|
(* Keywords *)
|
||||||
|
|
||||||
| And
|
(*| And*)
|
||||||
| Begin
|
| Begin
|
||||||
| Else
|
| Else
|
||||||
| End
|
| End
|
||||||
|
Loading…
Reference in New Issue
Block a user