1 module dnv.typechecker;
2 
3 import std.string : format, split;
4 import std.meta;
5 import std.traits;
6 
7 
8 struct Param(string args) {
9   mixin("private void _fun_(" ~ args ~ ") {}");
10   alias Args = AliasSeq!(Parameters!(_fun_));
11 }
12 
13 
14 bool predicate(alias trait, string kargs, Args ...)(Args args) {
15   return trait!(kargs, Args);
16 }
17 
18 void staticAssert(alias trait, string kargs, Args ...)(Args args) {
19   static assert(trait!(kargs, Args),
20                 "\nleft  args:(%s)\nright args:%s\nthis right args violate the <%s> trait"
21                 .format(kargs, Args.stringof, trait.stringof.split("(")[0]));
22 }
23 
24 
25 enum bool EqualArgTypes(string kargs, Args ...) = is(Param!kargs.Args == AliasSeq!Args);
26 
27 unittest {
28   immutable OK = q{int i, float* f, const(char)* c};
29   immutable NG = q{float i, float* f, const(char)* c};
30 
31   int i = 0;
32   float[] f = [1f, 2f];
33   const char[] c = ['a'];
34 
35   assert(predicate!(EqualArgTypes, OK)(i, f.ptr, c.ptr));
36   assert(!predicate!(EqualArgTypes, NG)(i, f.ptr, c.ptr));
37 
38   staticAssert!(EqualArgTypes, OK)(i, f.ptr, c.ptr);
39   // staticAssert!(EqualArgTypes, NG)(i, f.ptr, c.ptr);
40   static assert(!__traits(compiles, staticAssert!(EqualArgTypes, NG)(i, f.ptr, c.ptr)));
41 }
42 
43 enum bool isCudaAssignable(L, R) = function() {
44   static if (is(typeof({R.Storage s = null;}))) {
45     return isAssignable!(L, R.Storage);
46   } else {
47     return isAssignable!(L, R);
48   }
49 }();
50 
51 enum bool AssignableArgTypes(string kargs, Args ...) = function() {
52   alias KArgs = Param!kargs.Args;
53   if (KArgs.length != Args.length) {
54     return false;
55   }
56   
57   bool ok = true;
58   foreach (i, _; Args) {
59     ok &= isCudaAssignable!(KArgs[i], Args[i]);
60     if (!ok) {
61       return false;
62     }
63   }
64   return true;
65 }();
66 
67 unittest {
68   int i = 0;
69   float[] f = [1f, 2f];
70   const char[] c = ['a'];
71   immutable OK = q{int i, float* f, const(char)* c};
72   immutable NG = q{int i, float* f, char* c};
73 
74   assert(predicate!(AssignableArgTypes, OK)(i, f.ptr, c.ptr));
75   assert(!predicate!(AssignableArgTypes, NG)(i, f.ptr, c.ptr));
76 
77   staticAssert!(AssignableArgTypes, OK)(i, f.ptr, c.ptr);
78   // staticAssert!(AssignableArgTypes, NG)(i, f.ptr, c.ptr);
79   static assert(!__traits(compiles, staticAssert!(AssignableArgTypes, NG)(i, f.ptr, c.ptr)));
80 }
81 
82 unittest {
83   import dnv.storage;
84   import dnv.compiler;
85   static assert(isCudaAssignable!(float*, Array!float));
86 }