Skip to content

Commit f06c039

Browse files
authored
Merge pull request #100 from engboris/linear-constellations
Linear constellations
2 parents 83b0171 + ce823e6 commit f06c039

File tree

11 files changed

+245
-188
lines changed

11 files changed

+245
-188
lines changed

bin/lscrun.ml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,14 @@ open Lsc.Lsc_parser
55
open Lsc.Lsc_lexer
66
open Out_channel
77

8-
let usage_msg =
9-
"exec [-allow-unfinished-computation] [-show-steps] [-show-trace] <filename>"
8+
let usage_msg = "exec [-linear] [-show-trace] <filename>"
109

1110
let unfincomp = ref false
1211

1312
let showtrace = ref false
1413

14+
let linear = ref false
15+
1516
let input_file = ref ""
1617

1718
let anon_fun filename = input_file := filename
@@ -25,14 +26,15 @@ let speclist =
2526
; ( "-show-trace"
2627
, Stdlib.Arg.Set showtrace
2728
, "Interactively show steps of selection and unification." )
29+
; ("-linear", Stdlib.Arg.Set linear, "Actions which are used are consummed.")
2830
]
2931

3032
let () =
3133
Stdlib.Arg.parse speclist anon_fun usage_msg;
3234
let lexbuf = Lexing.from_channel (Stdlib.open_in !input_file) in
3335
let mcs = constellation_file read lexbuf in
3436
let result =
35-
match exec ~showtrace:!showtrace mcs with
37+
match exec ~linear:!linear ~showtrace:!showtrace mcs with
3638
| Ok result -> result
3739
| Error e ->
3840
pp_err_effect e |> Out_channel.output_string Out_channel.stderr;

examples/mll.sg

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,18 @@ end
3939

4040
show-exec #ps1->vehicle #ps1->cuts.
4141

42-
'''
43-
FIXME : MLL incorrectness
42+
spec "a * b" =
43+
-1(g:X) -2(g:X) +3(g:X);
44+
@-3(g:X) ok.
45+
46+
linear = galaxy
47+
interaction = linear-exec #tested #test end
48+
expect = ok.
49+
end
4450

51+
'does not typecheck
52+
'vehicle :: "a * a" [linear].
4553
vehicle =
4654
+3(l:X) +3(r:X);
4755
-3(l:X) +1(g:X);
4856
-3(r:X) +2(g:X).
49-
50-
test =
51-
-1(g:X) -2(g:X) +3(g:X);
52-
@-3(g:X) 3(X).
53-
'''

nvim/syntax/stellogen.vim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
syn clear
22

3-
syn keyword sgKeyword show exec spec trace process end galaxy run interface
3+
syn keyword sgKeyword show exec spec linear trace process end galaxy run interface
44
syn match sgComment "\s*'[^'].*$"
55
syn match sgId "#\%(\l\|\d\)\w*"
66
syn match sgIdDef "\zs\%(\l\|\d\)\w*\ze\s*="

src/lsc/lsc_ast.ml

Lines changed: 143 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -315,20 +315,15 @@ let extract_intspace (mcs : marked_constellation) =
315315
Execution
316316
--------------------------------------- *)
317317

318+
type configuration = constellation * constellation
319+
318320
let unpolarized_star s = List.for_all ~f:(Fn.compose not is_polarised) s.content
319321

320322
let kill : constellation -> constellation = List.filter ~f:unpolarized_star
321323

322324
let clean : constellation -> constellation =
323325
List.filter ~f:(fun s -> List.is_empty s.content)
324326

325-
let selections l =
326-
let rec aux acc = function
327-
| [] -> []
328-
| h :: t -> (h, acc @ t) :: aux (acc @ [ h ]) t
329-
in
330-
aux [] l
331-
332327
let fusion repl1 repl2 s1 s2 bans1 bans2 theta : star =
333328
let new1 = List.map s1 ~f:repl1 in
334329
let new2 = List.map s2 ~f:repl2 in
@@ -360,133 +355,165 @@ let pause () =
360355
let _ = input_line stdin in
361356
()
362357

