58
58
| {contract_code , string ()} % % for CREATE, by name
59
59
| {typerep , ftype ()}.
60
60
61
- -type fann () :: [ {file , aeso_syntax :ann_file ()} | {line , aeso_syntax :ann_line ()} ].
61
+ -type fann () :: [ {file , aeso_syntax :ann_file ()} |
62
+ {line , aeso_syntax :ann_line ()} |
63
+ {col , aeso_syntax :ann_col ()}
64
+ ].
62
65
63
66
-type fexpr () :: {lit , fann (), flit ()}
64
67
| {nil , fann ()}
@@ -387,11 +390,23 @@ to_fcode(Env, [{namespace, _, {con, _, Con}, Decls} | Code]) ->
387
390
Env1 = decls_to_fcode (Env #{ context => {namespace , Con } }, Decls ),
388
391
to_fcode (Env1 , Code ).
389
392
393
+ -spec ann_loc (aeso_syntax :ann () | fann ()) -> {File , Line , Column } when
394
+ File :: string () | none ,
395
+ Line :: non_neg_integer () | none ,
396
+ Column :: non_neg_integer () | none .
397
+ ann_loc (Ann ) ->
398
+ File = proplists :get_value (file , Ann , none ),
399
+ Line = proplists :get_value (line , Ann , none ),
400
+ Col = proplists :get_value (col , Ann , none ),
401
+ {File , Line , Col }.
402
+
390
403
-spec to_fann (aeso_syntax :ann ()) -> fann ().
391
404
to_fann (Ann ) ->
392
- File = proplists :lookup (file , Ann ),
393
- Line = proplists :lookup (line , Ann ),
394
- [ X || X <- [File , Line ], X =/= none ].
405
+ {File , Line , Col } = ann_loc (Ann ),
406
+ [ {Tag , X } ||
407
+ {Tag , X } <- [{file , File }, {line , Line }, {col , Col }],
408
+ X =/= none , X =/= no_file
409
+ ].
395
410
396
411
-spec get_fann (fexpr ()) -> fann ().
397
412
get_fann (FExpr ) -> element (2 , FExpr ).
@@ -1276,10 +1291,13 @@ event_function(_Env = #{event_type := {variant_t, EventCons}}, EventType = {vari
1276
1291
1277
1292
-spec lambda_lift (fcode ()) -> fcode ().
1278
1293
lambda_lift (FCode = #{ functions := Funs , state_layout := StateLayout }) ->
1279
- init_lambda_funs (),
1280
- Funs1 = maps :map (fun (_ , Body ) -> lambda_lift_fun (StateLayout , Body ) end , Funs ),
1281
- NewFuns = get_lambda_funs (),
1282
- FCode #{ functions := maps :merge (Funs1 , NewFuns ) }.
1294
+ NewFuns =
1295
+ [ {FunName , FunDef }
1296
+ || {ParentName , ParentDef } <- maps :to_list (Funs ),
1297
+ {NewParentDef , Lambdas } <- [lambda_lift_fun (StateLayout , ParentName , ParentDef )],
1298
+ {FunName , FunDef } <- [{ParentName , NewParentDef } | maps :to_list (Lambdas )]
1299
+ ],
1300
+ FCode #{ functions := maps :from_list (NewFuns ) }.
1283
1301
1284
1302
-define (lambda_key , '%lambdalifted' ).
1285
1303
@@ -1289,16 +1307,35 @@ init_lambda_funs() -> put(?lambda_key, #{}).
1289
1307
-spec get_lambda_funs () -> term ().
1290
1308
get_lambda_funs () -> erase (? lambda_key ).
1291
1309
1292
- -spec add_lambda_fun (fun_def ()) -> fun_name ().
1293
- add_lambda_fun (Def ) ->
1294
- Name = fresh_fun (),
1310
+ -spec add_lambda_fun (fun_name (), fann (), fun_def ()) -> fun_name ().
1311
+ add_lambda_fun (Parent , FAnn , Def ) ->
1295
1312
Funs = get (? lambda_key ),
1296
- put (? lambda_key , Funs #{ Name => Def }),
1313
+ LambdaId = maps :get ({fresh , Parent }, Funs , 0 ),
1314
+ Name = lambda_name (FAnn , LambdaId , Parent ),
1315
+ put (? lambda_key , Funs #{ Name => Def , {fresh , Parent } => LambdaId + 1 }),
1297
1316
Name .
1298
1317
1299
- -spec lambda_lift_fun (state_layout (), fun_def ()) -> fun_def ().
1300
- lambda_lift_fun (Layout , Def = #{ body := Body }) ->
1301
- Def #{ body := lambda_lift_expr (Layout , Body ) }.
1318
+ -spec lambda_name (fann (), non_neg_integer (), fun_name ()) -> fun_name ().
1319
+ lambda_name (FAnn , Id , PName ) ->
1320
+ PSName = case PName of
1321
+ {entrypoint , N } -> [binary_to_list (N )];
1322
+ {local_fun , Ns } -> Ns
1323
+ end ,
1324
+ {_File , Line , Col } = ann_loc (FAnn ),
1325
+ Name = PSName ++
1326
+ [ " %lambda"
1327
+ , if is_integer (Line ) -> integer_to_list (Line ); true -> " " end
1328
+ , if is_integer (Col ) -> integer_to_list (Col ); true -> " " end
1329
+ , integer_to_list (Id )],
1330
+ {local_fun , Name }.
1331
+
1332
+ -spec lambda_lift_fun (state_layout (), fun_name (), fun_def ()) -> {fun_def (), #{var_name () => term ()}}.
1333
+ lambda_lift_fun (Layout , Name , Def = #{ body := Body }) ->
1334
+ % % Not thread safe! We initialize state per functions not to depend on the order in which
1335
+ % % functions are processed.
1336
+ init_lambda_funs (),
1337
+ NewDef = Def #{ body := lambda_lift_expr (Layout , Name , Body ) },
1338
+ {NewDef , get_lambda_funs ()}.
1302
1339
1303
1340
-spec lifted_fun ([var_name ()], [var_name ()], fexpr ()) -> fun_def ().
1304
1341
lifted_fun ([Z ], Xs , Body ) ->
@@ -1316,21 +1353,20 @@ lifted_fun(FVs, Xs, Body) ->
1316
1353
body => lists :foldr (Proj , Body , indexed (FVs ))
1317
1354
}.
1318
1355
1319
- -spec make_closure ([var_name ()], [var_name ()], fexpr ()) -> Closure when
1356
+ -spec make_closure (fun_name (), fann (), [var_name ()], [var_name ()], fexpr ()) -> Closure when
1320
1357
Closure :: fexpr ().
1321
- make_closure (FVs , Xs , Body ) ->
1322
- Fun = add_lambda_fun (lifted_fun (FVs , Xs , Body )),
1323
- FAnn = get_fann (Body ),
1358
+ make_closure (ParentName , FAnn , FVs , Xs , Body ) ->
1359
+ Name = add_lambda_fun (ParentName , FAnn , lifted_fun (FVs , Xs , Body )),
1324
1360
Tup = fun ([Y ]) -> Y ; (Ys ) -> {tuple , FAnn , Ys } end ,
1325
- {closure , FAnn , Fun , Tup ([{var , FAnn , Y } || Y <- FVs ])}.
1361
+ {closure , FAnn , Name , Tup ([{var , FAnn , Y } || Y <- FVs ])}.
1326
1362
1327
- -spec lambda_lift_expr (state_layout (), fexpr ()) -> Closure when
1363
+ -spec lambda_lift_expr (state_layout (), fun_name (), fexpr ()) -> Closure when
1328
1364
Closure :: fexpr ().
1329
- lambda_lift_expr (Layout , L = {lam , _ , Xs , Body }) ->
1365
+ lambda_lift_expr (Layout , Name , L = {lam , FAnn , Xs , Body }) ->
1330
1366
FVs = free_vars (L ),
1331
- make_closure (FVs , Xs , lambda_lift_expr (Layout , Body ));
1332
- lambda_lift_expr (Layout , UExpr ) when element (1 , UExpr ) == def_u ; element (1 , UExpr ) == builtin_u ->
1333
- [Tag , _ , F , Ar | _ ] = tuple_to_list (UExpr ),
1367
+ make_closure (Name , FAnn , FVs , Xs , lambda_lift_expr (Layout , Name , Body ));
1368
+ lambda_lift_expr (Layout , Name , UExpr ) when element (1 , UExpr ) == def_u ; element (1 , UExpr ) == builtin_u ->
1369
+ [Tag , FAnn , F , Ar | _ ] = tuple_to_list (UExpr ),
1334
1370
ExtraArgs = case UExpr of
1335
1371
{builtin_u , _ , _ , _ , TypeArgs } -> TypeArgs ;
1336
1372
_ -> []
@@ -1341,41 +1377,41 @@ lambda_lift_expr(Layout, UExpr) when element(1, UExpr) == def_u; element(1, UExp
1341
1377
builtin_u -> builtin_to_fcode (Layout , get_fann (UExpr ), F , Args );
1342
1378
def_u -> {def , get_fann (UExpr ), F , Args }
1343
1379
end ,
1344
- make_closure ([], Xs , Body );
1345
- lambda_lift_expr (Layout , {remote_u , FAnn , ArgsT , RetT , Ct , F }) ->
1380
+ make_closure (Name , FAnn , [], Xs , Body );
1381
+ lambda_lift_expr (Layout , Name , {remote_u , FAnn , ArgsT , RetT , Ct , F }) ->
1346
1382
FVs = free_vars (Ct ),
1347
- Ct1 = lambda_lift_expr (Layout , Ct ),
1383
+ Ct1 = lambda_lift_expr (Layout , Name , Ct ),
1348
1384
NamedArgCount = 3 ,
1349
1385
Xs = [ lists :concat ([" arg" , I ]) || I <- lists :seq (1 , length (ArgsT ) + NamedArgCount ) ],
1350
1386
Args = [{var , [], X } || X <- Xs ],
1351
- make_closure (FVs , Xs , {remote , FAnn , ArgsT , RetT , Ct1 , F , Args });
1352
- lambda_lift_expr (Layout , Expr ) ->
1387
+ make_closure (Name , FAnn , FVs , Xs , {remote , FAnn , ArgsT , RetT , Ct1 , F , Args });
1388
+ lambda_lift_expr (Layout , Name , Expr ) ->
1353
1389
case Expr of
1354
1390
{lit , _ , _ } -> Expr ;
1355
1391
{nil , _ } -> Expr ;
1356
1392
{var , _ , _ } -> Expr ;
1357
1393
{closure , _ , _ , _ } -> Expr ;
1358
- {def , FAnn , D , As } -> {def , FAnn , D , lambda_lift_exprs (Layout , As )};
1359
- {builtin , FAnn , B , As } -> {builtin , FAnn , B , lambda_lift_exprs (Layout , As )};
1360
- {remote , FAnn , ArgsT , RetT , Ct , F , As } -> {remote , FAnn , ArgsT , RetT , lambda_lift_expr (Layout , Ct ), F , lambda_lift_exprs (Layout , As )};
1361
- {con , FAnn , Ar , C , As } -> {con , FAnn , Ar , C , lambda_lift_exprs (Layout , As )};
1362
- {tuple , FAnn , As } -> {tuple , FAnn , lambda_lift_exprs (Layout , As )};
1363
- {proj , FAnn , A , I } -> {proj , FAnn , lambda_lift_expr (Layout , A ), I };
1364
- {set_proj , FAnn , A , I , B } -> {set_proj , FAnn , lambda_lift_expr (Layout , A ), I , lambda_lift_expr (Layout , B )};
1365
- {op , FAnn , Op , As } -> {op , FAnn , Op , lambda_lift_exprs (Layout , As )};
1366
- {'let' , FAnn , X , A , B } -> {'let' , FAnn , X , lambda_lift_expr (Layout , A ), lambda_lift_expr (Layout , B )};
1367
- {funcall , FAnn , A , Bs } -> {funcall , FAnn , lambda_lift_expr (Layout , A ), lambda_lift_exprs (Layout , Bs )};
1368
- {set_state , FAnn , R , A } -> {set_state , FAnn , R , lambda_lift_expr (Layout , A )};
1394
+ {def , FAnn , D , As } -> {def , FAnn , D , lambda_lift_exprs (Layout , Name , As )};
1395
+ {builtin , FAnn , B , As } -> {builtin , FAnn , B , lambda_lift_exprs (Layout , Name , As )};
1396
+ {remote , FAnn , ArgsT , RetT , Ct , F , As } -> {remote , FAnn , ArgsT , RetT , lambda_lift_expr (Layout , Name , Ct ), F , lambda_lift_exprs (Layout , Name , As )};
1397
+ {con , FAnn , Ar , C , As } -> {con , FAnn , Ar , C , lambda_lift_exprs (Layout , Name , As )};
1398
+ {tuple , FAnn , As } -> {tuple , FAnn , lambda_lift_exprs (Layout , Name , As )};
1399
+ {proj , FAnn , A , I } -> {proj , FAnn , lambda_lift_expr (Layout , Name , A ), I };
1400
+ {set_proj , FAnn , A , I , B } -> {set_proj , FAnn , lambda_lift_expr (Layout , Name , A ), I , lambda_lift_expr (Layout , Name , B )};
1401
+ {op , FAnn , Op , As } -> {op , FAnn , Op , lambda_lift_exprs (Layout , Name , As )};
1402
+ {'let' , FAnn , X , A , B } -> {'let' , FAnn , X , lambda_lift_expr (Layout , Name , A ), lambda_lift_expr (Layout , Name , B )};
1403
+ {funcall , FAnn , A , Bs } -> {funcall , FAnn , lambda_lift_expr (Layout , Name , A ), lambda_lift_exprs (Layout , Name , Bs )};
1404
+ {set_state , FAnn , R , A } -> {set_state , FAnn , R , lambda_lift_expr (Layout , Name , A )};
1369
1405
{get_state , _ , _ } -> Expr ;
1370
- {switch , FAnn , S } -> {switch , FAnn , lambda_lift_expr (Layout , S )};
1371
- {split , Type , X , Alts } -> {split , Type , X , lambda_lift_exprs (Layout , Alts )};
1372
- {nosplit , Rens , A } -> {nosplit , Rens , lambda_lift_expr (Layout , A )};
1373
- {'case' , P , S } -> {'case' , P , lambda_lift_expr (Layout , S )}
1406
+ {switch , FAnn , S } -> {switch , FAnn , lambda_lift_expr (Layout , Name , S )};
1407
+ {split , Type , X , Alts } -> {split , Type , X , lambda_lift_exprs (Layout , Name , Alts )};
1408
+ {nosplit , Rens , A } -> {nosplit , Rens , lambda_lift_expr (Layout , Name , A )};
1409
+ {'case' , P , S } -> {'case' , P , lambda_lift_expr (Layout , Name , S )}
1374
1410
end .
1375
1411
1376
- -spec lambda_lift_exprs (state_layout (), [fexpr ()]) -> [Closure ] when
1412
+ -spec lambda_lift_exprs (state_layout (), fun_name (), [fexpr ()]) -> [Closure ] when
1377
1413
Closure :: fexpr ().
1378
- lambda_lift_exprs (Layout , As ) -> [lambda_lift_expr (Layout , A ) || A <- As ].
1414
+ lambda_lift_exprs (Layout , Name , As ) -> [lambda_lift_expr (Layout , Name , A ) || A <- As ].
1379
1415
1380
1416
% % -- Optimisations ----------------------------------------------------------
1381
1417
@@ -1900,9 +1936,6 @@ fresh_name_save(Name) ->
1900
1936
-spec fresh_name () -> var_name ().
1901
1937
fresh_name () -> fresh_name (" %" ).
1902
1938
1903
- -spec fresh_fun () -> fun_name ().
1904
- fresh_fun () -> {local_fun , [fresh_name (" ^" )]}.
1905
-
1906
1939
-spec fresh_name (string ()) -> var_name ().
1907
1940
fresh_name (Prefix ) ->
1908
1941
N = get ('%fresh' ),
0 commit comments