aboutsummaryrefslogtreecommitdiffziptar.gz
path: root/src/Godosa.Core/Runs/Scripts/ScriptRunFlags.cs
blob: 63a335aadee8090dc8c35d8e368c56ba16a5511a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
// Provenance: own design — shared run scripts (CLI)
using System.Globalization;

namespace Godosa.Core.Runs.Scripts;

/// <summary>Run-script CLI options (<c>--script</c>, <c>--var k=v</c>, <c>--output</c>, <c>--no-cache</c>, <c>--no-snapshots</c>, <c>--from</c>,
/// <c>--until</c>, <c>--nondeterministic</c>, <c>--step-cap</c>, <c>--report-dir</c>); determinism and seed come from
/// <see cref="RunFlags"/>.</summary>
public sealed class ScriptRunFlags
{
    public string? Script { get; set; }
    public Dictionary<string, string> Vars { get; } = new(StringComparer.Ordinal);
    public OutputLevel? Output { get; set; }
    public bool NoCache { get; set; }
    public bool NoSnapshots { get; set; }
    public string? From { get; set; }
    public string? Until { get; set; }
    public bool NonDeterministic { get; set; }
    public int? StepCap { get; set; }
    public string? ReportDir { get; set; }

    public static bool TryTake(string[] args, ref int i, ScriptRunFlags flags)
    {
        string Value(ref int j)
        {
            if (j + 1 >= args.Length)
                throw new ArgumentException($"{args[j]} needs a value");
            return args[++j];
        }
        switch (args[i])
        {
            case "--script":
                flags.Script = Value(ref i);
                return true;
            case "--var":
            {
                var v = Value(ref i);
                var eq = v.IndexOf('=');
                if (eq <= 0)
                    throw new ArgumentException($"--var needs name=value, got '{v}'");
                flags.Vars[v[..eq]] = v[(eq + 1)..];
                return true;
            }
            case "--output":
            {
                var v = Value(ref i);
                try
                {
                    flags.Output = RunOutput.Parse(v);
                }
                catch (ScriptFault e)
                {
                    throw new ArgumentException(e.Message);
                }
                return true;
            }
            case "--no-cache":
                flags.NoCache = true;
                return true;
            case "--no-snapshots":
                flags.NoSnapshots = true;
                return true;
            case "--from":
                flags.From = Value(ref i);
                return true;
            case "--until":
                flags.Until = Value(ref i);
                return true;
            case "--nondeterministic":
                flags.NonDeterministic = true;
                return true;
            case "--step-cap":
            {
                var v = Value(ref i);
                flags.StepCap = int.TryParse(v, CultureInfo.InvariantCulture, out var n) && n > 0 ? n : throw new ArgumentException($"bad --step-cap '{v}'");
                return true;
            }
            case "--report-dir":
                flags.ReportDir = Value(ref i);
                return true;
            default:
                return false;
        }
    }

    public ScriptRunOptions ToOptions(RunFlags run, string? cacheDir) => new()
    {
        Deterministic = !NonDeterministic,
        Seed = run.Seed,
        Output = Output ?? OutputLevel.Labels,
        Floor = Output ?? OutputLevel.Quiet,
        StepCap = StepCap ?? 36_000,
        CacheDir = cacheDir,
        UseCache = !NoCache,
        Snapshots = !NoSnapshots,
        From = From,
        Until = Until,
        ReportDir = ReportDir,
    };
}