363-
let search_partners ?(showtrace = false) (r, other_rays, bans) candidates :
358+
(* interaction between one selected ray and one selected action *)
359+
let rec interaction ~showtrace ~queue repl1 repl2
360+
(selected_action, other_actions) (selected_ray, other_rays, bans) :
364361
(star list, err_effect) Result.t =
365-
if showtrace then begin
366-
output_string stdout
367-
@@ Printf.sprintf "select state: >>%s<< %s" (string_of_ray r)
368-
(string_of_raylist other_rays);
369-
pause ()
370-
end;
371-
let rec select_ray ~queue other_stars repl1 repl2 s :
372-
(star list, err_effect) Result.t =
373-
match s.content with
374-
| [] -> Ok []
375-
| r' :: s' when not (is_polarised r') ->
376-
select_ray ~queue:(r' :: queue) other_stars repl1 repl2
377-
{ content = s'; bans }
378-
| r' :: s' -> (
379-
if showtrace then begin
380-
output_string stdout
381-
@@ Printf.sprintf " try action: >>%s<< %s...\n" (string_of_ray r')
382-
(string_of_raylist s')
362+
match selected_action.content with
363+
| [] -> Ok []
364+
| r' :: s' when not (is_polarised r') ->
365+
interaction ~showtrace ~queue:(r' :: queue) repl1 repl2
366+
({ content = s'; bans }, other_actions)
367+
(selected_ray, other_rays, bans)
368+
| r' :: s' -> (
369+
if showtrace then begin
370+
output_string stdout
371+
@@ Printf.sprintf " try action: >>%s<< %s...\n" (string_of_ray r')
372+
(string_of_raylist s')
373+
end;
374+
match raymatcher (repl1 selected_ray) (repl2 r') with
375+
| None ->
376+
if showtrace then output_string stdout "failed.";
377+
interaction ~showtrace ~queue:(r' :: queue) repl1 repl2
378+
({ content = s'; bans }, other_actions)
379+
(selected_ray, other_rays, bans)
380+
(* if there is an actual connection between rays *)
381+
| Some theta ->
382+
let* _ = apply_effect selected_ray theta in
383+
begin
384+
if showtrace then
385+
output_string stdout
386+
@@ Printf.sprintf "success with %s." (string_of_subst theta);
387+
if showtrace then pause ()
383388
end;
389+
(* action is consumed when execution is linear *)
384390
let* next =
385-
select_ray ~queue:(r' :: queue) other_stars repl1 repl2
386-
{ content = s'; bans }
391+
interaction ~showtrace ~queue:(r' :: queue) repl1 repl2
392+
({ content = s'; bans }, other_actions)
393+
(selected_ray, other_rays, bans)
394+
in
395+
let other_rays' = queue @ s' in
396+
let after_fusion =
397+
fusion repl1 repl2 other_rays other_rays' bans selected_action.bans
398+
theta
399+
in
400+
let all_coherent =
401+
List.for_all ~f:(fun (b1, b2) -> not @@ equal_ray b1 b2)
387402
in
388-
match raymatcher (repl1 r) (repl2 r') with
389-
| None ->
390-
if showtrace then output_string stdout "failed.";
391-
Ok next
392-
(* if there is an actual connection between rays *)
393-
| Some theta ->
394-
let* _ = apply_effect r theta in
395-
let* _ =
403+
let* res =
404+
if all_coherent after_fusion.bans then begin
405+
let _ =
406+
if showtrace then
407+
output_string stdout
408+
@@ Printf.sprintf " add star %s." (string_of_star after_fusion)
409+
in
410+
Ok (after_fusion :: next)
411+
end
412+
else begin
396413
if showtrace then
397414
output_string stdout
398-
@@ Printf.sprintf "success with %s." (string_of_subst theta);
399-
Ok ()
400-
in
401-
let* _ =
402-
if showtrace then pause ();
403-
Ok ()
404-
in
405-
let other_rays' = queue @ s' in
406-
let after_fusion =
407-
fusion repl1 repl2 other_rays other_rays' bans s.bans theta
408-
in
409-
let all_coherent =
410-
List.for_all ~f:(fun (b1, b2) -> not @@ equal_ray b1 b2)
411-
in
412-
let* res =
413-
if all_coherent after_fusion.bans then begin
414-
let _ =
415-
if showtrace then
416-
output_string stdout
417-
@@ Printf.sprintf " add star %s." (string_of_star after_fusion)
418-
in
419-
Ok (after_fusion :: next)
420-
end
421-
else begin
422-
let _ =
423-
if showtrace then
424-
output_string stdout
425-
@@ Printf.sprintf " result filtered out by constraint."
426-
in
427-
Ok next
428-
end
429-
in
430-
if showtrace then pause ();
431-
ident_counter := !ident_counter + 2;
432-
Ok res )
433-
in
415+
@@ Printf.sprintf " result filtered out by constraint.";
416+
Ok next
417+
end
418+
in
419+
if showtrace then pause ();
420+
ident_counter := !ident_counter + 2;
421+
Ok res )
422+
423+
(* search partner for a selected ray within a set of available actions *)
424+
let search_partners ~linear ~showtrace (selected_ray, other_rays, bans) actions
425+
: (star list * star list, err_effect) Result.t =
426+
if showtrace then begin
427+
let str_ray = string_of_ray selected_ray in
428+
let str_rays = string_of_raylist other_rays in
429+
Printf.sprintf "select state: >>%s<< %s" str_ray str_rays
430+
|> output_string stdout;
431+
pause ()
432+
end;
434433
let repl1 = replace_indices !ident_counter in
435-
List.map (selections candidates) ~f:(fun (s, cs) ->
436-
let repl2 = replace_indices (!ident_counter + 1) in
437-
select_ray ~queue:[] cs repl1 repl2 s )
438-
|> Result.all
439-
|> function
440-
| Ok l -> Ok (List.concat l)
441-
| Error e -> Error e
442-
443-
let interaction ?(showtrace = false) (actions : star list) (states : star list)
444-
: (constellation option, err_effect) Result.t =
445-
let rec select_ray states' ~queue s ~bans =
446-
match s with
447-
| [] -> Ok None
448-
| r :: rs when not (is_polarised r) ->
449-
select_ray states' ~queue:(r :: queue) rs ~bans
450-
| r :: rs -> begin
451-
match search_partners ~showtrace (r, queue @ rs, bans) actions with
452-
| Ok [] -> select_ray states' ~queue:(r :: queue) rs ~bans
453-
| Ok new_stars -> Ok (Some new_stars)
454-
| Error e -> Error e
455-
end
456-
in
457-
let rec select_star ~queue = function
458-
| [] -> Ok None
459-
| s :: states' -> begin
460-
match select_ray states' ~queue:[] s.content ~bans:s.bans with
461-
| Ok None -> select_star ~queue:(s :: queue) states'
462-
| Ok (Some new_stars) -> Ok (Some (List.rev queue @ states' @ new_stars))
463-
| Error e -> Error e
464-
end
434+
let rec try_actions acc = function
435+
| [] -> Ok ([], acc)
436+
| selected_action :: other_actions ->
437+
let repl2 = replace_indices (!ident_counter + 1) in
438+
let* res =
439+
interaction ~showtrace ~queue:[] repl1 repl2
440+
(selected_action, other_actions)
441+
(selected_ray, other_rays, bans)
442+
in
443+
if (not @@ List.is_empty res) && linear then
444+
let* next, new_actions = try_actions acc other_actions in
445+
Ok (res @ next, new_actions)
446+
else
447+
let* next, new_actions =
448+
try_actions (selected_action :: acc) other_actions
449+
in
450+
Ok (res @ next, new_actions)
465451
in
466-
select_star ~queue:[] states
467-
468-
let string_of_configuration (actions, states) : string =
452+
try_actions [] actions
453+
454+
let rec select_ray ~linear ~showtrace ~queue actions other_states
455+
(selected_state, bans) : (star list option * star list, err_effect) Result.t =
456+
match selected_state with
457+
| [] -> Ok (None, actions)
458+
(* if unpolarized, no need to try, try other stars *)
459+
| r :: rs when not (is_polarised r) ->
460+
select_ray ~linear ~showtrace ~queue:(r :: queue) actions other_states
461+
(rs, bans)
462+
| selected_ray :: other_rays -> (
463+
(* look for partners for the selected rays in actions *)
464+
match
465+
search_partners ~linear ~showtrace
466+
(selected_ray, queue @ other_rays, bans)
467+
actions
468+
with
469+
(* interaction did nothing (no partner), try other rays *)
470+
| Ok ([], new_actions) ->
471+
select_ray ~linear ~showtrace ~queue:(selected_ray :: queue) new_actions
472+
other_states (other_rays, bans)
473+
(* interaction returns a result, keep it for the next round *)
474+
| Ok (new_stars, new_actions) -> Ok (Some new_stars, new_actions)
475+
| Error e -> Error e )
476+
477+
let rec select_star ~linear ~showtrace ~queue actions :
478+
star list -> (star list option * star list, err_effect) Result.t = function
479+
| [] -> Ok (None, actions)
480+
(* select a state star and try finding a partner for each ray *)
481+
| selected_state :: other_states -> (
482+
match
483+
select_ray ~linear ~showtrace ~queue:[] actions other_states
484+
(selected_state.content, selected_state.bans)
485+
with
486+
(* no success with this star, try other stars *)
487+
| Ok (None, new_actions) ->
488+
select_star ~linear ~showtrace new_actions
489+
~queue:(selected_state :: queue) other_states
490+
(* got new stars to add, construct the result for the next round *)
491+
| Ok (Some new_stars, new_actions) ->
492+
Ok (Some (List.rev queue @ other_states @ new_stars), new_actions)
493+
| Error e -> Error e )
494+
495+
let string_of_cfg (actions, states) : string =
469496
Printf.sprintf ">> actions: %s\n>> states: %s\n"
470497
(string_of_constellation actions)
471498
(string_of_constellation states)
472499

473-
let exec ?(showtrace = false) mcs : (constellation, err_effect) Result.t =
474-
let rec aux (actions, states) =
500+
let exec ?(showtrace = false) ?(linear = false) mcs :
501+
(constellation, err_effect) Result.t =
502+
(* do a sequence of rounds with a single interaction on state per round *)
503+
let rec loop ((actions, states) as cfg) =
475504
if showtrace then begin
476-
output_string stdout @@ string_of_configuration (actions, states);
505+
output_string stdout @@ string_of_cfg cfg;
477506
pause ()
478507
end;
479-
begin
480-
match interaction ~showtrace actions states with
481-
| Ok None -> Ok states
482-
| Ok (Some result') -> aux (actions, result')
483-
| Error e -> Error e
484-
end
508+
match select_star ~linear ~showtrace ~queue:[] actions states with
509+
| Ok (None, _) -> Ok states (* no more possible interaction *)
510+
| Ok (Some res, new_actions) -> loop (new_actions, res)
511+
| Error e -> Error e
485512
in
486-
let actions, states = extract_intspace mcs in
513+
let cfg = extract_intspace mcs in
487514
if showtrace then
488515
output_string stdout @@ Printf.sprintf "\n>> starting trace...\n";
489-
let res = aux (actions, states) in
516+
let res = loop cfg in
490517
if showtrace then begin
491518
output_string stdout @@ Printf.sprintf ">> end trace.\n";
492519
pause ()

src/stellogen/sgen_ast.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ and galaxy_expr =
2727
| Access of galaxy_expr * ident
2828
| Id of ident
2929
| Exec of galaxy_expr
30+
| LinExec of galaxy_expr
3031
| Union of galaxy_expr * galaxy_expr
3132
| Subst of galaxy_expr * substitution
3233
| Focus of galaxy_expr

0 commit comments

Comments
 (0)