Changeset 238
- Timestamp:
- 11/17/07 12:31:58 (1 year ago)
- Files:
-
- trunk/docs/candydoc/modules.ddoc (modified) (1 diff)
- trunk/docs/minid.bind.html (modified) (7 diffs)
- trunk/minid/bind.d (modified) (16 diffs)
- trunk/minid/utils.d (modified) (1 diff)
- trunk/test.d (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/docs/candydoc/modules.ddoc
r230 r238 1 1 MODULES = 2 $(MODULE_FULL minid.minid)3 2 $(MODULE_FULL minid.bind) 4 $(MODULE_FULL minid.types)5 $(MODULE_FULL minid.compiler)6 $(MODULE_FULL minid.utils)trunk/docs/minid.bind.html
r232 r238 45 45 <dl> 46 46 <script>explorer.outline.writeEnabled = true;</script> 47 <dt><span class="decl"> void47 <dt><span class="decl">struct 48 48 <span class="currsymbol">WrapModule</span> 49 49 <script>explorer.outline.addDecl('WrapModule');</script> 50 50 51 (dchar[] name,Members...)(MDContext <span class="funcparam">context</span>); 52 </span></dt> 53 <script>explorer.outline.writeEnabled = false;</script> 54 55 56 <dd>Creates a module with the given name and members. 57 <br><br> 58 59 </dd> 60 61 <script>explorer.outline.writeEnabled = true;</script> 62 <dt><span class="decl">struct 51 ; 52 </span></dt> 53 <script>explorer.outline.writeEnabled = false;</script> 54 55 56 <dd>Used to wrap a module that is exposed to MiniD. A module can contain any number of functions, classes, structs, 57 and other values. They are added to the module using this struct's methods. 58 <br><br> 59 <b>Examples:</b><br> 60 <pre class="d_code"><u>WrapModule</u>(<font color=red>"foo.bar"</font>, myContext) <font color=green>// name it foo.bar, load it into myContext 61 </font> .func!(funcOne)() <font color=green>// wrap native function funcOne; the empty parens here are necessary 62 </font> .func!(funcTwo)() 63 .custom(<font color=red>"x"</font>, 6)() <font color=green>// set member "x" to the value 6. This can be any convertible type. 64 </font> .type(WrapClass!(MyClass) <font color=green>// wrap the native class MyClass. 65 </font> .method!(MyClass.method)() <font color=green>// A method. Again, the empty parens are necessary. 66 </font> .property!(MyClass.property)()); <font color=green>// a property 67 </font></pre> 68 <br><br> 69 70 71 <script>explorer.outline.incSymbolLevel();</script> 72 <dl> 73 <script>explorer.outline.writeEnabled = true;</script> 74 <dt><span class="decl">static WrapModule 75 <span class="currsymbol">opCall</span> 76 <script>explorer.outline.addDecl('opCall');</script> 77 78 (char[] <span class="funcparam">name</span>, MDContext <span class="funcparam">context</span>); 79 </span></dt> 80 <script>explorer.outline.writeEnabled = false;</script> 81 82 83 <dd>Creates an instance of this struct so you can start wrapping a module. 84 <br><br> 85 <b>Params:</b><br> 86 <table><tr> 87 <td nowrap valign="top" style="padding-right: 8px">char[] <span class="funcparam">name</span></td> 88 89 90 <td>The <span class="funcparam">name</span> of the module to expose to MiniD. This can be a multi-part <span class="funcparam">name</span>, with dots (like "foo.bar").</td></tr> 91 <tr> 92 <td nowrap valign="top" style="padding-right: 8px">MDContext <span class="funcparam">context</span></td> 93 94 95 <td>The MiniD <span class="funcparam">context</span> to load this module into.</td></tr> 96 </table><br> 97 <b>Returns:</b><br> 98 An instance of this struct ready to have members added. 99 100 <br><br> 101 102 </dd> 103 104 <script>explorer.outline.writeEnabled = true;</script> 105 <dt><span class="decl">typeof(this) 106 <span class="currsymbol">func</span> 107 <script>explorer.outline.addDecl('func');</script> 108 109 (alias f,char[] name = NameOfFunc!(f),funcType = typeof(f))(); 110 <br>typeof(this) 111 <span class="currsymbol"> 112 <span class="currsymbol">func</span> 113 <script>explorer.outline.addDecl('func');</script> 114 115 </span> 116 <script>explorer.outline.addDecl(' 117 <span class="currsymbol">func</span> 118 <script>explorer.outline.addDecl('func');</script> 119 120 ');</script> 121 122 (alias f,funcType)(); 123 </span></dt> 124 <script>explorer.outline.writeEnabled = false;</script> 125 126 127 <dd>Wrap a function and insert it into this module's namespace. This must be a non-member D function. 128 <br><br> 129 <b>Params:</b><br> 130 <table><tr> 131 <td nowrap valign="top" style="padding-right: 8px">f</td> 132 133 134 <td>An alias to the function you want to wrap.</td></tr> 135 <tr> 136 <td nowrap valign="top" style="padding-right: 8px">name</td> 137 138 139 <td>The name to call it in MiniD. Defaults to the D function name.</td></tr> 140 <tr> 141 <td nowrap valign="top" style="padding-right: 8px">funcType</td> 142 143 144 <td>The type of the function to wrap. This defaults to typeof(f), but you'll need to specify this 145 explicitly if you're wrapping an overloaded function, in order to select the proper overload.</td></tr> 146 </table><br> 147 <b>Returns:</b><br> 148 A chaining reference to this module. 149 150 <br><br> 151 152 </dd> 153 154 <script>explorer.outline.writeEnabled = true;</script> 155 <dt><span class="decl">typeof(this) 156 <span class="currsymbol">custom</span> 157 <script>explorer.outline.addDecl('custom');</script> 158 159 (T)(char[] <span class="funcparam">name</span>, T <span class="funcparam">value</span>); 160 </span></dt> 161 <script>explorer.outline.writeEnabled = false;</script> 162 163 164 <dd>Insert an arbitrary key-value pair into the module. The value can be any convertible type. 165 <br><br> 166 <b>Params:</b><br> 167 <table><tr> 168 <td nowrap valign="top" style="padding-right: 8px">name</td> 169 170 171 <td>The name to give this value in the module.</td></tr> 172 <tr> 173 <td nowrap valign="top" style="padding-right: 8px">value</td> 174 175 176 <td>The value to insert.</td></tr> 177 </table><br> 178 <b>Returns:</b><br> 179 A chaining reference to this module. 180 181 <br><br> 182 183 </dd> 184 185 <script>explorer.outline.writeEnabled = true;</script> 186 <dt><span class="decl">typeof(this) 187 <span class="currsymbol">type</span> 188 <script>explorer.outline.addDecl('type');</script> 189 190 (T)(T <span class="funcparam">value</span>, dchar[] <span class="funcparam">name</span> = ""); 191 </span></dt> 192 <script>explorer.outline.writeEnabled = false;</script> 193 194 195 <dd>Insert a wrapped class or struct 196 <span class="currsymbol">type</span> 197 <script>explorer.outline.addDecl('type');</script> 198 199 into the module. 200 <br><br> 201 <b>Params:</b><br> 202 <table><tr> 203 <td nowrap valign="top" style="padding-right: 8px">value</td> 204 205 206 <td>The wrapped class or struct 207 <span class="currsymbol">type</span> 208 <script>explorer.outline.addDecl('type');</script> 209 210 to insert. This should be an instance of the WrapClass struct, and should have 211 already had its members added to it.</td></tr> 212 <tr> 213 <td nowrap valign="top" style="padding-right: 8px">name</td> 214 215 216 <td>The name to give this 217 <span class="currsymbol">type</span> 218 <script>explorer.outline.addDecl('type');</script> 219 220 in the MiniD module. Defaults to "", which means it will use the D name of the 221 <span class="currsymbol">type</span> 222 <script>explorer.outline.addDecl('type');</script> 223 224 .</td></tr> 225 </table><br> 226 <b>Returns:</b><br> 227 A chaining reference to this module. 228 229 <br><br> 230 231 </dd> 232 </dl> 233 <script>explorer.outline.decSymbolLevel();</script> 234 235 236 </dd> 237 238 <script>explorer.outline.writeEnabled = true;</script> 239 <dt><span class="decl">void 63 240 <span class="currsymbol">WrapFunc</span> 64 241 <script>explorer.outline.addDecl('WrapFunc');</script> 65 242 66 (alias func,char[] name = NameOfFunc!(func),funcType = typeof(&func)) ;243 (alias func,char[] name = NameOfFunc!(func),funcType = typeof(&func))(MDNamespace <span class="funcparam">ns</span>); 67 244 <br>template 68 245 <span class="currsymbol">WrapFunc</span> … … 73 250 74 251 75 <dd>This wraps a function, and is meant to be used as a parameter to WrapModule. 76 <br><br> 77 78 79 <script>explorer.outline.incSymbolLevel();</script> 80 <dl></dl> 81 <script>explorer.outline.decSymbolLevel();</script> 82 252 <dd>Given a function alias, and an optional name and type for overloading, this will wrap the function and register 253 it in the global namespace. This is not meant to be used as a parameter to WrapModule, as it's not in any module. 254 <br><br> 83 255 84 256 </dd> … … 99 271 100 272 <dd>Given a function alias, and an optional name and type for overloading, this will wrap the function and register 101 <br><br>102 273 it in the global namespace. This is not meant to be used as a parameter to WrapModule, as it's not in any module. 103 274 <br><br> 104 105 </dd>106 107 <script>explorer.outline.writeEnabled = true;</script>108 <dt><span class="decl">struct109 <span class="currsymbol">WrapClass</span>110 <script>explorer.outline.addDecl('WrapClass');</script>111 112 (ClassType,char[] name = ClassType.stringof,Members...);113 </span></dt>114 <script>explorer.outline.writeEnabled = false;</script>115 116 117 <dd>Wraps a D class of the given type with the given members. name is the name that will be given to the class in MiniD.118 <br><br>119 120 121 <script>explorer.outline.incSymbolLevel();</script>122 <dl></dl>123 <script>explorer.outline.decSymbolLevel();</script>124 125 126 </dd>127 128 <script>explorer.outline.writeEnabled = true;</script>129 <dt><span class="decl">template130 <span class="currsymbol">WrapClassEx</span>131 <script>explorer.outline.addDecl('WrapClassEx');</script>132 133 (ClassType,Members...)</span></dt>134 <script>explorer.outline.writeEnabled = false;</script>135 136 137 <dd>Like WrapClass but lets you skip the name. This is named differently because otherwise there would be a naming conflict.138 <br><br>139 140 141 <script>explorer.outline.incSymbolLevel();</script>142 <dl></dl>143 <script>explorer.outline.decSymbolLevel();</script>144 145 146 </dd>147 148 <script>explorer.outline.writeEnabled = true;</script>149 <dt><span class="decl">void150 <span class="currsymbol">WrapGlobalClass</span>151 <script>explorer.outline.addDecl('WrapGlobalClass');</script>152 153 (ClassType,char[] name = ClassType.stringof,Members...)(MDContext <span class="funcparam">context</span>);154 </span></dt>155 <script>explorer.outline.writeEnabled = false;</script>156 157 158 <dd>Wrap a class and insert it into the global namespace.159 <br><br>160 161 </dd>162 163 <script>explorer.outline.writeEnabled = true;</script>164 <dt><span class="decl">template165 <span class="currsymbol">WrapGlobalClassEx</span>166 <script>explorer.outline.addDecl('WrapGlobalClassEx');</script>167 168 (ClassType,Members...)</span></dt>169 <script>explorer.outline.writeEnabled = false;</script>170 171 172 <dd>Like WrapGlobalClass but lets you skip the name. This is named differently because otherwise there would be a naming conflict.173 <br><br>174 175 176 <script>explorer.outline.incSymbolLevel();</script>177 <dl></dl>178 <script>explorer.outline.decSymbolLevel();</script>179 180 181 </dd>182 183 <script>explorer.outline.writeEnabled = true;</script>184 <dt><span class="decl">struct185 <span class="currsymbol">WrapMethod</span>186 <script>explorer.outline.addDecl('WrapMethod');</script>187 188 (alias func,char[] name = NameOfFunc!(func),funcType = typeof(&func));189 <br>template190 <span class="currsymbol">WrapMethod</span>191 <script>explorer.outline.addDecl('WrapMethod');</script>192 193 (alias func,funcType)</span></dt>194 <script>explorer.outline.writeEnabled = false;</script>195 196 197 <dd>Wrap a class method given an alias to the method (like A.foo). To be used as a parameter to one of the class wrapping templates.198 <br><br>199 200 201 <script>explorer.outline.incSymbolLevel();</script>202 <dl></dl>203 <script>explorer.outline.decSymbolLevel();</script>204 205 206 </dd>207 208 <script>explorer.outline.writeEnabled = true;</script>209 <dt><span class="decl">struct210 <span class="currsymbol">WrapProperty</span>211 <script>explorer.outline.addDecl('WrapProperty');</script>212 213 (alias func,char[] name = NameOfFunc!(func),funcType = typeof(&func));214 </span></dt>215 <script>explorer.outline.writeEnabled = false;</script>216 217 218 <dd>Wrap a property given an alias to the property (like A.foo). To be used as a parameter to one of the class wrapping templates.219 <br><br>220 MiniD doesn't have properties, but there is a protocol for property-like functions. A function which takes one parameter and221 <br><br>222 223 returns 0 or 1 values is a setter; a function of the same name with no parameters is the getter. This will automatically224 <br><br>225 226 figure out the setters/getters of the D class's properties, and wrap them into a single MiniD method which will call the setter227 <br><br>228 229 or getter as appropriate based on how many parameters were passed to the MiniD method.230 <br><br>231 232 233 <script>explorer.outline.incSymbolLevel();</script>234 <dl></dl>235 <script>explorer.outline.decSymbolLevel();</script>236 237 275 238 276 </dd> … … 248 286 249 287 <dd>Given an alias to a function, this metafunction will give the minimum legal number of arguments it can be called with. 250 <br><br>251 288 Even works for aliases to class methods. 252 289 <br><br> … … 270 307 271 308 <dd>Given a type tuple, this metafunction will give an expression tuple of all the .init values for each type. 309 <br><br> 310 311 312 <script>explorer.outline.incSymbolLevel();</script> 313 <dl></dl> 314 <script>explorer.outline.decSymbolLevel();</script> 315 316 317 </dd> 318 319 <script>explorer.outline.writeEnabled = true;</script> 320 <dt><span class="decl">template 321 <span class="currsymbol">FieldNames</span> 322 <script>explorer.outline.addDecl('FieldNames');</script> 323 324 (S,int idx = 0)</span></dt> 325 <script>explorer.outline.writeEnabled = false;</script> 326 327 328 <dd>Given a struct type, gives a tuple of strings of the names of fields in the struct. 272 329 <br><br> 273 330 … … 287 344 Page was generated with 288 345 <img src="candydoc/img/candydoc.gif" style="vertical-align:middle; position:relative; top:-1px"> 289 on Thu Nov 8 11:40:162007346 on Sat Nov 17 12:30:58 2007 290 347 291 348 </td></tr> … … 293 350 </div> 294 351 <script> 295 explorer.packageExplorer.addModuleFull("minid.minid"); 296 explorer.packageExplorer.addModuleFull("minid.bind"); 297 explorer.packageExplorer.addModuleFull("minid.types"); 298 explorer.packageExplorer.addModuleFull("minid.compiler"); 299 explorer.packageExplorer.addModuleFull("minid.utils");</script> 352 explorer.packageExplorer.addModuleFull("minid.bind");</script> 300 353 </body></html> 301 354 trunk/minid/bind.d
r237 r238 31 31 32 32 /** 33 Creates a module with the given name and members. 33 Used to wrap a module that is exposed to MiniD. A module can contain any number of functions, classes, structs, 34 and other values. They are added to the module using this struct's methods. 35 36 Examples: 37 ----- 38 WrapModule("foo.bar", myContext) // name it foo.bar, load it into myContext 39 .func!(funcOne)() // wrap native function funcOne; the empty parens here are necessary 40 .func!(funcTwo)() 41 .custom("x", 6)() // set member "x" to the value 6. This can be any convertible type. 42 .type(WrapClass!(MyClass) // wrap the native class MyClass. 43 .method!(MyClass.method)() // A method. Again, the empty parens are necessary. 44 .property!(MyClass.property)()); // a property 45 ----- 34 46 */ 35 public void WrapModule(char[] name, Members...)(MDContext context) 36 { 37 dchar[] name32 = utf.toUtf32(name); 38 39 context.setModuleLoader(name32, new MDClosure(context.globals.ns, delegate int (MDState s, uint numParams) 40 { 41 MDNamespace ns = s.getParam!(MDNamespace)(1); 42 43 foreach(i, member; Members) 44 { 45 static if(is(typeof(member.isFunc))) 46 { 47 dchar[] name = utf.toUtf32(member.Name); 48 ns[name] = MDValue(new MDClosure(ns, &member.WrappedFunc, name)); 49 } 50 else static if(is(typeof(member.isClass))) 51 { 52 dchar[] name = utf.toUtf32(member.Name); 53 ns[name] = MDValue(member.makeClass()); 54 } 55 else static if(is(typeof(member.isStruct))) 56 { 57 dchar[] name = utf.toUtf32(member.Name); 58 ns[name] = MDValue(new member.Class()); 59 } 60 else static if(is(typeof(member.isCustom))) 61 { 62 dchar[] name = utf.toUtf32(member.Name); 63 64 static assert(!is(ReturnTypeOf!(member.Func) == void), "Custom member function may not return void"); 65 66 static if(is(typeof(member.Func(s, ns)))) 67 ns[name] = MDValue(member.Func(s, ns)); 47 struct WrapModule 48 { 49 struct Loader 50 { 51 private MDNamespace namespace; 52 53 private int loader(MDState s, uint numParams) 54 { 55 MDNamespace ns = s.getParam!(MDNamespace)(1); 56 57 foreach(k, v; namespace) 58 ns[k] = v; 59 60 return 0; 61 } 62 } 63 64 private Loader* loader; 65 66 /** 67 Creates an instance of this struct so you can start wrapping a module. 68 69 Params: 70 name = The name of the module to expose to MiniD. This can be a multi-part name, with dots (like "foo.bar"). 71 context = The MiniD context to load this module into. 72 73 Returns: 74 An instance of this struct ready to have members added. 75 */ 76 public static typeof(*this) opCall(char[] name, MDContext context) 77 { 78 typeof(*this) ret; 79 80 ret.loader = new Loader; 81 ret.loader.namespace = new MDNamespace(); 82 83 dchar[] name32 = utf.toUtf32(name); 84 85 context.setModuleLoader(name32, new MDClosure(context.globals.ns, &ret.loader.loader, "module " ~ name32)); 86 87 return ret; 88 } 89 90 /** 91 Wrap a function and insert it into this module's namespace. This must be a non-member D function. 92 93 Params: 94 f = An alias to the function you want to wrap. 95 name = The name to call it in MiniD. Defaults to the D function name. 96 funcType = The type of the function to wrap. This defaults to typeof(f), but you'll need to specify this 97 explicitly if you're wrapping an overloaded function, in order to select the proper overload. 98 99 Returns: 100 A chaining reference to this module. 101 */ 102 public typeof(this) func(alias f, char[] name = NameOfFunc!(f), funcType = typeof(f))() 103 { 104 const name32 = ToUTF32!(name); 105 loader.namespace[name32] = MDValue(new MDClosure(loader.namespace, &WrappedFunc!(f, name, funcType), name32)); 106 107 return this; 108 } 109 110 /** ditto */ 111 public typeof(this) func(alias f, funcType)() 112 { 113 const name = NameOfFunc!(f); 114 const name32 = ToUTF32!(name); 115 loader.namespace[name32] = MDValue(new MDClosure(loader.namespace, &WrappedFunc!(f, name, funcType), name32)); 116 117 return this; 118 } 119 120 /** 121 Insert an arbitrary key-value pair into the module. The value can be any convertible type. 122 123 Params: 124 name = The name to give this value in the module. 125 value = The value to insert. 126 127 Returns: 128 A chaining reference to this module. 129 */ 130 public typeof(this) custom(T)(char[] name, T value) 131 { 132 loader.namespace[utf.toUtf32(name)] = MDValue(value); 133 return this; 134 } 135 136 /** 137 Insert a wrapped class or struct type into the module. 138 139 Params: 140 value = The wrapped class or struct type to insert. This should be an instance of the WrapClass struct, and should have 141 already had its members added to it. 142 name = The name to give this type in the MiniD module. Defaults to "", which means it will use the D name of the type. 143 144 Returns: 145 A chaining reference to this module. 146 */ 147 public typeof(this) type(T)(T value, dchar[] name = "") 148 { 149 value.addToNamespace(loader.namespace, name); 150 return this; 151 } 152 } 153 154 struct WrapClass(ClassType, DirtyCtors...) 155 { 156 static if(is(ClassType == class)) 157 { 158 const ClassName = ToUTF32!(ClassType.stringof); 159 alias WrappedInstance InstanceType; 160 alias WrappedClass MDClassType; 161 } 162 else static if(is(ClassType == struct)) 163 { 164 // DMDFE inserts a spurious space after struct.stringof. 165 const ClassName = ToUTF32!(ClassType.stringof[0 .. $ - 1]); 166 alias WrappedStruct!(ClassType) InstanceType; 167 alias WrappedStructClass!(ClassType) MDClassType; 168 } 169 else 170 static assert(false, "Cannot wrap type " ~ ClassType.stringof); 171 172 alias Unique!(QSort!(SortByNumParams, DirtyCtors)) Ctors; 173 174 private MDClassType mClass; 175 176 public static typeof(*this) opCall() 177 { 178 typeof(*this) ret; 179 180 if(typeid(ClassType) in WrappedClasses) 181 throw new MDException("Native type " ~ ToUTF8!(ClassName) ~ " cannot be wrapped more than once"); 182 183 static if(is(ClassType == class)) 184 { 185 alias BaseTypeTupleOf!(ClassType) Bases; 186 187 static if(!is(Bases[0] == Object)) 188 ret.mClass = new MDClassType(ClassName, GetWrappedClass(typeid(Bases[0]))); 189 else 190 ret.mClass = new MDClassType(ClassName, null); 191 } 192 else 193 { 194 ret.mClass = new MDClassType(ClassName, null); 195 } 196 197 WrappedClasses[typeid(ClassType)] = ret.mClass; 198 199 static if(is(ClassType == struct)) 200 { 201 ret.mClass.mMethods["opIndex"d] = MDValue(new MDClosure(ret.mClass.mMethods, &ret.mClass.getField, ClassName ~ ".opIndex")); 202 ret.mClass.mMethods["opIndexAssign"d] = MDValue(new MDClosure(ret.mClass.mMethods, &ret.mClass.setField, ClassName ~ ".opIndexAssign")); 203 } 204 205 static if(Ctors.length == 0) 206 ret.mClass.mMethods["constructor"d] = MDValue(new MDClosure(ret.mClass.mMethods, &defaultCtor, ClassName ~ ".constructor")); 207 else 208 ret.mClass.mMethods["constructor"d] = MDValue(new MDClosure(ret.mClass.mMethods, &constructor, ClassName ~ ".constructor")); 209 210 return ret; 211 } 212 213 public typeof(this) method(alias func, char[] name = NameOfFunc!(func), funcType = typeof(func))() 214 { 215 const name32 = ToUTF32!(name); 216 mClass.mMethods[name32] = MDValue(new MDClosure(mClass.mMethods, &WrappedMethod!(func, funcType, ClassType), ClassName ~ "." ~ name32)); 217 218 return this; 219 } 220 221 public typeof(this) method(alias func, funcType)() 222 { 223 const name = NameOfFunc!(func); 224 const name32 = ToUTF32!(name); 225 mClass.mMethods[name32] = MDValue(new MDClosure(mClass.mMethods, &WrappedMethod!(func, funcType, ClassType), ClassName ~ "." ~ name32)); 226 227 return this; 228 } 229 230 public typeof(this) property(alias func, char[] name = NameOfFunc!(func), funcType = typeof(func))() 231 { 232 const name32 = ToUTF32!(name); 233 mClass.mMethods[name32] = MDValue(new MDClosure(mClass.mMethods, &WrappedProperty!(func, name, funcType, ClassType), ClassName ~ "." ~ name32)); 234 235 return this; 236 } 237 238 public typeof(this) property(alias func, funcType)() 239 { 240 const name = NameOfFunc!(func); 241 const name32 = ToUTF32!(name); 242 mClass.mMethods[name32] = MDValue(new MDClosure(mClass.mMethods, &WrappedProperty!(func, name, funcType, ClassType), ClassName ~ "." ~ name32)); 243 244 return this; 245 } 246 247 public void makeGlobal(MDContext ctx, dchar[] name = "") 248 { 249 if(name.length == 0) 250 ctx.globals[ClassName] = MDValue(mClass); 251 else 252 ctx.globals[name] = MDValue(mClass); 253 } 254 255 public void addToNamespace(MDNamespace ns, dchar[] name = "") 256 { 257 if(name.length == 0) 258 ns[ClassName] = MDValue(mClass); 259 else 260 ns[name] = MDValue(mClass); 261 } 262 263 static if(Ctors.length == 0) 264 { 265 static if(is(ClassType == class)) 266 static assert(is(typeof(new ClassType())), "Cannot call default constructor for class " ~ ToUTF8!(ClassName) ~ "; please wrap a constructor explicitly"); 267 else 268 static assert(is(typeof(ClassType())), "Cannot call default constructor for struct " ~ ToUTF8!(ClassName) ~ "; please wrap a constructor explicitly"); 269 270 private static int defaultCtor(MDState s, uint numParams) 271 { 272 auto self = s.getContext!(InstanceType); 273 assert(self !is null, "Invalid 'this' parameter passed to " ~ ToUTF8!(ClassName) ~ ".constructor"); 274 275 static if(is(ClassType == class)) 276 self.inst = new ClassType(); 277 else 278 self.inst = ClassType(); 279 280 return 0; 281 } 282 } 283 else 284 { 285 private static int constructor(MDState s, uint numParams) 286 { 287 auto self = s.getContext!(InstanceType); 288 assert(self !is null, "Invalid 'this' parameter passed to " ~ ToUTF8!(ClassName) ~ ".constructor"); 289 290 static if(is(ClassType == class)) 291 { 292 static if(is(typeof(new ClassType()))) 293 const minArgs = 0; 68 294 else 69 ns[name] = MDValue(member.Func());295 const minArgs = ParameterTupleOf!(Ctors[0]).length; 70 296 } 71 297 else 72 static assert(false, "Invalid member type '" ~ typeof(member).stringof ~ "' in wrapped module '" ~ name ~ "'"); 73 } 74 75 return 0; 76 }, "module " ~ name32)); 298 { 299 static if(is(typeof(ClassType()))) 300 const minArgs = 0; 301 else 302 const minArgs = ParameterTupleOf!(Ctors[0]).length; 303 } 304 305 const maxArgs = ParameterTupleOf!(Ctors[$ - 1]).length; 306 307 MDValue[maxArgs] args; 308 309 if(numParams < minArgs) 310 s.throwRuntimeException("At least " ~ Itoa!(minArgs) ~ " parameter" ~ (minArgs == 1 ? "" : "s") ~ " expected, not {}", numParams); 311 312 if(numParams > maxArgs) 313 numParams = maxArgs; 314 315 static if(minArgs == 0) 316 { 317 if(numParams == 0) 318 { 319 static if(is(ClassType == class)) 320 self.inst = new ClassType(); 321 else 322 self.inst = ClassType(); 323 324 return 0; 325 } 326 } 327 328 for(uint i = 0; i < numParams; i++) 329 args[i] = s.getParam(i); 330 331 static if(is(ClassType == class)) 332 const Switch = GenerateCases!(Ctors); 333 else 334 const Switch = GenerateStructCases!(Ctors); 335 336 mixin(Switch); 337 338 dchar[] typeString = "("; 339 340 if(numParams > 0) 341 { 342 typeString ~= s.getParam(0u).typeString(); 343 344 for(uint i = 1; i < numParams; i++) 345 typeString ~= ", " ~ s.getParam(i).typeString(); 346 } 347 348 typeString ~= ")"; 349 350 s.throwRuntimeException("Parameter list {} passed to constructor does not match any wrapped constructors", typeString); 351 } 352 } 77 353 } 78 354 79 355 /** 80 This wraps a function, and is meant to be used as a parameter to WrapModule. 356 Given a function alias, and an optional name and type for overloading, this will wrap the function and register 357 it in the global namespace. This is not meant to be used as a parameter to WrapModule, as it's not in any module. 81 358 */ 82 public struct WrapFunc(alias func) 83 { 84 const bool isFunc = true; 85 const char[] Name = NameOfFunc!(func); 86 mixin WrappedFunc!(func, Name, typeof(&func)); 359 public void WrapFunc(alias func, char[] name = NameOfFunc!(func), funcType = typeof(&func))(MDNamespace ns) 360 { 361 const name32 = ToUTF32!(name); 362 ns[name32] = new MDClosure(ns, &WrappedFunc!(func, name, funcType), name32); 87 363 } 88 364 … … 90 366 public template WrapFunc(alias func, funcType) 91 367 { 92 const bool isFunc = true; 93 const char[] Name = NameOfFunc!(func); 94 mixin WrappedFunc!(func, Name, funcType); 95 } 96 97 /// ditto 98 public struct WrapFunc(alias func, char[] name) 99 { 100 const bool isFunc = true; 101 const char[] Name = name; 102 mixin WrappedFunc!(func, Name, typeof(&func)); 103 } 104 105 /// ditto 106 public struct WrapFunc(alias func, char[] name, funcType) 107 { 108 const bool isFunc = true; 109 const char[] Name = name; 110 mixin WrappedFunc!(func, Name, funcType); 368 alias WrapFunc!(func, NameOfFunc!(func), funcType) WrapFunc; 111 369 } 112 370 … … 117 375 public void WrapGlobalFunc(alias func, char[] name = NameOfFunc!(func), funcType = typeof(&func))(MDContext context) 118 376 { 119 dchar[] n = utf.toUtf32(name);120 context.globals[n ] = context.newClosure(&WrappedFunc!(func, name, funcType), n);377 const name32 = ToUTF32!(name); 378 context.globals[name32] = context.newClosure(&WrappedFunc!(func, name, funcType), name32); 121 379 } 122 380 … … 127 385 } 128 386 129 public struct WrapCustom(char[] name, alias func)130 {131 const bool isCustom = true;132 const char[] Name = name;133 alias func Func;134 }135 136 private class WrappedClass : MDClass137 {138 private this(dchar[] name, MDClass base)139 {140 super(name, base);141 }142 143 public override WrappedInstance newInstance()144 {145 return new WrappedInstance(this);146 }147 }148 149 private class WrappedInstance : MDInstance150 {151 private Object inst;152 153 private this(MDClass owner)154 {155 super(owner);156 }157 }158 159 private class WrappedStruct(T) : MDInstance160 {161 private T inst;162 163 private this(MDClass owner)164 {165 super(owner);166 }167 }168 169 387 /** 170 Wraps a D class of the given type with the given members. name is the name that will be given to the class in MiniD.171 This is meant to be used as a parameter to WrapModule.388 Given an alias to a function, this metafunction will give the minimum legal number of arguments it can be called with. 389 Even works for aliases to class methods. 172 390 */ 173 public struct WrapClass(ClassType, char[] name = ClassType.stringof, Members...) 174 { 175 static assert(!is(ClassType == Object), "Wrapping Object is not allowed"); 176 177 const bool isClass = true; 178 const char[] Name = name; 179 const CtorCount = CountCtors!(Members); 180 const className = ToUTF32!(name); 181 182 static assert(CtorCount <= 1, "Cannot have more than one WrapCtors instance in wrapped class parameters for class " ~ ClassType.stringof); 183 184 public static WrappedClass makeClass() 185 { 186 alias BaseTypeTupleOf!(ClassType) Bases; 187 188 if(typeid(ClassType) in WrappedClasses) 189 throw new MDException("Native class " ~ ClassType.stringof ~ " cannot be wrapped more than once"); 190 191 WrappedClass self; 192 193 static if(!is(Bases[0] == Object)) 194 { 195 self = new WrappedClass(className, GetWrappedClass(typeid(Bases[0]))); 196 } 197 else 198 { 199 self = new WrappedClass(className, null); 200 } 201 202 WrappedClasses[typeid(ClassType)] = self; 203 204 foreach(i, member; Members) 205 { 206 static if(is(typeof(member.isMethod))) 207 { 208 const name = ToUTF32!(member.Name); 209 self.mMethods[name] = MDValue(new MDClosure(self.mMethods, &WrappedMethod!(member.Func, member.FuncType, ClassType), className ~ "." ~ name)); 210 } 211 else static if(is(typeof(member.isProperty))) 212 { 213 const name = ToUTF32!(member.Name); 214 self.mMethods[name] = MDValue(new MDClosure(self.mMethods, &WrappedProperty!(member.Func, member.Name, member.FuncType, ClassType), className ~ "." ~ name)); 215 } 216 else static if(is(typeof(member.isCtors))) 217 { 218 self.mMethods["constructor"d] = MDValue(new MDClosure(self.mMethods, &constructor!(member.Types), className ~ ".constructor")); 219 } 220 else 221 static assert(false, "Invalid member type '" ~ typeof(member).stringof ~ "' in wrapped class '" ~ name ~ "'"); 222 } 223 224 static if(CtorCount == 0) 225 self.mMethods["constructor"d] = MDValue(new MDClosure(self.mMethods, &defaultCtor, className ~ ".constructor")); 226 227 return self; 228 } 229 230 static if(CtorCount == 0) 231 { 232 static assert(is(typeof(new ClassType())), "Cannot call default constructor for class " ~ ClassType.stringof ~ "; please wrap a constructor explicitly"); 233 234 private static int defaultCtor(MDState s, uint numParams) 235 { 236 auto self = s.getContext!(WrappedInstance); 237 assert(self !is null, "Invalid 'this' parameter passed to " ~ ClassType.stringof ~ ".constructor"); 238 239 self.inst = new ClassType(); 240 return 0; 241 } 242 } 243 else 244 { 245 private static int constructor(Ctors...)(MDState s, uint numParams) 246 { 247 auto self = s.getContext!(WrappedInstance); 248 assert(self !is null, "Invalid 'this' parameter passed to " ~ ClassType.stringof ~ ".constructor"); 249 250 static if(is(typeof(new ClassType()))) 251 const minArgs = 0; 252 else 253 const minArgs = ParameterTupleOf!(Ctors[0]).length; 254 255 const maxArgs = ParameterTupleOf!(Ctors[$ - 1]).length; 256 257 MDValue[maxArgs] args; 258 259 if(numParams < minArgs) 260 s.throwRuntimeException("At least " ~ itoa!(minArgs) ~ " parameter" ~ (minArgs == 1 ? "" : "s") ~ " expected, not {}", numParams); 261 262 if(numParams > maxArgs) 263 numParams = maxArgs; 264 265 static if(minArgs == 0) 266 { 267 if(numParams == 0) 268 { 269 self.inst = new ClassType(); 270 return 0; 271 } 272 } 273 274 for(uint i = 0; i < numParams; i++) 275 args[i] = s.getParam(i); 276 277 const Switch = GenerateCases!(Ctors); 278 mixin(Switch); 279 280 dchar[] typeString = "("; 281 282 if(numParams > 0) 283 { 284 typeString ~= s.getParam(0u).typeString(); 285 286 for(uint i = 1; i < numParams; i++) 287 typeString ~= ", " ~ s.getParam(i).typeString(); 288 } 289 290 typeString ~= ")"; 291 292 s.throwRuntimeException("Parameter list {} passed to constructor does not match any wrapped constructors", typeString); 293 } 294 } 391 public template MinArgs(alias func) 392 { 393 const uint MinArgs = MinArgsImpl!(func, 0, InitsOf!(ParameterTupleOf!(typeof(&func)))); 394 } 395 396 public template MinArgsImpl(alias func, int index, Args...) 397 { 398 static if(index >= Args.length) 399 const uint MinArgsImpl = Args.length; 400 else static if(is(typeof(func(Args[0 .. index])))) 401 const uint MinArgsImpl = index; 402 else 403 const uint MinArgsImpl = MinArgsImpl!(func, index + 1, Args); 404 } 405 406 /** 407 Given a type tuple, this metafunction will give an expression tuple of all the .init values for each type. 408 */ 409 public template InitsOf(T...) 410 { 411 static if(T.length == 0) 412 alias Tuple!() InitsOf; 413 else static if(is(T[0] == MDValue)) 414 alias Tuple!(MDValue.nullValue, InitsOf!(T[1 .. $])) InitsOf; 415 else 416 alias Tuple!(InitOf!(T[0]), InitsOf!(T[1 .. $])) InitsOf; 417 } 418 419 private template InitOf(T) 420 { 421 static if(!is(typeof(Tuple!(T.init)))) 422 { 423 static assert(is(T == struct), "I don't know what to do with this."); 424 alias Tuple!(T(InitsOf!(typeof(T.tupleof)))) InitOf; 425 } 426 else 427 alias Tuple!(T.init) InitOf; 428 } 429 430 /** 431 Given a struct type, gives a tuple of strings of the names of fields in the struct. 432 */ 433 public template FieldNames(S, int idx = 0) 434 { 435 static if(idx >= S.tupleof.length) 436 alias Tuple!() FieldNames; 437 else 438 alias Tuple!(GetLastName!(S.tupleof[idx].stringof), FieldNames!(S, idx + 1)) FieldNames; 439 } 440 441 private template GetLastName(char[] fullName, int idx = fullName.length - 1) 442 { 443 static if(idx < 0) 444 const char[] GetLastName = fullName; 445 else static if(fullName[idx] == '.') 446 const char[] GetLastName = fullName[idx + 1 .. $]; 447 else 448 const char[] GetLastName = GetLastName!(fullName, idx - 1); 295 449 } 296 450 … … 306 460 const GenerateCasesImpl = ""; 307 461 else static if(NumParams!(Ctors[0]) != num) 308 const GenerateCasesImpl = "break;\ncase " ~ itoa!(NumParams!(Ctors[0])) ~ ":\n" ~ GenerateCasesImpl!(NumParams!(Ctors[0]), idx, Ctors);309 else 310 { 311 const GenerateCasesImpl = "if(TypesMatch!(ParameterTupleOf!(Ctors[" ~ itoa!(idx) ~ "]))(args[0 .. " ~ itoa!(num) ~ "]))312 { 313 ParameterTupleOf!(Ctors[" ~ itoa!(idx) ~ "]) params;462 const GenerateCasesImpl = "break;\ncase " ~ Itoa!(NumParams!(Ctors[0])) ~ ":\n" ~ GenerateCasesImpl!(NumParams!(Ctors[0]), idx, Ctors); 463 else 464 { 465 const GenerateCasesImpl = "if(TypesMatch!(ParameterTupleOf!(Ctors[" ~ Itoa!(idx) ~ "]))(args[0 .. " ~ Itoa!(num) ~ "])) 466 { 467 ParameterTupleOf!(Ctors[" ~ Itoa!(idx) ~ "]) params; 314 468 315 469 foreach(i, arg; params) … … 333 487 const GenerateStructCasesImpl = ""; 334 488 else static if(NumParams!(Ctors[0]) != num) 335
