Gardening.

This commit is contained in:
Christian Rinderknecht 2019-10-07 16:33:34 +02:00
parent 0c7bfbdecd
commit ff9584c7b7
12 changed files with 268 additions and 270 deletions

View File

@ -1 +1 @@
--explain --external-tokens Token --base Parser ParToken.mly
--explain --external-tokens LexToken --base Parser ParToken.mly

View File

@ -4,18 +4,17 @@ $HOME/git/ligo/vendors/ligo-utils/simple-utils/pos.mli
$HOME/git/ligo/vendors/ligo-utils/simple-utils/pos.ml
$HOME/git/ligo/vendors/ligo-utils/simple-utils/region.mli
$HOME/git/ligo/vendors/ligo-utils/simple-utils/region.ml
$HOME/git/ligo/src/parser/shared/Lexer.mli
$HOME/git/ligo/src/parser/shared/Lexer.mll
$HOME/git/ligo/src/parser/shared/Error.mli
$HOME/git/ligo/src/parser/shared/EvalOpt.ml
$HOME/git/ligo/src/parser/shared/EvalOpt.mli
$HOME/git/ligo/src/parser/shared/FQueue.ml
$HOME/git/ligo/src/parser/shared/FQueue.mli
$HOME/git/ligo/src/parser/shared/LexerLog.mli
$HOME/git/ligo/src/parser/shared/LexerLog.ml
$HOME/git/ligo/src/parser/shared/Markup.ml
$HOME/git/ligo/src/parser/shared/Markup.mli
$HOME/git/ligo/src/parser/shared/Utils.mli
$HOME/git/ligo/src/parser/shared/Utils.ml
$HOME/git/ligo/src/parser/shared/Version.ml
../shared/Lexer.mli
../shared/Lexer.mll
../shared/Error.mli
../shared/EvalOpt.ml
../shared/EvalOpt.mli
../shared/FQueue.ml
../shared/FQueue.mli
../shared/LexerLog.mli
../shared/LexerLog.ml
../shared/Markup.ml
../shared/Markup.mli
../shared/Utils.mli
../shared/Utils.ml
Stubs/Simple_utils.ml

View File

@ -6,7 +6,7 @@ let () = Printexc.record_backtrace true
(* Running the lexer on the source *)
let options = EvalOpt.read "Ligodity" ".mligo"
let options = EvalOpt.read "CameLIGO" ".mligo"
open EvalOpt

View File

