Commit 230a8485 authored by Andrei Paskevich's avatar Andrei Paskevich

labeled binding idents in logic and programs

parent ae1037fb
...@@ -274,6 +274,7 @@ let specialize_lsymbol ~loc s = ...@@ -274,6 +274,7 @@ let specialize_lsymbol ~loc s =
let ident_of_vs ~loc vs = let ident_of_vs ~loc vs =
{ id = vs.vs_name.id_string; { id = vs.vs_name.id_string;
id_lab = vs.vs_name.id_label;
id_loc = match vs.vs_name.id_origin with id_loc = match vs.vs_name.id_origin with
| User loc -> loc | User loc -> loc
| _ -> loc } | _ -> loc }
......
...@@ -72,6 +72,10 @@ ...@@ -72,6 +72,10 @@
let infix s = "infix " ^ s let infix s = "infix " ^ s
let prefix s = "prefix " ^ s let prefix s = "prefix " ^ s
let mk_id id loc = { id = id; id_lab = []; id_loc = loc }
let add_lab id l = { id with id_lab = l }
let user_loc fname lnum bol cnum1 cnum2 = let user_loc fname lnum bol cnum1 cnum2 =
let pos = { let pos = {
Lexing.pos_fname = fname; Lexing.pos_fname = fname;
...@@ -164,9 +168,9 @@ list0_theory: ...@@ -164,9 +168,9 @@ list0_theory:
; ;
theory_head: theory_head:
| THEORY uident | THEORY uident labels
{ let id = $2 in { let id = add_lab $2 $3 and labels = $3 in
let name = Ident.id_user id.id id.id_loc in let name = Ident.id_user ~labels id.id id.id_loc in
ref_push uc_ref (create_theory name); id } ref_push uc_ref (create_theory name); id }
; ;
...@@ -226,7 +230,7 @@ decl: ...@@ -226,7 +230,7 @@ decl:
| META ident list1_meta_arg_sep_comma | META ident list1_meta_arg_sep_comma
{ Meta (loc (), $2, $3) } { Meta (loc (), $2, $3) }
| META STRING list1_meta_arg_sep_comma | META STRING list1_meta_arg_sep_comma
{ Meta (loc (), { id = $2; id_loc = loc_i 2 }, $3) } { Meta (loc (), mk_id $2 (loc_i 2), $3) }
; ;
/* Use and clone */ /* Use and clone */
...@@ -286,13 +290,14 @@ list1_type_decl: ...@@ -286,13 +290,14 @@ list1_type_decl:
; ;
type_decl: type_decl:
| lident type_args typedefn | lident labels type_args typedefn
{ { td_loc = loc (); td_ident = $1; td_params = $2; td_def = $3 } } { { td_loc = loc (); td_ident = add_lab $1 $2;
td_params = $3; td_def = $4 } }
; ;
type_args: type_args:
| /* epsilon */ { [] } | /* epsilon */ { [] }
| type_var type_args { $1 :: $2 } | type_var labels type_args { add_lab $1 $2 :: $3 }
; ;
typedefn: typedefn:
...@@ -308,7 +313,7 @@ typecases: ...@@ -308,7 +313,7 @@ typecases:
; ;
typecase: typecase:
| uident params { (loc_i 1,$1,$2) } | uident labels params { (loc (), add_lab $1 $2, $3) }
; ;
/* Logic declarations */ /* Logic declarations */
...@@ -319,9 +324,9 @@ list1_logic_decl: ...@@ -319,9 +324,9 @@ list1_logic_decl:
; ;
logic_decl: logic_decl:
| lident_rich params logic_type_option logic_def_option | lident_rich labels params logic_type_option logic_def_option
{ { ld_loc = loc (); ld_ident = $1; ld_params = $2; { { ld_loc = loc (); ld_ident = add_lab $1 $2;
ld_type = $3; ld_def = $4; } } ld_params = $3; ld_type = $4; ld_def = $5 } }
; ;
logic_type_option: logic_type_option:
...@@ -342,8 +347,9 @@ list1_inductive_decl: ...@@ -342,8 +347,9 @@ list1_inductive_decl:
; ;
inductive_decl: inductive_decl:
| lident_rich params inddefn | lident_rich labels params inddefn
{ { in_loc = loc (); in_ident = $1; in_params = $2; in_def = $3 } } { { in_loc = loc (); in_ident = add_lab $1 $2;
in_params = $3; in_def = $4 } }
; ;
inddefn: inddefn:
...@@ -357,7 +363,7 @@ indcases: ...@@ -357,7 +363,7 @@ indcases:
; ;
indcase: indcase:
| uident COLON lexpr { (loc (),$1,$3) } | uident labels COLON lexpr { (loc (), add_lab $1 $2, $4) }
; ;
/* Type expressions */ /* Type expressions */
...@@ -414,36 +420,27 @@ lexpr: ...@@ -414,36 +420,27 @@ lexpr:
| lexpr OR lexpr | lexpr OR lexpr
{ infix_pp $1 PPor $3 } { infix_pp $1 PPor $3 }
| lexpr ASYM_OR lexpr | lexpr ASYM_OR lexpr
{ let label = Ident.label "asym_split" in { mk_pp (PPnamed (Ident.label "asym_split", infix_pp $1 PPor $3)) }
mk_pp (PPnamed (label, infix_pp $1 PPor $3)) }
| lexpr AND lexpr | lexpr AND lexpr
{ infix_pp $1 PPand $3 } { infix_pp $1 PPand $3 }
| lexpr ASYM_AND lexpr | lexpr ASYM_AND lexpr
{ let label = Ident.label "asym_split" in { mk_pp (PPnamed (Ident.label "asym_split", infix_pp $1 PPand $3)) }
mk_pp (PPnamed (label, infix_pp $1 PPand $3)) }
| NOT lexpr | NOT lexpr
{ prefix_pp PPnot $2 } { prefix_pp PPnot $2 }
| lexpr EQUAL lexpr | lexpr EQUAL lexpr
{ let id = { id = infix "="; id_loc = loc_i 2 } in { mk_pp (PPinfix ($1, mk_id (infix "=") (loc_i 2), $3)) }
mk_pp (PPinfix ($1, id, $3)) }
| lexpr LTGT lexpr | lexpr LTGT lexpr
{ let id = { id = infix "="; id_loc = loc_i 2 } in { prefix_pp PPnot (mk_pp (PPinfix ($1, mk_id (infix "=") (loc_i 2), $3))) }
prefix_pp PPnot (mk_pp (PPinfix ($1, id, $3))) }
| lexpr OP1 lexpr | lexpr OP1 lexpr
{ let id = { id = infix $2; id_loc = loc_i 2 } in { mk_pp (PPinfix ($1, mk_id (infix $2) (loc_i 2), $3)) }
mk_pp (PPinfix ($1, id, $3)) }
| lexpr OP2 lexpr | lexpr OP2 lexpr
{ let id = { id = infix $2; id_loc = loc_i 2 } in { mk_pp (PPinfix ($1, mk_id (infix $2) (loc_i 2), $3)) }
mk_pp (PPinfix ($1, id, $3)) }
| lexpr OP3 lexpr | lexpr OP3 lexpr
{ let id = { id = infix $2; id_loc = loc_i 2 } in { mk_pp (PPinfix ($1, mk_id (infix $2) (loc_i 2), $3)) }
mk_pp (PPinfix ($1, id, $3)) }
| lexpr OP4 lexpr | lexpr OP4 lexpr
{ let id = { id = infix $2; id_loc = loc_i 2 } in { mk_pp (PPinfix ($1, mk_id (infix $2) (loc_i 2), $3)) }
mk_pp (PPinfix ($1, id, $3)) }
| any_op lexpr %prec prefix_op | any_op lexpr %prec prefix_op
{ let id = { id = prefix $1; id_loc = loc_i 2 } in { mk_pp (PPapp (Qident (mk_id (prefix $1) (loc_i 2)), [$2])) }
mk_pp (PPapp (Qident id, [$2])) }
| qualid list1_lexpr_arg | qualid list1_lexpr_arg
{ mk_pp (PPapp ($1, $2)) } { mk_pp (PPapp ($1, $2)) }
| IF lexpr THEN lexpr ELSE lexpr | IF lexpr THEN lexpr ELSE lexpr
...@@ -460,8 +457,8 @@ lexpr: ...@@ -460,8 +457,8 @@ lexpr:
{ mk_pp (PPmatch ($2, $5)) } { mk_pp (PPmatch ($2, $5)) }
| MATCH lexpr COMMA list1_lexpr_sep_comma WITH bar_ match_cases END | MATCH lexpr COMMA list1_lexpr_sep_comma WITH bar_ match_cases END
{ mk_pp (PPmatch (mk_pp (PPtuple ($2::$4)), $7)) } { mk_pp (PPmatch (mk_pp (PPtuple ($2::$4)), $7)) }
| EPSILON lident COLON primitive_type DOT lexpr | EPSILON lident labels COLON primitive_type DOT lexpr
{ mk_pp (PPeps ($2, $4, $6)) } { mk_pp (PPeps (add_lab $2 $3, $5, $7)) }
| lexpr COLON primitive_type | lexpr COLON primitive_type
{ mk_pp (PPcast ($1, $3)) } { mk_pp (PPcast ($1, $3)) }
| lexpr_arg | lexpr_arg
...@@ -491,8 +488,7 @@ lexpr_arg: ...@@ -491,8 +488,7 @@ lexpr_arg:
| LEFTPAR lexpr COMMA list1_lexpr_sep_comma RIGHTPAR | LEFTPAR lexpr COMMA list1_lexpr_sep_comma RIGHTPAR
{ mk_pp (PPtuple ($2 :: $4)) } { mk_pp (PPtuple ($2 :: $4)) }
| OPPREF lexpr_arg | OPPREF lexpr_arg
{ let id = { id = prefix $1; id_loc = loc_i 2 } in { mk_pp (PPapp (Qident (mk_id (prefix $1) (loc_i 2)), [$2])) }
mk_pp (PPapp (Qident id, [$2])) }
; ;
quant: quant:
...@@ -549,9 +545,9 @@ list1_pat_uni: ...@@ -549,9 +545,9 @@ list1_pat_uni:
; ;
pat_uni: pat_uni:
| pat_arg { $1 } | pat_arg { $1 }
| uqualid list1_pat_arg { mk_pat (PPpapp ($1, $2)) } | uqualid list1_pat_arg { mk_pat (PPpapp ($1, $2)) }
| pat_uni AS lident { mk_pat (PPpas ($1, $3)) } | pat_uni AS lident labels { mk_pat (PPpas ($1, add_lab $3 $4)) }
; ;
list1_pat_arg: list1_pat_arg:
...@@ -561,7 +557,7 @@ list1_pat_arg: ...@@ -561,7 +557,7 @@ list1_pat_arg:
pat_arg: pat_arg:
| UNDERSCORE { mk_pat (PPpwild) } | UNDERSCORE { mk_pat (PPpwild) }
| lident { mk_pat (PPpvar $1) } | lident labels { mk_pat (PPpvar (add_lab $1 $2)) }
| uqualid { mk_pat (PPpapp ($1, [])) } | uqualid { mk_pat (PPpapp ($1, [])) }
| LEFTPAR RIGHTPAR { mk_pat (PPptuple []) } | LEFTPAR RIGHTPAR { mk_pat (PPptuple []) }
| LEFTPAR pattern RIGHTPAR { $2 } | LEFTPAR pattern RIGHTPAR { $2 }
...@@ -613,6 +609,12 @@ list1_param_var_sep_comma: ...@@ -613,6 +609,12 @@ list1_param_var_sep_comma:
param_var: param_var:
| list1_lident COLON primitive_type | list1_lident COLON primitive_type
{ List.map (fun id -> (Some id, $3)) $1 } { List.map (fun id -> (Some id, $3)) $1 }
| list1_lident label labels list0_lident_labels COLON primitive_type
{ let l = match List.rev $1 with
| i :: l -> add_lab i ($2 :: $3) :: l
| [] -> assert false
in
List.map (fun id -> (Some id, $6)) (List.rev_append l $4) }
; ;
list1_lident: list1_lident:
...@@ -620,6 +622,11 @@ list1_lident: ...@@ -620,6 +622,11 @@ list1_lident:
| lident list1_lident { $1 :: $2 } | lident list1_lident { $1 :: $2 }
; ;
list0_lident_labels:
| /* epsilon */ { [] }
| lident labels list0_lident_labels { add_lab $1 $2 :: $3 }
;
/* Idents */ /* Idents */
ident: ident:
...@@ -636,17 +643,17 @@ lident_rich: ...@@ -636,17 +643,17 @@ lident_rich:
| lident | lident
{ $1 } { $1 }
| LEFTPAR lident_op RIGHTPAR | LEFTPAR lident_op RIGHTPAR
{ { id = infix $2; id_loc = loc () } } { mk_id (infix $2) (loc ()) }
| LEFTPAR_STAR_RIGHTPAR | LEFTPAR_STAR_RIGHTPAR
{ { id = infix "*"; id_loc = loc () } } { mk_id (infix "*") (loc ()) }
| LEFTPAR lident_op UNDERSCORE RIGHTPAR | LEFTPAR lident_op UNDERSCORE RIGHTPAR
{ { id = prefix $2; id_loc = loc () } } { mk_id (prefix $2) (loc ()) }
| LEFTPAR OPPREF RIGHTPAR | LEFTPAR OPPREF RIGHTPAR
{ { id = prefix $2; id_loc = loc () } } { mk_id (prefix $2) (loc ()) }
; ;
lident: lident:
| LIDENT { { id = $1; id_loc = loc () } } | LIDENT { mk_id $1 (loc ()) }
; ;
lident_op: lident_op:
...@@ -665,7 +672,7 @@ any_op: ...@@ -665,7 +672,7 @@ any_op:
; ;
uident: uident:
| UIDENT { { id = $1; id_loc = loc () } } | UIDENT { mk_id $1 (loc ()) }
; ;
lq_lident: lq_lident:
...@@ -713,6 +720,11 @@ label: ...@@ -713,6 +720,11 @@ label:
Ident.label ~loc $1 } Ident.label ~loc $1 }
; ;
labels:
| /* epsilon */ { [] }
| label labels { $1 :: $2 }
;
bar_: bar_:
| /* epsilon */ { () } | /* epsilon */ { () }
| BAR { () } | BAR { () }
......
...@@ -36,7 +36,7 @@ type pp_binop = ...@@ -36,7 +36,7 @@ type pp_binop =
type pp_unop = type pp_unop =
| PPnot | PPnot
type ident = { id : string; id_loc : loc } type ident = { id : string; id_lab : label list; id_loc : loc }
type qualid = type qualid =
| Qident of ident | Qident of ident
......
...@@ -460,7 +460,7 @@ and dterm_node loc env = function ...@@ -460,7 +460,7 @@ and dterm_node loc env = function
let trl = List.map (List.map trigger) trl in let trl = List.map (List.map trigger) trl in
let id, ty, f = match trigger a with let id, ty, f = match trigger a with
| TRterm t -> | TRterm t ->
let id = { id = "fc" ; id_loc = loc } in let id = { id = "fc"; id_lab = []; id_loc = loc } in
let tyl,ty = List.fold_right (fun (_,uty) (tyl,ty) -> let tyl,ty = List.fold_right (fun (_,uty) (tyl,ty) ->
let nty = Tyapp (ts_func, [uty;ty]) in ty :: tyl, nty) let nty = Tyapp (ts_func, [uty;ty]) in ty :: tyl, nty)
uqu ([],t.dt_ty) uqu ([],t.dt_ty)
...@@ -473,7 +473,7 @@ and dterm_node loc env = function ...@@ -473,7 +473,7 @@ and dterm_node loc env = function
in in
id, ty, Fapp (ps_equ, [h;t]) id, ty, Fapp (ps_equ, [h;t])
| TRfmla f -> | TRfmla f ->
let id = { id = "pc" ; id_loc = loc } in let id = { id = "pc"; id_lab = []; id_loc = loc } in
let (uid,uty),uqu = match List.rev uqu with let (uid,uty),uqu = match List.rev uqu with
| uq :: uqu -> uq, List.rev uqu | uq :: uqu -> uq, List.rev uqu
| [] -> assert false | [] -> assert false
......
...@@ -154,6 +154,8 @@ rule token = parse ...@@ -154,6 +154,8 @@ rule token = parse
{ comment lexbuf; token lexbuf } { comment lexbuf; token lexbuf }
| "'" | "'"
{ QUOTE } { QUOTE }
| "`"
{ BACKQUOTE }
| "," | ","
{ COMMA } { COMMA }
| "(" | "("
......
...@@ -34,6 +34,17 @@ ...@@ -34,6 +34,17 @@
let mk_pat p = { pat_loc = loc (); pat_desc = p } let mk_pat p = { pat_loc = loc (); pat_desc = p }
let add_lab id l = { id with id_lab = l }
let user_loc fname lnum bol cnum1 cnum2 =
let pos = {
Lexing.pos_fname = fname;
Lexing.pos_lnum = lnum;
Lexing.pos_bol = bol;
Lexing.pos_cnum = cnum1 }
in
pos, { pos with Lexing.pos_cnum = cnum2 }
(* FIXME: factorize with parser/parser.mly *) (* FIXME: factorize with parser/parser.mly *)
let infix s = "infix " ^ s let infix s = "infix " ^ s
let prefix s = "prefix " ^ s let prefix s = "prefix " ^ s
...@@ -57,23 +68,23 @@ ...@@ -57,23 +68,23 @@
mk_apply e mk_apply e
let mk_infix e1 op e2 = let mk_infix e1 op e2 =
let id = { id = infix op; id_loc = loc_i 2 } in let id = { id = infix op; id_lab = []; id_loc = loc_i 2 } in
mk_expr (mk_apply_id id [e1; e2]) mk_expr (mk_apply_id id [e1; e2])
let mk_binop e1 op e2 = let mk_binop e1 op e2 =
let id = { id = op; id_loc = loc_i 2 } in let id = { id = op; id_lab = []; id_loc = loc_i 2 } in
mk_expr (mk_apply_id id [e1; e2]) mk_expr (mk_apply_id id [e1; e2])
let mk_prefix op e1 = let mk_prefix op e1 =
let id = { id = prefix op; id_loc = loc_i 1 } in let id = { id = prefix op; id_lab = []; id_loc = loc_i 1 } in
mk_expr (mk_apply_id id [e1]) mk_expr (mk_apply_id id [e1])
let id_unit () = { id = "unit"; id_loc = loc () } let id_unit () = { id = "unit"; id_lab = []; id_loc = loc () }
let id_result () = { id = "result"; id_loc = loc () } let id_result () = { id = "result"; id_lab = []; id_loc = loc () }
let id_anonymous () = { id = "_"; id_loc = loc () } let id_anonymous () = { id = "_"; id_lab = []; id_loc = loc () }
let exit_exn () = { id = "%Exit"; id_loc = loc () } let exit_exn () = { id = "%Exit"; id_lab = []; id_loc = loc () }
let id_lt_nat () = Qident { id = "lt_nat"; id_loc = loc () } let id_lt_nat () = Qident { id = "lt_nat"; id_lab = []; id_loc = loc () }
let ty_unit () = Tpure (PPTtyapp ([], Qident (id_unit ()))) let ty_unit () = Tpure (PPTtyapp ([], Qident (id_unit ())))
...@@ -116,7 +127,7 @@ ...@@ -116,7 +127,7 @@
%token UNDERSCORE QUOTE COMMA LEFTPAR RIGHTPAR COLON SEMICOLON %token UNDERSCORE QUOTE COMMA LEFTPAR RIGHTPAR COLON SEMICOLON
%token COLONEQUAL ARROW EQUAL LTGT AT DOT LEFTSQ RIGHTSQ %token COLONEQUAL ARROW EQUAL LTGT AT DOT LEFTSQ RIGHTSQ
%token LEFTBLEFTB RIGHTBRIGHTB BAR BARBAR AMPAMP %token LEFTBLEFTB RIGHTBRIGHTB BAR BARBAR AMPAMP
%token LEFTPAR_STAR_RIGHTPAR EOF %token BACKQUOTE LEFTPAR_STAR_RIGHTPAR EOF
/* Precedences */ /* Precedences */
...@@ -187,18 +198,18 @@ list1_decl: ...@@ -187,18 +198,18 @@ list1_decl:
decl: decl:
| LOGIC | LOGIC
{ Dlogic $1 } { Dlogic $1 }
| LET lident list1_type_v_binder opt_cast EQUAL triple | LET lident labels list1_type_v_binder opt_cast EQUAL triple
{ Dlet ($2, mk_expr_i 3 (Efun ($3, cast_body $4 $6))) } { Dlet (add_lab $2 $3, mk_expr_i 7 (Efun ($4, cast_body $5 $7))) }
| LET lident EQUAL FUN list1_type_v_binder ARROW triple | LET lident labels EQUAL FUN list1_type_v_binder ARROW triple
{ Dlet ($2, mk_expr_i 3 (Efun ($5, $7))) } { Dlet (add_lab $2 $3, mk_expr_i 8 (Efun ($6, $8))) }
| LET REC list1_recfun_sep_and | LET REC list1_recfun_sep_and
{ Dletrec $3 } { Dletrec $3 }
| PARAMETER lident COLON type_v | PARAMETER lident labels COLON type_v
{ Dparam ($2, $4) } { Dparam (add_lab $2 $3, $5) }
| EXCEPTION uident | EXCEPTION uident labels
{ Dexn ($2, None) } { Dexn (add_lab $2 $3, None) }
| EXCEPTION uident OF pure_type | EXCEPTION uident labels OF pure_type
{ Dexn ($2, Some $4) } { Dexn (add_lab $2 $3, Some $5) }
; ;
list1_recfun_sep_and: list1_recfun_sep_and:
...@@ -207,16 +218,16 @@ list1_recfun_sep_and: ...@@ -207,16 +218,16 @@ list1_recfun_sep_and:
; ;
recfun: recfun:
| lident list1_type_v_binder opt_cast opt_variant EQUAL triple | lident labels list1_type_v_binder opt_cast opt_variant EQUAL triple
{ $1, $2, $4, cast_body $3 $6 } { add_lab $1 $2, $3, $5, cast_body $4 $7 }
; ;
lident: lident:
| LIDENT { { id = $1; id_loc = loc () } } | LIDENT { { id = $1; id_lab = []; id_loc = loc () } }
; ;
uident: uident:
| UIDENT { { id = $1; id_loc = loc () } } | UIDENT { { id = $1; id_lab = []; id_loc = loc () } }
; ;
ident: ident:
...@@ -253,7 +264,7 @@ expr: ...@@ -253,7 +264,7 @@ expr:
{ mk_infix $1 "=" $3 } { mk_infix $1 "=" $3 }
| expr LTGT expr | expr LTGT expr
{ let t = mk_infix $1 "=" $3 in { let t = mk_infix $1 "=" $3 in
mk_expr (mk_apply_id { id = "notb"; id_loc = loc () } [t]) } mk_expr (mk_apply_id { id = "notb"; id_lab = []; id_loc = loc () } [t]) }
| expr OP1 expr | expr OP1 expr
{ mk_infix $1 $2 $3 } { mk_infix $1 $2 $3 }
| expr OP2 expr | expr OP2 expr
...@@ -263,7 +274,7 @@ expr: ...@@ -263,7 +274,7 @@ expr:
| expr OP4 expr | expr OP4 expr
{ mk_infix $1 $2 $3 } { mk_infix $1 $2 $3 }
| NOT expr %prec prefix_op | NOT expr %prec prefix_op
{ mk_expr (mk_apply_id { id = "notb"; id_loc = loc () } [$2]) } { mk_expr (mk_apply_id { id = "notb"; id_lab = []; id_loc = loc () } [$2]) }
| any_op expr %prec prefix_op | any_op expr %prec prefix_op
{ mk_prefix $1 $2 } { mk_prefix $1 $2 }
| expr COLONEQUAL expr | expr COLONEQUAL expr
...@@ -286,8 +297,8 @@ expr: ...@@ -286,8 +297,8 @@ expr:
{ match $2.pat_desc with { match $2.pat_desc with
| PPpvar id -> mk_expr (Elet (id, $4, $6)) | PPpvar id -> mk_expr (Elet (id, $4, $6))
| _ -> mk_expr (Ematch ($4, [$2, $6])) } | _ -> mk_expr (Ematch ($4, [$2, $6])) }
| LET lident list1_type_v_binder EQUAL triple IN expr | LET lident labels list1_type_v_binder EQUAL triple IN expr
{ mk_expr (Elet ($2, mk_expr_i 3 (Efun ($3, $5)), $7)) } { mk_expr (Elet (add_lab $2 $3, mk_expr_i 6 (Efun ($4, $6)), $8)) }
| LET REC list1_recfun_sep_and IN expr | LET REC list1_recfun_sep_and IN expr
{ mk_expr (Eletrec ($3, $5)) } { mk_expr (Eletrec ($3, $5)) }
| FUN list1_type_v_binder ARROW triple