Added filter and map operators

This commit is contained in:
Denis Merigoux 2021-01-10 18:11:46 +01:00
parent f51d8833c7
commit e5c6a196e2
14 changed files with 385 additions and 299 deletions

View File

@ -381,9 +381,26 @@ let rec translate_expr (scope : Scopelang.Ast.ScopeName.t) (ctxt : Name_resoluti
Bindlib.box_apply
(fun es -> (Scopelang.Ast.EArray es, pos))
(Bindlib.box_list (List.map rec_helper es))
| CollectionOp ((Ast.Map, _pos_op'), _param', _collection, _predicate) -> failwith "unimplemented"
| CollectionOp ((Ast.Filter, _pos_op'), _param', _collection, _predicate) ->
failwith "unimplemented"
| CollectionOp ((((Ast.Filter | Ast.Map) as op'), _pos_op'), param', collection, predicate) ->
let collection = rec_helper collection in
let ctxt, param = Name_resolution.add_def_local_var ctxt param' in
let f_pred =
Scopelang.Ast.make_abs [| param |]
(translate_expr scope ctxt predicate)
pos [ (Scopelang.Ast.TAny, pos) ] pos
in
Bindlib.box_apply2
(fun f_pred collection ->
( Scopelang.Ast.EApp
( ( Scopelang.Ast.EOp
( match op' with
| Ast.Map -> Dcalc.Ast.Binop Dcalc.Ast.Map
| Ast.Filter -> Dcalc.Ast.Binop Dcalc.Ast.Filter
| _ -> assert false (* should not happen *) ),
pos ),
[ f_pred; collection ] ),
pos ))
f_pred collection
| CollectionOp
( (Ast.Aggregate (Ast.AggregateArgExtremum (max_or_min, pred_typ, init)), pos_op'),
param',

View File

@ -79,6 +79,8 @@ let token_list : (string * token) list =
("increasing", INCREASING);
("maximum", MAXIMUM);
("minimum", MINIMUM);
("filter", FILTER);
("map", MAP);
("init", INIT);
("of", OF);
("set", COLLECTION);
@ -311,6 +313,12 @@ let rec lex_code (lexbuf : lexbuf) : token =
| "minimum" ->
update_acc lexbuf;
MINIMUM
| "filter" ->
update_acc lexbuf;
FILTER
| "map" ->
update_acc lexbuf;
MAP
| "init" ->
update_acc lexbuf;
INIT

View File

@ -72,6 +72,8 @@ let token_list_en : (string * token) list =
("not", NOT);
("maximum", MAXIMUM);
("minimum", MINIMUM);
("filter", FILTER);
("map", MAP);
("initial", INIT);
("number", CARDINAL);
("year", YEAR);
@ -265,6 +267,12 @@ let rec lex_code_en (lexbuf : lexbuf) : token =
| "minimum" ->
L.update_acc lexbuf;
MINIMUM
| "filter" ->
L.update_acc lexbuf;
FILTER
| "map" ->
L.update_acc lexbuf;
MAP
| "initial" ->
L.update_acc lexbuf;
INIT

View File

@ -71,6 +71,8 @@ let token_list_fr : (string * token) list =
("nombre", CARDINAL);
("maximum", MAXIMUM);
("minimum", MINIMUM);
("filtre", FILTER);
("application", MAP);
("initial", INIT);
("an", YEAR);
("mois", MONTH);
@ -260,6 +262,12 @@ let rec lex_code_fr (lexbuf : lexbuf) : token =
| "minimum" ->
L.update_acc lexbuf;
MINIMUM
| "filtre" ->
L.update_acc lexbuf;
FILTER
| "application" ->
L.update_acc lexbuf;
MAP
| "initial" ->
L.update_acc lexbuf;
INIT

File diff suppressed because it is too large Load Diff

View File

@ -65,6 +65,7 @@
%token LABEL EXCEPTION LSQUARE RSQUARE SEMICOLON
%token INT_TO_DEC MAXIMUM MINIMUM INIT
%token GET_DAY GET_MONTH GET_YEAR
%token FILTER MAP
%type <Ast.source_file_or_master> source_file_or_master
@ -238,6 +239,8 @@ aggregate_func:
}
| SUM t = typ_base { (Aggregate (AggregateSum (Pos.unmark t)), $sloc) }
| CARDINAL { (Aggregate AggregateCount, $sloc) }
| FILTER { (Filter, $sloc ) }
| MAP { (Map, $sloc) }
aggregate:
| func = aggregate_func FOR i = ident IN e1 = primitive_expression

View File

@ -13,11 +13,11 @@ let message s =
"expected another inclusion of a Catala file, since this file is a master file which can \
only contain inclusions of other Catala files\n"
| 8 -> "expected some text, another heading or a law article\n"
| 366 -> "expected a heading, an article title or some text\n"
| 351 -> "expected an article title, another heading or some text\n"
| 356 -> "expected a code block, a metadata block, more law text or a heading\n"
| 362 -> "expected a code block, a metadata block, more law text or a heading\n"
| 357 -> "expected a declaration or a scope use\n"
| 368 -> "expected a heading, an article title or some text\n"
| 353 -> "expected an article title, another heading or some text\n"
| 358 -> "expected a code block, a metadata block, more law text or a heading\n"
| 364 -> "expected a code block, a metadata block, more law text or a heading\n"
| 359 -> "expected a declaration or a scope use\n"
| 22 -> "expected the name of the scope you want to use\n"
| 24 -> "expected a scope use precondition or a colon\n"
| 25 -> "expected an expression which will act as the condition\n"
@ -28,137 +28,137 @@ let message s =
| 31 -> "expected the third component of the date literal\n"
| 32 -> "expected a delimiter to finish the date literal\n"
| 70 -> "expected an operator to compose the expression on the left with\n"
| 108 -> "expected an enum constructor to test if the expression on the left\n"
| 107 -> "expected an operator to compose the expression on the left with\n"
| 134 -> "expected an expression on the right side of the sum or minus operator\n"
| 176 -> "expected an expression on the right side of the logical operator\n"
| 110 -> "expected an expression for the argument of this function call\n"
| 168 -> "expected an expression on the right side of the comparison operator\n"
| 143 -> "expected an expression on the right side of the multiplication or division operator\n"
| 136 -> "expected an operator to compose the expression on the left\n"
| 121 -> "expected an expression standing for the set you want to test for membership\n"
| 110 -> "expected an enum constructor to test if the expression on the left\n"
| 109 -> "expected an operator to compose the expression on the left with\n"
| 136 -> "expected an expression on the right side of the sum or minus operator\n"
| 178 -> "expected an expression on the right side of the logical operator\n"
| 112 -> "expected an expression for the argument of this function call\n"
| 170 -> "expected an expression on the right side of the comparison operator\n"
| 145 -> "expected an expression on the right side of the multiplication or division operator\n"
| 138 -> "expected an operator to compose the expression on the left\n"
| 123 -> "expected an expression standing for the set you want to test for membership\n"
| 71 -> "expected an identifier standing for a struct field or a subscope name\n"
| 234 -> "expected a colon after the scope use precondition\n"
| 236 -> "expected a colon after the scope use precondition\n"
| 73 -> "expected a constructor, to get the payload of this enum case\n"
| 35 -> "expected the \"for\" keyword to spell the aggregation\n"
| 170 -> "expected an expression to take the negation of\n"
| 105 -> "expected an expression to take the opposite of\n"
| 172 -> "expected an expression to take the negation of\n"
| 107 -> "expected an expression to take the opposite of\n"
| 59 -> "expected an expression to match with\n"
| 76 -> "expected a pattern matching case\n"
| 77 -> "expected the name of the constructor for the enum case in the pattern matching\n"
| 190 ->
| 192 ->
"expected a binding for the constructor payload, or a colon and the matching case expression\n"
| 191 -> "expected an identifier for this enum case binding\n"
| 193 -> "expected an identifier for this enum case binding\n"
| 80 -> "expected a colon and then the expression for this matching case\n"
| 193 -> "expected a colon or a binding for the enum constructor payload\n"
| 195 -> "expected a colon or a binding for the enum constructor payload\n"
| 81 -> "expected an expression for this pattern matching case\n"
| 78 ->
"expected another match case or the rest of the expression since the previous match case is \
complete\n"
| 75 -> "expected the \"with patter\" keyword to complete the pattern matching expression\n"
| 58 -> "expected an expression inside the parenthesis\n"
| 222 -> "unmatched parenthesis that should have been closed by here\n"
| 87 -> "expected a unit for this literal, or a valid operator to complete the expression \n"
| 197 -> "expected an expression for the test of the conditional\n"
| 218 -> "expected an expression the for the \"then\" branch of the conditiona\n"
| 219 ->
| 224 -> "unmatched parenthesis that should have been closed by here\n"
| 89 -> "expected a unit for this literal, or a valid operator to complete the expression \n"
| 199 -> "expected an expression for the test of the conditional\n"
| 220 -> "expected an expression the for the \"then\" branch of the conditiona\n"
| 221 ->
"expected the \"else\" branch of this conditional expression as the \"then\" branch is \
complete\n"
| 220 -> "expected an expression for the \"else\" branch of this conditional construction\n"
| 217 -> "expected the \"then\" keyword as the conditional expression is complete\n"
| 198 ->
| 222 -> "expected an expression for the \"else\" branch of this conditional construction\n"
| 219 -> "expected the \"then\" keyword as the conditional expression is complete\n"
| 200 ->
"expected the \"all\" keyword to mean the \"for all\" construction of the universal test\n"
| 203 -> "expected an identifier for the bound variable of the universal test\n"
| 204 -> "expected the \"in\" keyword for the rest of the universal test\n"
| 205 -> "expected the expression designating the set on which to perform the universal test\n"
| 206 -> "expected the \"we have\" keyword for this universal test\n"
| 202 -> "expected an expression for the universal test\n"
| 211 -> "expected an identifier that will designate the existential witness for the test\n"
| 212 -> "expected the \"in\" keyword to continue this existential test\n"
| 213 -> "expected an expression that designates the set subject to the existential test\n"
| 214 -> "expected a keyword to form the \"such that\" expression for the existential test\n"
| 215 -> "expected a keyword to complete the \"such that\" construction\n"
| 209 -> "expected an expression for the existential test\n"
| 96 ->
| 205 -> "expected an identifier for the bound variable of the universal test\n"
| 206 -> "expected the \"in\" keyword for the rest of the universal test\n"
| 207 -> "expected the expression designating the set on which to perform the universal test\n"
| 208 -> "expected the \"we have\" keyword for this universal test\n"
| 204 -> "expected an expression for the universal test\n"
| 213 -> "expected an identifier that will designate the existential witness for the test\n"
| 214 -> "expected the \"in\" keyword to continue this existential test\n"
| 215 -> "expected an expression that designates the set subject to the existential test\n"
| 216 -> "expected a keyword to form the \"such that\" expression for the existential test\n"
| 217 -> "expected a keyword to complete the \"such that\" construction\n"
| 211 -> "expected an expression for the existential test\n"
| 98 ->
"expected a payload for the enum case constructor, or the rest of the expression (with an \
operator ?)\n"
| 97 -> "expected structure fields introduced by --\n"
| 98 -> "expected the name of the structure field\n"
| 102 -> "expected a colon\n"
| 103 -> "expected the expression for this struct field\n"
| 99 -> "expected another structure field or the closing bracket\n"
| 99 -> "expected structure fields introduced by --\n"
| 100 -> "expected the name of the structure field\n"
| 180 -> "expected an expression for the content of this enum case\n"
| 181 ->
| 104 -> "expected a colon\n"
| 105 -> "expected the expression for this struct field\n"
| 101 -> "expected another structure field or the closing bracket\n"
| 102 -> "expected the name of the structure field\n"
| 182 -> "expected an expression for the content of this enum case\n"
| 183 ->
"the expression for the content of the enum case is already well-formed, expected an \
operator to form a bigger expression\n"
| 104 -> "expected the keyword following cardinal to compute the number of elements in a set\n"
| 235 -> "expected a scope use item: a rule, definition or assertion\n"
| 270 -> "expected the name of the variable subject to the rule\n"
| 248 ->
| 106 -> "expected the keyword following cardinal to compute the number of elements in a set\n"
| 237 -> "expected a scope use item: a rule, definition or assertion\n"
| 272 -> "expected the name of the variable subject to the rule\n"
| 250 ->
"expected a condition or a consequence for this rule, or the rest of the variable qualified \
name\n"
| 277 -> "expected a condition or a consequence for this rule\n"
| 272 -> "expected filled or not filled for a rule consequence\n"
| 278 -> "expected the name of the parameter for this dependent variable \n"
| 271 -> "expected the expression of the rule\n"
| 275 -> "expected the filled keyword the this rule \n"
| 249 -> "expected a struct field or a sub-scope context item after the dot\n"
| 236 -> "expected the name of the label\n"
| 266 -> "expected a rule or a definition after the label declaration\n"
| 267 -> "expected the label to which the exception is referring back\n"
| 269 -> "expected a rule or a definition after the exception declaration\n"
| 282 -> "expected the name of the variable you want to define\n"
| 283 -> "expected the defined as keyword to introduce the definition of this variable\n"
| 285 -> "expected an expression for the consequence of this definition under condition\n"
| 284 ->
| 279 -> "expected a condition or a consequence for this rule\n"
| 274 -> "expected filled or not filled for a rule consequence\n"
| 280 -> "expected the name of the parameter for this dependent variable \n"
| 273 -> "expected the expression of the rule\n"
| 277 -> "expected the filled keyword the this rule \n"
| 251 -> "expected a struct field or a sub-scope context item after the dot\n"
| 238 -> "expected the name of the label\n"
| 268 -> "expected a rule or a definition after the label declaration\n"
| 269 -> "expected the label to which the exception is referring back\n"
| 271 -> "expected a rule or a definition after the exception declaration\n"
| 284 -> "expected the name of the variable you want to define\n"
| 285 -> "expected the defined as keyword to introduce the definition of this variable\n"
| 287 -> "expected an expression for the consequence of this definition under condition\n"
| 286 ->
"expected a expression for defining this function, introduced by the defined as keyword\n"
| 286 -> "expected an expression for the definition\n"
| 238 -> "expected an expression that shoud be asserted during execution\n"
| 239 -> "expecting the name of the varying variable\n"
| 242 -> "the variable varies with an expression that was expected here\n"
| 243 -> "expected an indication about the variation sense of the variable, or a new scope item\n"
| 241 -> "expected an indication about what this variable varies with\n"
| 251 -> "expected an expression for this condition\n"
| 261 -> "expected a consequence for this definition under condition\n"
| 257 -> "expected an expression for this definition under condition\n"
| 253 -> "expected the name of the variable that should be fixed\n"
| 254 -> "expected the legislative text by which the value of the variable is fixed\n"
| 255 -> "expected the legislative text by which the value of the variable is fixed\n"
| 264 -> "expected a new scope use item \n"
| 293 -> "expected the kind of the declaration (struct, scope or enum)\n"
| 294 -> "expected the struct name\n"
| 295 -> "expected a colon\n"
| 296 -> "expected struct data or condition\n"
| 297 -> "expected the name of this struct data \n"
| 298 -> "expected the type of this struct data, introduced by the content keyword\n"
| 299 -> "expected the type of this struct data\n"
| 313 -> "expected the name of this struct condition\n"
| 306 -> "expected a new struct data, or another declaration or scope use\n"
| 307 -> "expected the type of the parameter of this struct data function\n"
| 311 -> "expected a new struct data, or another declaration or scope use\n"
| 303 -> "expected a new struct data, or another declaration or scope use\n"
| 316 -> "expected the name of the scope you are declaring\n"
| 317 -> "expected a colon followed by the list of context items of this scope\n"
| 318 -> "expected a context item introduced by \"context\"\n"
| 319 -> "expected the name of this new context item\n"
| 320 -> "expected the kind of this context item: is it a condition, a sub-scope or a data?\n"
| 321 -> "expected the name of the subscope for this context item\n"
| 328 -> "expected another scope context item or the end of the scope declaration\n"
| 323 -> "expected the type of this context item\n"
| 324 -> "expected the next context item or a dependency declaration for this item\n"
| 288 -> "expected an expression for the definition\n"
| 240 -> "expected an expression that shoud be asserted during execution\n"
| 241 -> "expecting the name of the varying variable\n"
| 244 -> "the variable varies with an expression that was expected here\n"
| 245 -> "expected an indication about the variation sense of the variable, or a new scope item\n"
| 243 -> "expected an indication about what this variable varies with\n"
| 253 -> "expected an expression for this condition\n"
| 263 -> "expected a consequence for this definition under condition\n"
| 259 -> "expected an expression for this definition under condition\n"
| 255 -> "expected the name of the variable that should be fixed\n"
| 256 -> "expected the legislative text by which the value of the variable is fixed\n"
| 257 -> "expected the legislative text by which the value of the variable is fixed\n"
| 266 -> "expected a new scope use item \n"
| 295 -> "expected the kind of the declaration (struct, scope or enum)\n"
| 296 -> "expected the struct name\n"
| 297 -> "expected a colon\n"
| 298 -> "expected struct data or condition\n"
| 299 -> "expected the name of this struct data \n"
| 300 -> "expected the type of this struct data, introduced by the content keyword\n"
| 301 -> "expected the type of this struct data\n"
| 315 -> "expected the name of this struct condition\n"
| 308 -> "expected a new struct data, or another declaration or scope use\n"
| 309 -> "expected the type of the parameter of this struct data function\n"
| 313 -> "expected a new struct data, or another declaration or scope use\n"
| 305 -> "expected a new struct data, or another declaration or scope use\n"
| 318 -> "expected the name of the scope you are declaring\n"
| 319 -> "expected a colon followed by the list of context items of this scope\n"
| 320 -> "expected a context item introduced by \"context\"\n"
| 321 -> "expected the name of this new context item\n"
| 322 -> "expected the kind of this context item: is it a condition, a sub-scope or a data?\n"
| 323 -> "expected the name of the subscope for this context item\n"
| 330 -> "expected another scope context item or the end of the scope declaration\n"
| 325 -> "expected the type of this context item\n"
| 326 -> "expected the next context item or a dependency declaration for this item\n"
| 331 -> "expected the name of your enum\n"
| 332 -> "expected a colon\n"
| 333 -> "expected an enum case\n"
| 334 -> "expected the name of an enum case \n"
| 335 -> "expected a payload for your enum case, or another case or declaration \n"
| 336 -> "expected a content type\n"
| 341 -> "expected another enum case, or a new declaration or scope use\n"
| 328 -> "expected the next context item or a dependency declaration for this item\n"
| 333 -> "expected the name of your enum\n"
| 334 -> "expected a colon\n"
| 335 -> "expected an enum case\n"
| 336 -> "expected the name of an enum case \n"
| 337 -> "expected a payload for your enum case, or another case or declaration \n"
| 338 -> "expected a content type\n"
| 343 -> "expected another enum case, or a new declaration or scope use\n"
| 18 -> "expected a declaration or a scope use\n"
| 19 -> "expected some text or the beginning of a code section\n"
| 20 -> "expected a declaration or a scope use\n"
| 21 -> "should not happen\n"
| 347 -> "expected a metadata-closing tag\n"
| 348 -> "expected a metadata-closing tag\n"
| 349 -> "expected a metadata-closing tag\n"
| 350 -> "expected a metadata-closing tag\n"
| _ -> raise Not_found

View File

@ -66,6 +66,7 @@ type binop =
| Eq
| Neq
| Map
| Filter
type log_entry = VarDef | BeginCall | EndCall

View File

@ -190,6 +190,18 @@ let rec evaluate_operator (op : A.operator Pos.marked) (args : A.expr Pos.marked
(List.map
(fun e' -> evaluate_expr (Pos.same_pos_as (A.EApp (List.nth args 0, [ e' ])) e'))
es)
| A.Binop A.Filter, [ _; A.EArray es ] ->
A.EArray
(List.filter
(fun e' ->
match evaluate_expr (Pos.same_pos_as (A.EApp (List.nth args 0, [ e' ])) e') with
| A.ELit (A.LBool b), _ -> b
| _ ->
Errors.raise_spanned_error
"This predicate evaluated to something else than a boolean (should not happen \
if the term was well-typed)"
(Pos.get_position (List.nth args 0)))
es)
| A.Binop _, ([ ELit LEmptyError; _ ] | [ _; ELit LEmptyError ]) -> A.ELit LEmptyError
| A.Unop (A.Minus KInt), [ ELit (LInt i) ] -> A.ELit (LInt (Z.sub Z.zero i))
| A.Unop (A.Minus KRat), [ ELit (LRat i) ] -> A.ELit (LRat (Q.sub Q.zero i))

View File

@ -135,6 +135,7 @@ let format_binop (fmt : Format.formatter) (op : binop Pos.marked) : unit =
| Gt k -> Format.fprintf fmt "%s%a" ">" format_op_kind k
| Gte k -> Format.fprintf fmt "%s%a" ">=" format_op_kind k
| Map -> Format.fprintf fmt "map"
| Filter -> Format.fprintf fmt "filter"
let format_ternop (fmt : Format.formatter) (op : ternop Pos.marked) : unit =
match Pos.unmark op with Fold -> Format.fprintf fmt "fold"
@ -228,6 +229,9 @@ let rec format_expr (fmt : Format.formatter) (e : expr Pos.marked) : unit =
(fun fmt (x, tau) ->
Format.fprintf fmt "@[<hov 2>(%a:@ %a)@]" format_var x format_typ tau))
xs_tau format_expr body
| EApp ((EOp (Binop ((Ast.Map | Ast.Filter) as op)), _), [ arg1; arg2 ]) ->
Format.fprintf fmt "@[<hov 2>%a@ %a@ %a@]" format_binop (op, Pos.no_pos) format_with_parens
arg1 format_with_parens arg2
| EApp ((EOp (Binop op), _), [ arg1; arg2 ]) ->
Format.fprintf fmt "@[<hov 2>%a@ %a@ %a@]" format_with_parens arg1 format_binop
(op, Pos.no_pos) format_with_parens arg2

View File

@ -124,6 +124,7 @@ let op_type (op : A.operator Pos.marked) : typ Pos.marked UnionFind.elem =
let any = UnionFind.make (TAny (Any.fresh ()), pos) in
let array_any = UnionFind.make (TArray any, pos) in
let any2 = UnionFind.make (TAny (Any.fresh ()), pos) in
let array_any2 = UnionFind.make (TArray any2, pos) in
let arr x y = UnionFind.make (TArrow (x, y), pos) in
match Pos.unmark op with
| A.Ternop A.Fold -> arr (arr any2 (arr any any2)) (arr any2 (arr array_any any2))
@ -143,7 +144,8 @@ let op_type (op : A.operator Pos.marked) : typ Pos.marked UnionFind.elem =
| A.Binop (A.Lt KDuration | A.Lte KDuration | A.Gt KDuration | A.Gte KDuration) ->
arr dut (arr dut bt)
| A.Binop (A.Eq | A.Neq) -> arr any (arr any bt)
| A.Binop A.Map -> arr (arr any any2) (arr array_any any2)
| A.Binop A.Map -> arr (arr any any2) (arr array_any array_any2)
| A.Binop A.Filter -> arr (arr any bt) (arr array_any array_any)
| A.Unop (A.Minus KInt) -> arr it it
| A.Unop (A.Minus KRat) -> arr rt rt
| A.Unop (A.Minus KMoney) -> arr mt mt

View File

@ -0,0 +1,18 @@
@Article@
/*
new scope A:
param x content set money
scope A:
def x := [$0; $4 +$ $5; $8 *$ 0.65]
new scope B:
param a scope A
param y content set money
param z content set bool
scope B:
def y := filter for m in a.x of (m >=$ $4.95)
def z := map for m in a.x of (m >=$ $4.95)
*/

View File

@ -0,0 +1,2 @@
[RESULT] Computation successful! Results:
[RESULT] x = [$0.00; $9.00; $5.20]

View File

@ -0,0 +1,3 @@
[RESULT] Computation successful! Results:
[RESULT] y = [$9.00; $5.20]
[RESULT] z = [false; true; true]