Changeset 238

Show
Ignore:
Timestamp:
11/17/07 12:31:58 (1 year ago)
Author:
JarrettBillingsley
Message:

--

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/docs/candydoc/modules.ddoc

    r230 r238  
    11MODULES = 
    2     $(MODULE_FULL minid.minid) 
    32    $(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  
    4545<dl> 
    4646<script>explorer.outline.writeEnabled = true;</script> 
    47 <dt><span class="decl">void  
     47<dt><span class="decl">struct  
    4848<span class="currsymbol">WrapModule</span> 
    4949<script>explorer.outline.addDecl('WrapModule');</script> 
    5050 
    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, 
     57and 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> 
     98An 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> 
     148A 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> 
     179A 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> 
     227A 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  
    63240<span class="currsymbol">WrapFunc</span> 
    64241<script>explorer.outline.addDecl('WrapFunc');</script> 
    65242 
    66 (alias func,char[] name = NameOfFunc!(func),funcType = typeof(&amp;func))
     243(alias func,char[] name = NameOfFunc!(func),funcType = typeof(&amp;func))(MDNamespace <span class="funcparam">ns</span>)
    67244<br>template  
    68245<span class="currsymbol">WrapFunc</span> 
     
    73250 
    74251 
    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 
     253it 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> 
    83255 
    84256</dd> 
     
    99271 
    100272<dd>Given a function alias, and an optional name and type for overloading, this will wrap the function and register 
    101 <br><br> 
    102273it in the global namespace.  This is not meant to be used as a parameter to WrapModule, as it's not in any module. 
    103274<br><br> 
    104  
    105 </dd> 
    106  
    107 <script>explorer.outline.writeEnabled = true;</script> 
    108 <dt><span class="decl">struct  
    109 <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">template  
    130 <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">void  
    150 <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">template  
    165 <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">struct  
    185 <span class="currsymbol">WrapMethod</span> 
    186 <script>explorer.outline.addDecl('WrapMethod');</script> 
    187  
    188 (alias func,char[] name = NameOfFunc!(func),funcType = typeof(&amp;func)); 
    189 <br>template  
    190 <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">struct  
    210 <span class="currsymbol">WrapProperty</span> 
    211 <script>explorer.outline.addDecl('WrapProperty');</script> 
    212  
    213 (alias func,char[] name = NameOfFunc!(func),funcType = typeof(&amp;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 and 
    221 <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 automatically 
    224 <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 setter 
    227 <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  
    237275 
    238276</dd> 
     
    248286 
    249287<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> 
    251288Even works for aliases to class methods. 
    252289<br><br> 
     
    270307 
    271308<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. 
    272329<br><br> 
    273330 
     
    287344            Page was generated with 
    288345            <img src="candydoc/img/candydoc.gif" style="vertical-align:middle; position:relative; top:-1px"> 
    289             on Thu Nov  8 11:40:16 2007 
     346            on Sat Nov 17 12:30:58 2007 
    290347 
    291348        </td></tr> 
     
    293350</div> 
    294351<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> 
    300353</body></html> 
    301354 
  • trunk/minid/bind.d

    r237 r238  
    3131 
    3232/** 
    33 Creates a module with the given name and members. 
     33Used to wrap a module that is exposed to MiniD.  A module can contain any number of functions, classes, structs, 
     34and other values.  They are added to the module using this struct's methods. 
     35 
     36Examples: 
     37----- 
     38WrapModule("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----- 
    3446*/ 
    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)); 
     47struct 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 
     154struct 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; 
    68294                else 
    69                     ns[name] = MDValue(member.Func())
     295                    const minArgs = ParameterTupleOf!(Ctors[0]).length
    70296            } 
    71297            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    } 
    77353} 
    78354 
    79355/** 
    80 This wraps a function, and is meant to be used as a parameter to WrapModule. 
     356Given a function alias, and an optional name and type for overloading, this will wrap the function and register 
     357it in the global namespace.  This is not meant to be used as a parameter to WrapModule, as it's not in any module. 
    81358*/ 
    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)); 
     359public 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); 
    87363} 
    88364 
     
    90366public template WrapFunc(alias func, funcType) 
    91367{ 
    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; 
    111369} 
    112370 
     
    117375public void WrapGlobalFunc(alias func, char[] name = NameOfFunc!(func), funcType = typeof(&func))(MDContext context) 
    118376{ 
    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); 
    121379} 
    122380 
     
    127385} 
    128386 
    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 : MDClass 
    137 { 
    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 : MDInstance 
    150 { 
    151     private Object inst; 
    152  
    153     private this(MDClass owner) 
    154     { 
    155         super(owner); 
    156     } 
    157 } 
    158  
    159 private class WrappedStruct(T) : MDInstance 
    160 { 
    161     private T inst; 
    162  
    163     private this(MDClass owner) 
    164     { 
    165         super(owner); 
    166     } 
    167 } 
    168  
    169387/** 
    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
     388Given an alias to a function, this metafunction will give the minimum legal number of arguments it can be called with
     389Even works for aliases to class methods
    172390*/ 
    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     } 
     391public template MinArgs(alias func) 
     392
     393    const uint MinArgs = MinArgsImpl!(func, 0, InitsOf!(ParameterTupleOf!(typeof(&func)))); 
     394
     395 
     396public 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/** 
     407Given a type tuple, this metafunction will give an expression tuple of all the .init values for each type. 
     408*/ 
     409public 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 
     419private 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/** 
     431Given a struct type, gives a tuple of strings of the names of fields in the struct. 
     432*/ 
     433public 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 
     441private 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); 
    295449} 
    296450 
     
    306460        const GenerateCasesImpl = ""; 
    307461    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; 
    314468 
    315469    foreach(i, arg; params) 
     
    333487        const GenerateStructCasesImpl = ""; 
    334488    else static if(NumParams!(Ctors[0]) != num) 
    335