1 module glued.annotations.common_impl;
2 
3 import std.traits;
4 
5 import glued.utils;
6 
7 enum TargetType {
8     MODULE = 1 << 31, //non-target ; 31 is max value when using <<
9     FUNCTION = 1<<0,
10     VARIABLE = 1<<1,
11     INTERFACE = 1<<2,
12     CLASS = 1<<3,
13     STRUCT = 1<<4,
14     ENUM = 1<<5,
15     //todo consider making annotations, templates, unittests targets as well; introduce RAW_STRUCT and friends, TEMPLATE, and then STRUCT = RAW_STRUCT | TEMPLATE
16     
17     CODE = (FUNCTION | VARIABLE),
18     
19     DATA = (STRUCT | ENUM),
20     POINTER = (INTERFACE | CLASS),
21     TYPE = (DATA | POINTER),
22     
23     ANY = (CODE | TYPE)
24 }
25 
26 bool TargetChecker(alias target, alias annotation, alias constraint)(){
27     return constraint.canAnnotate(TargetTypeOf!(target));
28 }
29 
30 bool TargetOwnerChecker(alias target, alias annotation, alias constraint)(){
31     return constraint.canAnnotate(TargetTypeOf!(__traits(parent, target)));
32 }
33 
34 template TargetTypeOf(T...) if (T.length == 1) {
35     static if (is(T[0])) {
36         static if (is(T[0] == class)){
37             enum TargetTypeOf = TargetType.CLASS;
38         } 
39         else
40         static if (is(T[0] == interface)){
41             enum TargetTypeOf = TargetType.INTERFACE;
42         }
43         else
44         static if (is(T[0] == struct)){
45             enum TargetTypeOf = TargetType.STRUCT;
46         }
47         static if (is(T[0] == enum)){
48             enum TargetTypeOf = TargetType.ENUM;
49         }
50     } else {
51         static if (isFunction!(T[0]))
52         {
53             enum TargetTypeOf = TargetType.FUNCTION;
54         }
55         else
56         {
57             static if (__traits(compiles, typeof(T[0])))
58             {
59                 enum TargetTypeOf = TargetType.VARIABLE;
60             }
61             else 
62             {
63                 enum TargetTypeOf = TargetType.MODULE;
64             }
65         }
66     }
67 }
68 
69 bool RepeatableChecker(alias target, alias annotation, alias constraint)(){
70     import glued.annotations.core_impl: getUncheckedAnnotations;
71     import std.meta: Filter;
72     
73     immutable occurences = Filter!(ofType!(toType!(annotation)), getUncheckedAnnotations!(target)).length; 
74     return constraint.boundaries.check(occurences);
75 }