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 }