1 /* 2 * The MIT License (MIT) 3 * 4 * Copyright (c) 2014 Richard Andrew Cattermole 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to deal 8 * in the Software without restriction, including without limitation the rights 9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 * copies of the Software, and to permit persons to whom the Software is 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in all 14 * copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 * SOFTWARE. 23 */ 24 module dakka.base.impl.wrap; 25 import dakka.base.impl.defs; 26 import dakka.base.defs; 27 import std.traits : hasMember, ReturnType, ParameterIdentifierTuple; 28 29 pure string getActorWrapImpl(T : Actor)(T t = T.init) { 30 string ret; 31 32 foreach(m; __traits(allMembers, T)) { 33 static if (__traits(getProtection, __traits(getMember, t, m)) == "public" && !hasMember!(Actor, m)) { 34 static if (__traits(isVirtualFunction, __traits(getMember, t, m))) { 35 static if (!isMethodLocalOnly!(T, m)) { 36 ret ~= funcDeclText!(T, m)(!is(ReturnType!(mixin("t." ~ m)) == void)); 37 38 switch(getCallUDA!(T, m).strategy) { 39 case DakkaCallStrategy.Until: 40 untilWrapStrategy!(T, m)(ret); 41 break; 42 43 case DakkaCallStrategy.Sequentially: 44 default: 45 sequentialWrapStrategy!(T, m)(ret); 46 break; 47 } 48 49 ret ~= " }\n"; 50 } 51 } 52 } 53 } 54 55 return ret; 56 } 57 58 pure DakkaCall_ getCallUDA(T : Actor, string m)() { 59 enum T t = T.init; 60 foreach(UDA; __traits(getAttributes, mixin("t." ~ m))) { 61 if (typeText!(typeof(UDA)) == typeText!DakkaCall_) { 62 return UDA; 63 } 64 } 65 66 return DakkaCall(DakkaCallStrategy.Sequentially); 67 } 68 69 pure void sequentialWrapStrategy(T, string m)(ref string ret) { 70 enum uda = getCallUDA!(T, m); 71 enum T t = T.init; 72 73 string names; 74 foreach(name; ParameterIdentifierTuple!(mixin("t." ~ m))) { 75 names ~= name ~ ", "; 76 } 77 if (names.length > 0) 78 names.length -= 2; 79 80 if (is(ReturnType!(mixin("t." ~ m)) == void)) { 81 ret ~= (""" 82 checkForUpdatesToAddresses(); 83 84 localRef." ~ m ~ "(" ~ names ~ "); 85 foreach(actor; remoteRefs.values) { 86 actor." ~ m ~ "(" ~ names ~ "); 87 } 88 """)[1 .. $]; 89 } else { 90 ret ~= (""" 91 checkForUpdatesToAddresses(); 92 " ~ typeText!(ReturnType!(mixin("t." ~ m))) ~ "[] ret; 93 94 ret ~= localRef." ~ m ~ "(" ~ names ~ "); 95 foreach(actor; remoteRefs.values) { 96 ret ~= actor." ~ m ~ "(" ~ names ~ "); 97 } 98 return ret; 99 """)[1 .. $]; 100 } 101 } 102 103 pure void untilWrapStrategy(T, string m)(ref string ret) { 104 enum uda = getCallUDA!(T, m); 105 enum T t = T.init; 106 import std.conv : to; 107 108 string names; 109 foreach(name; ParameterIdentifierTuple!(mixin("t." ~ m))) { 110 names ~= name ~ ", "; 111 } 112 if (names.length > 0) 113 names.length -= 2; 114 115 ret ~= (""" 116 checkForUpdatesToAddresses(); 117 " ~ typeText!(ReturnType!(mixin("t." ~ m))) ~ "[] ret; 118 119 " ~ typeText!(ReturnType!(mixin("t." ~ m))) ~ " vcmp = Decerealizer(" ~ to!string(uda.data) ~ ").value!(" ~ typeText!(ReturnType!(mixin("t." ~ m))) ~ "); 120 121 ret ~= localRef." ~ m ~ "(" ~ names ~ "); 122 if (ret[0] == vcmp) 123 return ret; 124 125 foreach(actor; remoteRefs.values) { 126 " ~ typeText!(ReturnType!(mixin("t." ~ m))) ~ " v = actor." ~ m ~ "(" ~ names ~ "); 127 ret ~= v; 128 if (v == vcmp) 129 break; 130 } 131 return ret; 132 """)[1 .. $]; 133 }