@ -49,7 +49,7 @@ par(X):
rpar = $3}
in {region; value}
}
brackets(X):
LBRACKET X RBRACKET {
let region = cover $1 $3
@ -109,7 +109,7 @@ sepseq(item,sep):
(* Non-empty comma-separated values (at least two values) *)
tuple(item):
item COMMA nsepseq(item,COMMA) {
item COMMA nsepseq(item,COMMA) {
let h,t = $3 in $1,($2,h)::t
}
@ -117,7 +117,7 @@ tuple(item):
list(item):
LBRACKET sep_or_term_list(item,SEMI) RBRACKET {
let elements, terminator = $2 in
let elements, terminator = $2 in
{ value =
{
opening = LBracket $1;
@ -136,7 +136,7 @@ list(item):
terminator = None;
closing = RBracket $2
};
region = cover $1 $2
region = cover $1 $2
}
}
@ -150,10 +150,10 @@ declarations:
| declaration declarations { Utils.(nseq_foldl (swap nseq_cons) $2 $1)}
declaration:
LetEntry entry_binding {
LetEntry entry_binding {
let start = $1 in
let stop = expr_to_region $2.let_rhs in
let region = cover start stop in
let region = cover start stop in
LetEntry { value = ($1, $2); region}, []
}
| type_decl { TypeDecl $1, [] }
@ -162,7 +162,7 @@ declaration:
(* Type declarations *)
type_decl:
Type type_name EQ type_expr {
Type type_name EQ type_expr {
let region = cover $1 (type_expr_to_region $4) in
let value = {
kwd_type = $1;
@ -179,19 +179,19 @@ type_expr:
| record_type { TRecord $1 }
cartesian:
nsepseq(fun_type, TIMES) {
nsepseq(fun_type, TIMES) {
let region = nsepseq_to_region type_expr_to_region $1
in {region; value=$1}
}
fun_type:
core_type {
$1
core_type {
$1
}
| core_type ARROW fun_type {
| core_type ARROW fun_type {
let region = cover (type_expr_to_region $1)
(type_expr_to_region $3)
in
in
TFun {region; value = ($1, $2, $3)}
}
@ -202,16 +202,16 @@ core_type:
| module_name DOT type_name {
let module_name = $1.value in
let type_name = $3.value in
let value = module_name ^ "." ^ type_name in
let value = module_name ^ "." ^ type_name in
let region = cover $1.region $3.region
in
in
TAlias {region; value}
}
| core_type type_constr {
let arg_val = $1 in
let constr = $2 in
let start = type_expr_to_region $1 in
let stop = $2.region in
let start = type_expr_to_region $1 in
let stop = $2.region in
let region = cover start stop in
let lpar, rpar = ghost, ghost in
let value = {lpar; inside=arg_val,[]; rpar} in
@ -219,12 +219,12 @@ core_type:
TApp Region.{value = constr, arg; region}
}
| type_tuple type_constr {
let total = cover $1.region $2.region in
let total = cover $1.region $2.region in
TApp {region=total; value = $2, $1 }
}
}
| par(cartesian) {
let Region.{value={inside=prod; _}; _} = $1 in
TPar {$1 with value={$1.value with inside = TProd prod}} }
TPar {$1 with value={$1.value with inside = TProd prod}} }
type_constr:
type_name { $1 }
@ -233,7 +233,7 @@ type_tuple:
par(tuple(type_expr)) { $1 }
sum_type:
ioption(VBAR) nsepseq(variant,VBAR) {
ioption(VBAR) nsepseq(variant,VBAR) {
let region = nsepseq_to_region (fun x -> x.region) $2
in {region; value = $2}
}
@ -256,7 +256,7 @@ record_type:
elements = Some elements;
terminator;
closing = RBrace $3}
in {region; value}
in {region; value}
}
field_decl:
@ -264,7 +264,7 @@ field_decl:
let stop = type_expr_to_region $3 in
let region = cover $1.region stop
and value = {field_name = $1; colon = $2; field_type = $3}
in {region; value}
in {region; value}
}
(* Entry points *)
@ -284,7 +284,7 @@ entry_binding:
let_declaration:
Let let_binding {
let kwd_let = $1 in
let kwd_let = $1 in
let binding, region = $2 in
{value = kwd_let, binding; region}
}
@ -299,10 +299,10 @@ let_binding:
let region = cover start stop in
({bindings= (ident_pattern :: hd :: tl); lhs_type=$3; eq=$4; let_rhs}, region)
}
| irrefutable type_annotation? EQ expr {
| irrefutable type_annotation? EQ expr {
let pattern = $1 in
let start = pattern_to_region $1 in
let stop = expr_to_region $4 in
let stop = expr_to_region $4 in
let region = cover start stop in
({bindings = [pattern]; lhs_type=$2; eq=$3; let_rhs=$4}, region)
}
@ -313,11 +313,11 @@ type_annotation:
(* Patterns *)
irrefutable:
tuple(sub_irrefutable) {
let h, t = $1 in
tuple(sub_irrefutable) {
let h, t = $1 in
let start = pattern_to_region h in
let stop = last (fun (region, _) -> region) t in
let region = cover start stop in
let region = cover start stop in
PTuple { value = $1; region }
}
| sub_irrefutable { $1 }
@ -335,14 +335,14 @@ closed_irrefutable:
| typed_pattern { PTyped $1 }
typed_pattern:
irrefutable COLON type_expr {
let start = pattern_to_region $1 in
irrefutable COLON type_expr {
let start = pattern_to_region $1 in
let stop = type_expr_to_region $3 in
let region = cover start stop in
{
value = {
pattern = $1;
colon = $2;
pattern = $1;
colon = $2;
type_expr = $3
};
region
@ -350,18 +350,18 @@ typed_pattern:
}
pattern:
sub_pattern CONS tail {
sub_pattern CONS tail {
let start = pattern_to_region $1 in
let stop = pattern_to_region $3 in
let stop = pattern_to_region $3 in
let region = cover start stop in
let val_ = {value = $1, $2, $3; region} in
PList (PCons val_)
PList (PCons val_)
}
| tuple(sub_pattern) {
let h, t = $1 in
| tuple(sub_pattern) {
let h, t = $1 in
let start = pattern_to_region h in
let stop = last (fun (region, _) -> region) t in
let region = cover start stop in
let region = cover start stop in
PTuple { value = $1; region }
}
| core_pattern { $1 }
@ -379,7 +379,7 @@ core_pattern:
| False { PFalse $1 }
| Str { PString $1 }
| par(ptuple) { PPar $1 }
| list(tail) { PList (Sugar $1) }
| list(tail) { PList (Sugar $1) }
| constr_pattern { PConstr $1 }
| record_pattern { PRecord $1 }
@ -393,7 +393,7 @@ record_pattern:
terminator;
closing = RBrace $3}
in
{region; value}
{region; value}
}
field_pattern:
@ -405,29 +405,29 @@ field_pattern:
}
constr_pattern:
Constr sub_pattern {
Constr sub_pattern {
let region = cover $1.region (pattern_to_region $2) in
{ value = $1, Some $2; region } }
| Constr { { value = $1, None; region = $1.region } }
ptuple:
tuple(tail) {
let h, t = $1 in
tuple(tail) {
let h, t = $1 in
let start = pattern_to_region h in
let stop = last (fun (region, _) -> region) t in
let region = cover start stop in
PTuple { value = $1; region }
let region = cover start stop in
PTuple { value = $1; region }
}
unit:
LPAR RPAR {
LPAR RPAR {
let the_unit = ghost, ghost in
let region = cover $1 $2 in
{ value = the_unit; region }
}
tail:
sub_pattern CONS tail {
sub_pattern CONS tail {
let start = pattern_to_region $1 in
let end_ = pattern_to_region $3 in
let region = cover start end_ in
@ -456,11 +456,11 @@ base_expr(right_expr):
| fun_expr(right_expr)
| disj_expr_level { $1 }
| tuple(disj_expr_level) {
let h, t = $1 in
let h, t = $1 in
let start = expr_to_region h in
let stop = last (fun (region, _) -> region) t in
let region = cover start stop in
ETuple { value = $1; region }
let region = cover start stop in
ETuple { value = $1; region }
}
conditional(right_expr):
@ -476,27 +476,27 @@ if_then(right_expr):
let ifnot = EUnit {region=ghost; value=the_unit} in
{
value = {
kwd_if = $1;
test = $2;
kwd_then = $3;
kwd_if = $1;
test = $2;
kwd_then = $3;
ifso = $4;
kwd_else = ghost;
kwd_else = ghost;
ifnot
};
region
region
}
}
if_then_else(right_expr):
If expr Then closed_if Else right_expr {
let region = cover $1 (expr_to_region $6) in
{
{
value = {
kwd_if = $1;
test = $2;
kwd_then = $3;
kwd_if = $1;
test = $2;
kwd_then = $3;
ifso = $4;
kwd_else = $5;
kwd_else = $5;
ifnot = $6
};
region
@ -520,21 +520,21 @@ match_expr(right_expr):
let start = $1 in
let stop = match $5 with (* TODO: move to separate function *)
| {region; _}, [] -> region
| _, tl -> last (fun (region,_) -> region) tl
| _, tl -> last (fun (region,_) -> region) tl
in
let region = cover start stop in
{ value = {
kwd_match = $1;
expr = $2;
kwd_match = $1;
expr = $2;
opening = With $3;
lead_vbar = $4;
lead_vbar = $4;
cases = {
value = cases;
value = cases;
region = nsepseq_to_region (fun {region; _} -> region) $5
};
closing = End ghost
};
region
};
region
}
}
| MatchNat expr With VBAR? cases(right_expr) {
@ -544,27 +544,27 @@ match_expr(right_expr):
let start = $1 in
let stop = match $5 with (* TODO: move to separate function *)
| {region; _}, [] -> region
| _, tl -> last (fun (region,_) -> region) tl
| _, tl -> last (fun (region,_) -> region) tl
in
let region = cover start stop in
{
{
value = {
kwd_match = $1;
expr = cast;
kwd_match = $1;
expr = cast;
opening = With $3;
lead_vbar = $4;
lead_vbar = $4;
cases = {
value = cases;
value = cases;
region = nsepseq_to_region (fun {region; _} -> region) $5
};
closing = End ghost
};
region
};
region
}
}
cases(right_expr):
case_clause(right_expr) {
case_clause(right_expr) {
let start = pattern_to_region $1.pattern in
let stop = expr_to_region $1.rhs in
let region = cover start stop in
@ -573,25 +573,25 @@ cases(right_expr):
| cases(base_cond) VBAR case_clause(right_expr) {
let start = match $1 with
| {region; _}, [] -> region
| _, tl -> last (fun (region,_) -> region) tl
| _, tl -> last (fun (region,_) -> region) tl
in
let stop = expr_to_region $3.rhs in
let region = cover start stop in
let h,t = $1 in { value = $3; region}, ($2, h)::t
}
let h,t = $1 in { value = $3; region}, ($2, h)::t
}
case_clause(right_expr):
pattern ARROW right_expr {
pattern ARROW right_expr {
{
pattern = $1;
arrow = $2;
rhs=$3
pattern = $1;
arrow = $2;
rhs=$3
}
}
let_expr(right_expr):
Let let_binding In right_expr {
let kwd_let = $1 in
let kwd_let = $1 in
let (binding, _) = $2 in
let kwd_in = $3 in
let body = $4 in
@ -603,7 +603,7 @@ let_expr(right_expr):
fun_expr(right_expr):
Fun nseq(irrefutable) ARROW right_expr {
let kwd_fun = $1 in
let bindings = $2 in
let bindings = $2 in
let arrow = $3 in
let body = $4 in
let stop = expr_to_region $4 in
@ -624,7 +624,7 @@ disj_expr_level:
| conj_expr_level { $1 }
bin_op(arg1,op,arg2):
arg1 op arg2 {
arg1 op arg2 {
let start = expr_to_region $1 in
let stop = expr_to_region $3 in
let region = cover start stop in
@ -720,16 +720,16 @@ unary_expr_level:
let start = $1 in
let end_ = expr_to_region $2 in
let region = cover start end_
and value = {op = $1; arg = $2}
in EArith (Neg {region; value})
and value = {op = $1; arg = $2}
in EArith (Neg {region; value})
}
| Not call_expr_level {
let start = $1 in
let end_ = expr_to_region $2 in
let region = cover start end_
and value = {op = $1; arg = $2} in
and value = {op = $1; arg = $2} in
ELogic (BoolExpr (Not ({region; value})))
}
}
| call_expr_level { $1 }
call_expr_level:
@ -738,11 +738,11 @@ call_expr_level:
| core_expr { $1 }
constr_expr:
Constr core_expr? {
Constr core_expr? {
let start = $1.region in
let stop = match $2 with
let stop = match $2 with
| Some c -> expr_to_region c
| None -> start
| None -> start
in
let region = cover start stop in
{ value = $1,$2; region}
@ -751,7 +751,7 @@ constr_expr:
call_expr:
core_expr nseq(core_expr) {
let start = expr_to_region $1 in
let stop = match $2 with
let stop = match $2 with
| e, [] -> expr_to_region e
| _, l -> last expr_to_region l
in
@ -777,50 +777,49 @@ core_expr:
EAnnot {$1 with value=$1.value.inside} }
module_field:
module_name DOT field_name {
module_name DOT field_name {
let region = cover $1.region $3.region in
{ value = $1.value ^ "." ^ $3.value; region }
{ value = $1.value ^ "." ^ $3.value; region }
}
projection:
struct_name DOT nsepseq(selection,DOT) {
let start = $1.region in
let stop = nsepseq_to_region (function
| FieldName f -> f.region
| Component c -> c.region) $3
let start = $1.region in
let stop = nsepseq_to_region (function
| FieldName f -> f.region
| Component c -> c.region) $3
in
let region = cover start stop in
{ value =
{ value =
{
struct_name = $1;
selector = $2;
struct_name = $1;
selector = $2;
field_path = $3
};
region
}
}
| module_name DOT field_name DOT nsepseq(selection,DOT) {
let open Region in
let module_name = $1 in
let field_name = $3 in
let value = module_name.value ^ "." ^ field_name.value in
let struct_name = {$1 with value} in
let start = $1.region in
let stop = nsepseq_to_region (function
| FieldName f -> f.region
let stop = nsepseq_to_region (function
| FieldName f -> f.region
| Component c -> c.region) $5
in
in
let region = cover start stop in
{
{
value = {
struct_name;
selector = $4;
struct_name;
selector = $4;
field_path = $5
};
region
}
}
selection:
field_name { FieldName $1 }
| par(Int) { Component $1 }
@ -829,36 +828,36 @@ record_expr:
LBRACE sep_or_term_list(field_assignment,SEMI) RBRACE {
let elements, terminator = $2 in
let region = cover $1 $3 in
{value =
{value =
{
opening = LBrace $1;
elements = Some elements;
terminator;
closing = RBrace $3
};
};
region}
}
field_assignment:
field_name EQ expr {
let start = $1.region in
let stop = expr_to_region $3 in
let start = $1.region in
let stop = expr_to_region $3 in
let region = cover start stop in
{ value =
{ value =
{
field_name = $1;
assignment = $2;
field_name = $1;
assignment = $2;
field_expr = $3
};
region
}
}
}
sequence:
Begin sep_or_term_list(expr,SEMI) End {
let elements, terminator = $2 in
let start = $1 in
let stop = $3 in
let start = $1 in
let stop = $3 in
let region = cover start stop in
{
value = {
@ -869,4 +868,4 @@ sequence:
};
region
}
}
}

View File

@ -1,3 +1,5 @@
[@@@warning "-42"]
open AST
open! Region
@ -351,7 +353,6 @@ and print_fun_expr {value; _} =
print_expr body
and print_conditional {value; _} =
let open Region in
let {kwd_if; test; kwd_then; ifso; kwd_else; ifnot} = value
in print_token ghost "(";
print_token kwd_if "if";

View File

@ -6,7 +6,7 @@ let () = Printexc.record_backtrace true
(* Reading the command-line options *)
let options = EvalOpt.read "Ligodity" ".mligo"
let options = EvalOpt.read "CameLIGO" ".mligo"
open EvalOpt

View File

@ -4,17 +4,17 @@ $HOME/git/ligo/vendors/ligo-utils/simple-utils/pos.mli
$HOME/git/ligo/vendors/ligo-utils/simple-utils/pos.ml
$HOME/git/ligo/vendors/ligo-utils/simple-utils/region.mli
$HOME/git/ligo/vendors/ligo-utils/simple-utils/region.ml
$HOME/git/ligo/src/parser/shared/Lexer.mli
$HOME/git/ligo/src/parser/shared/Lexer.mll
$HOME/git/ligo/src/parser/shared/Error.mli
$HOME/git/ligo/src/parser/shared/EvalOpt.ml
$HOME/git/ligo/src/parser/shared/EvalOpt.mli
$HOME/git/ligo/src/parser/shared/FQueue.ml
$HOME/git/ligo/src/parser/shared/FQueue.mli
$HOME/git/ligo/src/parser/shared/LexerLog.mli
$HOME/git/ligo/src/parser/shared/LexerLog.ml
$HOME/git/ligo/src/parser/shared/Markup.ml
$HOME/git/ligo/src/parser/shared/Markup.mli
$HOME/git/ligo/src/parser/shared/Utils.mli
$HOME/git/ligo/src/parser/shared/Utils.ml
../shared/Lexer.mli
../shared/Lexer.mll
../shared/Error.mli
../shared/EvalOpt.ml
../shared/EvalOpt.mli
../shared/FQueue.ml
../shared/FQueue.mli
../shared/LexerLog.mli
../shared/LexerLog.ml
../shared/Markup.ml
../shared/Markup.mli
../shared/Utils.mli
../shared/Utils.ml
Stubs/Simple_utils.ml

View File

@ -119,9 +119,9 @@ use the non-operation `skip`.
end
end with f
Like Pascal, PascaLIGO offers procedures, as well as functions. The
difference follows the divide between expressions and instructions:
function calls are expressions, procedure calls are instructions.
<!-- Like Pascal, PascaLIGO offers procedures, as well as functions. The -->
<!-- difference follows the divide between expressions and instructions: -->
<!-- function calls are expressions, procedure calls are instructions. -->
In order for a function to be a candidate to be an entrypoint to the
contract, it needs to return a specific type: `list (operation) *
@ -554,7 +554,7 @@ given the declarations (in verbose style)
then the value of `r.f` is `4`.
### Predefined functions, procedures and instructions
### Predefined functions instructions
Beyond a few operators, PascaLIGO features some predefined values and
functions.
@ -590,54 +590,54 @@ string: if `offset + length` is greater than the length of `string`,
the result is `None`, otherwise `Some (substring)`. See section
"Options".
#### Lists
<!-- #### Lists -->
PascaLIGO offers two kinds of iterators on lists.
<!-- PascaLIGO offers two kinds of iterators on lists. -->
The first applies a given function to all the items of a given list,
each call returning the predefined value `Unit`. If the function name
is `f` and the list is `l`, this is expressed as
<!-- The first applies a given function to all the items of a given list, -->
<!-- each call returning the predefined value `Unit`. If the function name -->
<!-- is `f` and the list is `l`, this is expressed as -->
list_iter (l, f);
<!-- list_iter (l, f); -->
Note: `list_iter` is a predefined _procedure_. Procedures are
functions that return `Unit` and whose calls are instructions, not
expressions. The same holds for the iterated function `f` here. See
section "Declarations/Procedures".
<!-- Note: `list_iter` is a predefined _procedure_. Procedures are -->
<!-- functions that return `Unit` and whose calls are instructions, not -->
<!-- expressions. The same holds for the iterated function `f` here. See -->
<!-- section "Declarations/Procedures". -->
For an iterator like `list_iter` to be useful, it needs to be able to
perform a side effect, which user-defined procedures and functions
cannot do. Like so:
<!-- For an iterator like `list_iter` to be useful, it needs to be able to -->
<!-- perform a side effect, which user-defined procedures and functions -->
<!-- cannot do. Like so: -->
function iter (const delta : int; const l : list (int)) : int is
var acc : int := 0
procedure aggregate (const i : int) is
begin
acc := acc + i
end
begin
aggregate (delta); // Has no effect on acc
list_iter (l, aggregate) // Has an effect on acc
end with acc
<!-- function iter (const delta : int; const l : list (int)) : int is -->
<!-- var acc : int := 0 -->
<!-- procedure aggregate (const i : int) is -->
<!-- begin -->
<!-- acc := acc + i -->
<!-- end -->
<!-- begin -->
<!-- aggregate (delta); // Has no effect on acc -->
<!-- list_iter (l, aggregate) // Has an effect on acc -->
<!-- end with acc -->
The other predefined iterator on lists is `list_map`. It is useful
when we need to apply a function to all the items of a list and gather
them into another list, in the same order as the original items. (In
mathematical terms, `list_map` builds the list of the images through
the function.) For instance, the function `iter`
<!-- The other predefined iterator on lists is `list_map`. It is useful -->
<!-- when we need to apply a function to all the items of a list and gather -->
<!-- them into another list, in the same order as the original items. (In -->
<!-- mathematical terms, `list_map` builds the list of the images through -->
<!-- the function.) For instance, the function `iter` -->
function iter (const l : list (int)) : list (int) is
function incr (const i : int) : int is
begin
skip
end with i+1
begin
skip
end with list_map (l, incr)
<!-- function iter (const l : list (int)) : list (int) is -->
<!-- function incr (const i : int) : int is -->
<!-- begin -->
<!-- skip -->
<!-- end with i+1 -->
<!-- begin -->
<!-- skip -->
<!-- end with list_map (l, incr) -->
will take a list of integers as a parameter and return a list with the
integers all incremented, e.g., `iter (list [1;2;3])` evaluates in
`list [2;3;4]`.
<!-- will take a list of integers as a parameter and return a list with the -->
<!-- integers all incremented, e.g., `iter (list [1;2;3])` evaluates in -->
<!-- `list [2;3;4]`. -->
#### Sets
@ -709,18 +709,13 @@ functions to update sets.
has value `3`.
- The iterator `set_iter` is similar to `list_iter`: it takes a set
and a procedure (or function returning `Unit`) and applies it in
turn to all the elements of the set.
- Another form of complete iteration on sets is performed by
loops. See section "Loops".
- Complete iteration on sets is performed by loops. See section
"Loops".
#### Maps
Currently, maps have less support than sets. PascaLIGO offers the
following functions and procedures on maps:
following functions on maps:
- Adding bindings to a map is only possible if the map is mutable,
that is, if it was declared with the annotation `var`, like so, in
@ -768,19 +763,8 @@ following functions and procedures on maps:
where `sender` is a key and `backers` is a map. If the key is
absent in the map, this instruction is a non-operation.
- The iterator `map_iter` is similar to `list_iter`: it takes a set
and a procedure (or function returning `Unit`) and applies it in
turn to all the bindings of the map. The type of the iterated
procedure/function is expected to be `key * value -> unit`.
- The iterator `map_map` is similar to `list_map`: it takes a map
and a function and builds a new map by applying the function to
all the bindings. In particular, this means that the expected
return type of the iterated function must be the type of the
values in the map.
- Another form of complete iteration on maps is performed by
loops. See section "Loops".
- Complete iteration on maps is performed by loops. See section
"Loops".
#### Failures
@ -800,17 +784,17 @@ can chose.
## Declarations
There are several kinds of declarations: types, mutable variables,
constants, functions, procedures, fields. Depending on the syntactic
context, only some of those declarations will be allowed. Declarations
may be separated by a semicolon. (Because each declaration starts with a
constants, functions, fields. Depending on the syntactic context, only
some of those declarations will be allowed. Declarations may be
separated by a semicolon. (Because each declaration starts with a
keyword they can be parsed without separators.)
### Types
Type declarations are found only at top-level, that is, outside any
function or procedure. They associate a type name to a type
expression. The general syntax is
function. They associate a type name to a type expression. The general
syntax is
type some_type_name is some_type_expression
@ -959,27 +943,39 @@ is valid and changes the value of the mutable variable `counter` to be
`3n`. This is the semantics found in all imperative languages.
IMPORTANT: Mutable variables cannot be declared at top-level, but only
in the scope of function and procedure bodies. This is to avoid global
side effects that hide the control flow and makes static analysis
extremely difficult.
in the scope of function bodies. This is to avoid global side effects
that hide the control flow and makes static analysis extremely
difficult.
### Functions
Function declarations can occur both at top-level and inside functions
and procedures (in the tradition of Pascal). We saw an example
earlier:
Function declarations can occur both at top-level and inside
functions, in the tradition of Pascal. For example,
function iter (const l : list (int)) : list (int) is
function incr (const i : int) : int is
function incr_list (const l : list (int)) : list (int) is
function incr_int (const i : int) : int is
begin
skip
end with i+1
const item : int = 0
begin
skip
end with list_map (l, incr)
var temp : list (int) := nil;
for item in l
begin
temp := incr_int (item) # temp
end;
var new_l : list (int) := nil;
for item in temp
begin
new_l := item # new_l
end
end with new_l
Here, the function `incr` is declared inside the declaration of the
function `iter`. The general shape of a function declaration is
Here, the function `incr_int` is declared inside the declaration of
the function `incr_list`, which take a list of integers and a list
containing the same integers plus one.
The general shape of a function declaration is
function my_name ( ... (* parameters here *)) : return_type is
... // local declarations here
@ -1042,7 +1038,7 @@ copies. Let us copy an example seen above:
function iter (const delta : int; const l : list (int)) : int is
var acc : int := 0
procedure aggregate (const i : int) is
function aggregate (const i : int) : unit is
begin
acc := acc + i // acc is part of the copied environment
end
@ -1058,41 +1054,41 @@ value in return.
IMPORTANT: _Functions cannot be recursive in PascaLIGO_, that is why
loops or iterators are needed.
### Procedures
<!-- ### Procedures -->
WARNING: Procedures are not implemented in the current version of LIGO, they
will appear in a future version with these semantics but cannot currently be
used.
<!-- WARNING: Procedures are not implemented in the current version of LIGO, they -->
<!-- will appear in a future version with these semantics but cannot currently be -->
<!-- used. -->
Procedures are a special kind of functions that return `Unit`. They
are declared as follows:
<!-- Procedures are a special kind of functions that return `Unit`. They -->
<!-- are declared as follows: -->
procedure my_name ( ... (* parameters here *)) is
... // local declarations here
begin
... // instructions here
end
<!-- procedure my_name ( ... (* parameters here *)) is -->
<!-- ... // local declarations here -->
<!-- begin -->
<!-- ... // instructions here -->
<!-- end -->
Since function calls (see section "Functions") leave the environment
invariant, one may wonder what use there is to procedures. As we have
seen in the section about "Lists" and their iterators, the exception
to this rule are predefined iterators, like `list_iter`. They actually
allow the iterated function to perform side effects. Here is the
example again:
<!-- Since function calls (see section "Functions") leave the environment -->
<!-- invariant, one may wonder what use there is to procedures. As we have -->
<!-- seen in the section about "Lists" and their iterators, the exception -->
<!-- to this rule are predefined iterators, like `list_iter`. They actually -->
<!-- allow the iterated function to perform side effects. Here is the -->
<!-- example again: -->
function iter (const delta : int; const l : list (int)) : int is
var acc : int := 0
procedure aggregate (const i : int) is
begin
acc := acc + i
end
begin
aggregate (delta); // Has no effect on acc
list_iter (l, aggregate) // Has an effect on acc
end with acc
<!-- function iter (const delta : int; const l : list (int)) : int is -->
<!-- var acc : int := 0 -->
<!-- procedure aggregate (const i : int) is -->
<!-- begin -->
<!-- acc := acc + i -->
<!-- end -->
<!-- begin -->
<!-- aggregate (delta); // Has no effect on acc -->
<!-- list_iter (l, aggregate) // Has an effect on acc -->
<!-- end with acc -->
(For the keen reader, this is because the iterated function is inlined
by the compiler.)
<!-- (For the keen reader, this is because the iterated function is inlined -->
<!-- by the compiler.) -->
## Instructions
@ -1154,7 +1150,7 @@ To iterate on a set `s`, we would write, for instance,
... // instructions
end
where `e` is bound in turn in increasing orde to each element of the
where `e` is bound in turn in increasing order to each element of the
set `s`. For example, given the declarations
const s : set (int) = set 3; 1; 2 end
@ -1329,7 +1325,7 @@ PascaLIGO has an explicit keyword for the non-operation: `skip`. Using
- The `for` loop is not supported yet.
- Procedures are not supported yet.
<!-- - Procedures are not supported yet. -->
- Nested code blocks are not supported yet.

View File

@ -6,7 +6,7 @@ let () = Printexc.record_backtrace true
(* Reading the command-line options *)
let options = EvalOpt.read "Pascaligo" ".ligo"
let options = EvalOpt.read "PascaLIGO" ".ligo"
open EvalOpt

View File

@ -8,7 +8,7 @@ let () = Printexc.record_backtrace true
(* Reading the command-line options *)
let options = EvalOpt.read ()
let options = EvalOpt.read "PascaLIGO" ".ligo"
open EvalOpt

View File

@ -174,7 +174,7 @@ let check extension =
let read language extension =
try
Getopt.parse_cmdline (specs language extension) anonymous;
Getopt.parse_cmdline (specs language extension) anonymous;
(verb_str :=
let apply e a =
if a <> "" then Printf.sprintf "%s, %s" e a else e

View File

@ -47,6 +47,9 @@ type options = {
cmd : command
}
(* Parsing the command-line options on stdin *)
(* Parsing the command-line options on stdin. The first parameter is
the name of the concrete syntax, e.g., "pascaligo", and the second
is the file extension, e.g., ".ligo".
*)
val read : string -> string -> options