AlignmentCli.bend

bend-edit-distance@0.1.0.0 · 93 lines · 0 definitions

1import Base
2import bend-edit-distance@0.1.0.0/Cli.bend as CLI
3import bend-edit-distance@0.1.0.0/EdlibTypes.bend as E
4
5def read_mode(value: String) -> Maybe<&2, E.Mode>:
6  match value:
7    case "NW":
8      Some{E.NW{}}
9    case "SHW":
10      Some{E.SHW{}}
11    case "HW":
12      Some{E.HW{}}
13    case _:
14      None{}
15
16def read_task(value: String) -> Maybe<&2, E.Task>:
17  match value:
18    case "DISTANCE":
19      Some{E.Distance{}}
20    case "LOC":
21      Some{E.Locations{}}
22    case "PATH":
23      Some{E.Path{}}
24    case _:
25      None{}
26
27def read_format(value: String) -> Maybe<&2, E.CigarFormat>:
28  match value:
29    case "STANDARD":
30      Some{E.Standard{}}
31    case "EXTENDED":
32      Some{E.Extended{}}
33    case _:
34      None{}
35
36def bounded_threshold(value: Nat, valid: Bool) -> Maybe<&2, E.Threshold>:
37  match valid:
38    case True{}:
39      Some{E.MaxDistance{value}}
40    case False{}:
41      None{}
42
43def read_threshold(value: String) -> Maybe<&2, E.Threshold>:
44  match value:
45    case "-1":
46      Some{E.Unlimited{}}
47    case _:
48      do Maybe<&2, E.Threshold>:
49        +maximum : Nat <- Nat.read(value)
50        bounded_threshold(maximum, Nat.is_le(maximum, 2147483647n))
51
52def read_pairs(value: String) -> Maybe<&2, List<&2, E.EqualityPair>>:
53  match value:
54    case SNil{}:
55      Some{Nil{}}
56    case SCon{_, SNil{}}:
57      None{}
58    case SCon{first, SCon{second, tail}}:
59      do Maybe<&2, List<&2, E.EqualityPair>>:
60        pairs : List<&2, E.EqualityPair> <- read_pairs(tail)
61        return E.EqualityPair{first, second} <> pairs
62
63def parse(mode: String, task: String, threshold: String, pairs: String,
64          format: String) -> Maybe<&2, E.AlignConfig>:
65  do Maybe<&2, E.AlignConfig>:
66    m : E.Mode <- read_mode(mode)
67    t : E.Task <- read_task(task)
68    k : E.Threshold <- read_threshold(threshold)
69    eq : List<&2, E.EqualityPair> <- read_pairs(pairs)
70    c : E.CigarFormat <- read_format(format)
71    return E.AlignConfig{m, t, k, eq, c}
72
73def respond(~align: String -> String -> E.AlignConfig -> E.AlignResult,
74            query: String, target: String, config: Maybe<&2, E.AlignConfig>,
75            status: CLI.InputStatus) -> IO(Unit):
76  match config status:
77    case None{} _:
78      IO.die(Unit, 2, "Invalid alignment configuration")
79    case Some{value} CLI.Supported{}:
80      IO.print(E.result_show(align(query, target, value)))
81    case _ CLI.NonAscii{}:
82      IO.die(Unit, 2, "Sequences and equality pairs must contain only non-NUL ASCII characters")
83    case _ CLI.TooLong{}:
84      IO.die(Unit, 2, "Sequence or equality-pair length exceeds maximum of 4096 ASCII characters")
85
86def run(~align: String -> String -> E.AlignConfig -> E.AlignResult,
87        args: List<String>) -> IO(Unit):
88  match args:
89    case _ <> "--config" <> mode <> task <> threshold <> +pairs <> format <> +query <> +target <> Nil{}:
90      respond(~align, query, target, parse(mode, task, threshold, pairs, format),
91        CLI.combine(CLI.validate(query, target), CLI.scan(pairs, CLI.max_sequence_length())))
92    case _:
93      IO.die(Unit, 2, "Expected QUERY TARGET or --config MODE TASK K PAIRS CIGAR QUERY TARGET")