1 module dud.resolve.versionconfigurationtoolchain;
2 
3 import std.algorithm.iteration : map;
4 import std.array : array, empty;
5 import std.stdio;
6 import std.exception : enforce;
7 import std.array : empty;
8 import std.format : format;
9 import dud.semver.semver;
10 import dud.semver.parse;
11 import dud.semver.checks : allowsAll, allowsAny;
12 import dud.semver.versionrange;
13 import dud.semver.versionunion;
14 static import dud.semver.setoperation;
15 import dud.resolve.confs : Confs;
16 import dud.resolve.positive;
17 import dud.resolve.toolchain;
18 
19 @safe pure:
20 
21 /** The algebraic datatype that stores a version range and a configuration
22 */
23 struct VersionConfigurationToolchain {
24 @safe pure:
25 	VersionUnion ver;
26 	Confs conf;
27 	ToolchainVersionUnion[] toolchains;
28 }
29 
30 VersionConfigurationToolchain dup(const(VersionConfigurationToolchain) old) {
31 	return VersionConfigurationToolchain(old.ver.dup(), old.conf.dup()
32 			, old.toolchains.map!(it => dud.resolve.toolchain.dup(it)).array);
33 }
34 
35 VersionConfigurationToolchain invert(const(VersionConfigurationToolchain) conf) {
36 	static import dud.resolve.confs;
37 	return VersionConfigurationToolchain(
38 			dud.semver.setoperation.invert(conf.ver)
39 			, conf.conf.invert());
40 }
41 
42 bool allowsAny(const(VersionConfigurationToolchain) a, const(VersionConfigurationToolchain) b) {
43 	static import dud.resolve.confs;
44 	static import dud.semver.checks;
45 	return dud.semver.checks.allowsAny(a.ver, b.ver)
46 		&& dud.resolve.confs.allowsAny(a.conf, b.conf)
47 		&& dud.resolve.toolchain.allowsAny(a.toolchains, b.toolchains);
48 }
49 
50 bool allowsAll(const(VersionConfigurationToolchain) a, const(VersionConfigurationToolchain) b) {
51 	static import dud.resolve.confs;
52 	static import dud.semver.checks;
53 	return dud.semver.checks.allowsAll(a.ver, b.ver)
54 		&& dud.resolve.confs.allowsAll(a.conf, b.conf)
55 		&& dud.resolve.toolchain.allowsAll(a.toolchains, b.toolchains);
56 }
57 
58 VersionConfigurationToolchain intersectionOf(const(VersionConfigurationToolchain) a,
59 		const(VersionConfigurationToolchain) b)
60 {
61 	static import dud.resolve.confs;
62 	static import dud.semver.setoperation;
63 	return VersionConfigurationToolchain(
64 			dud.semver.setoperation.intersectionOf(a.ver, b.ver)
65 			, dud.resolve.confs.intersectionOf(a.conf, b.conf)
66 			, dud.resolve.toolchain.intersectionOf(a.toolchains, b.toolchains));
67 }
68 
69 /** Return if a is a subset of b, or if a and b are disjoint, or
70 if a and b overlap
71 */
72 SetRelation relation(const(VersionConfigurationToolchain) a,
73 		const(VersionConfigurationToolchain) b) pure
74 {
75 	static import dud.resolve.confs;
76 	const SetRelation ver = allowsAll(b.ver, a.ver)
77 		? SetRelation.subset
78 		: allowsAny(b.ver, a.ver)
79 			? SetRelation.overlapping
80 			: SetRelation.disjoint;
81 
82 	const SetRelation conf = dud.resolve.confs.relation(a.conf, b.conf);
83 	const SetRelation tc = dud.resolve.toolchain.relation(a.toolchains,
84 			b.toolchains);
85 	debug writefln("ver %s, conf %s, tc %s", ver, conf, tc);
86 
87 	//debug writefln("ver %s, conf %s", ver, conf);
88 	if(ver == SetRelation.disjoint || conf == SetRelation.disjoint) {
89 		return SetRelation.disjoint;
90 	}
91 
92 	if(ver == SetRelation.overlapping || conf == SetRelation.overlapping) {
93 		return SetRelation.overlapping;
94 	}
95 
96 	assert(ver == SetRelation.subset && conf == SetRelation.subset,
97 			format("a: %s, b: %s", a, b));
98 	return SetRelation.subset;
99 }