tagged release 0.6.4
[parrot.git] / languages / lua / src / pmc / luaany.pmc
blobf1fec1af4ed6d0640dc9d9bf9955437875564c4b
1 /*
2 Copyright (C) 2006-2008, The Perl Foundation.
3 $Id$
5 =head1 NAME
7 pmc/luaany.pmc - Lua abstract base class
9 =head1 DESCRIPTION
11 C<LuaAny> provides an abstract base class for some Lua types.
13 =head2 PMC Inheritance Summary
15  Class                  Parents
16  -----------------------------------------------
17  LuaBoolean             LuaAny, Default
18  LuaClosure             Closure, LuaAny, Default
19  LuaFunction            Sub, LuaAny, Default
20  LuaNil                 LuaAny, Default
21  LuaNumber              LuaAny, Default
22  LuaString              LuaAny, Default
23  LuaTable               LuaAny, Default
24  LuaThread              LuaAny, Default
25  LuaUserdata            LuaAny, Default
27 =head2 PMC "Attribute" Summary
29  Class                  Metatable       Environment     Userdata
30      accessor           get_metatable   getfenv         get_attr_str (getattribute)
31      mutator            set_metatable   setfenv         set_attr_str (setattribute)
32      default value      nil             nil             NULL
33  ------------------------------------------------------------------
34  LuaBoolean             nil             -               -
35  LuaClosure             nil             yes             -
36  LuaFunction            nil             yes             -
37  LuaNil                 nil             -               -
38  LuaNumber              nil             -               -
39  LuaString              yes (common)    -               -
40  LuaTable               yes             -               -
41  LuaThread              nil             yes             -
42  LuaUserdata            yes             yes             yes
44 The metatable supports the OO mecanism.
46 =head2 Methods
48 =over 4
50 =cut
54 #include "lua_private.h"
57 PMC *
58 find_meth(PARROT_INTERP, PMC *obj, const char *name) {
59     PMC   *meta = NULL;
60     INTVAL type = PMC_type(obj);
62     if (dynpmc_LuaString == type) {
63         meta = Parrot_find_global_s(interp,
64                                     const_string(interp, "Lua::string"),
65                                     const_string(interp, "mt_string"));
66     }
68     if (dynpmc_LuaClosure != type && dynpmc_LuaFunction != type) {
69         if (obj->pmc_ext)
70             meta = PMC_metadata(obj);
72         if (meta && dynpmc_LuaTable != PMC_type(meta))
73             return meta;
74     }
76     if (meta) {
77         PMC *method;
78         PMC *key = pmc_new(interp, dynpmc_LuaString);
79         VTABLE_set_string_native(interp, key, const_string(interp, name));
81         method = VTABLE_get_pmc_keyed(interp, meta, key);
83         if (dynpmc_LuaNil != PMC_type(method))
84             return method;
85     }
87     return NULL;
91 pmclass LuaAny
92     abstract
93     dynpmc
94     group lua_group
95     hll Lua {
98 =item C<void morph(INTVAL type)>
100 Changes the PMC to a PMC of a new type
102 =cut
105     void morph(INTVAL type) {
106         if (PMC_type(SELF) == type)
107             return;
108         pmc_reuse(INTERP, SELF, type, 0);
109     }
113 =item C<INTVAL get_bool()>
115 Returns C<true>.
117 =cut
120     INTVAL get_bool() {
121         return (INTVAL)1;
122     }
126 =item C<void *get_pointer()>
128 Returns the address of the PMC.
130 =cut
133     void* get_pointer() {
134         return SELF;
135     }
139 =item C<void assign_pmc(PMC *value)>
141 =cut
144     void assign_pmc(PMC *value) {
145         VTABLE_morph(INTERP, SELF, PMC_type(value));
146         if (PMC_type(value) != dynpmc_LuaNil)
147             SELF.set_pmc(value);
148     }
152 =item C<PMC* get_pmc_keyed(PMC *key)>
154 Throws an exception.
156 =cut
159     PMC* get_pmc_keyed(PMC *key) {
160         PMC *meth = find_meth(INTERP, SELF, "__index");
162         if (meth) {
163             if (dynpmc_LuaClosure  == PMC_type(meth)
164             ||  dynpmc_LuaFunction == PMC_type(meth)) {
165                 PMC *retval = Parrot_runops_fromc_args(INTERP, meth, "PPP",
166                                                        SELF, key);
167                 if (retval)
168                     return retval;
170                 return pmc_new(INTERP, dynpmc_LuaNil);
171             }
172             else
173                 return VTABLE_get_pmc_keyed(INTERP, meth, key);
174         }
175         real_exception(INTERP, NULL, ILL_INHERIT,
176                 "attempt to index a %Ss value", SELF.name());
177     }
181 =item C<void set_pmc_keyed(PMC* key, PMC* value)>
183 Throws an exception.
185 =cut
188     void set_pmc_keyed(PMC *key, PMC *value) {
189         PMC *meth = find_meth(INTERP, SELF, "__newindex");
191         if (!meth)
192             real_exception(INTERP, NULL, ILL_INHERIT,
193                 "attempt to index a %Ss value", SELF.name());
195         if (dynpmc_LuaClosure  == PMC_type(meth)
196         ||  dynpmc_LuaFunction == PMC_type(meth)) {
197             Parrot_runops_fromc_args(INTERP, meth, "vPPP",
198                                      SELF, key, value);
199         }
200         else
201             VTABLE_set_pmc_keyed(INTERP, meth, key, value);
202     }
206 =item C<PMC* neg(PMC *dest)>
208 =item C<void i_neg()>
210 Throws an exception.
212 =cut
215     PMC* neg(PMC *dest) {
216         PMC *meth = find_meth(INTERP, SELF, "__unm");
218         if (!meth)
219             real_exception(INTERP, NULL, ILL_INHERIT,
220                 "attempt to perform arithmetic on a %Ss value", SELF.name());
222         dest = Parrot_runops_fromc_args(INTERP, meth, "PP", SELF);
224         if (PMC_IS_NULL(dest))
225             return pmc_new(INTERP, dynpmc_LuaNil);
227         return dest;
228     }
230     void i_neg() {
231         PMC *meth = find_meth(INTERP, SELF, "__unm");
233         if (!meth)
234             real_exception(INTERP, NULL, ILL_INHERIT,
235                 "attempt to perform arithmetic on a %Ss value", SELF.name());
237         SELF = Parrot_runops_fromc_args(INTERP, meth, "PP", SELF);
239         if (PMC_IS_NULL(SELF))
240                 SELF = pmc_new(INTERP, dynpmc_LuaNil);
241     }
245 =item C<PMC* logical_not(PMC *dest)>
247 Common implementation
249 =cut
252     PMC* logical_not(PMC *dest) {
253         dest = pmc_new(INTERP, dynpmc_LuaBoolean);
254         VTABLE_set_bool(INTERP, dest, ! SELF.get_bool());
255         return dest;
256     }
260 =item C<INTVAL defined()>
262 Always returns true.
264 =cut
267     INTVAL defined() {
268         return (INTVAL)1;
269     }
273 =item C<void* invoke(void* next)>
275 Throws an exception.
277 =cut
280     opcode_t* invoke(void *next) {
281         PMC *meth = find_meth(INTERP, SELF, "__call");
282         PMC *retval;
284         if (!meth)
285             real_exception(INTERP, NULL, ILL_INHERIT,
286                 "attempt to call a %Ss value", SELF.name());
288             /* fix me */
289 #if 1
290             retval = Parrot_runops_fromc_args(INTERP, meth, "PP", SELF);
291             if (!retval)
292                 retval = pmc_new(INTERP, dynpmc_LuaNil);
293 #else
294             next = VTABLE_invoke(INTERP, meth, next);
295 #endif
296             return (opcode_t *)next;
297     }
301 =back
303 =head2 non-Vtable Methods
305 =over 4
307 =item C<void add(PMC *value, PMC *dest)>
309 =item C<void i_add(PMC *value)>
311 =item C<void subtract(PMC *value, PMC *dest)>
313 =item C<void i_substract (PMC *value)>
315 =item C<void multiply(PMC *value, PMC *dest)>
317 =item C<void i_multiply(PMC *value)>
319 =item C<void divide(PMC *value, PMC *dest)>
321 =item C<void i_divide(PMC *value)>
323 =item C<PMC* modulus(PMC *value, PMC *dest)>
325 =item C<void i_modulus(PMC *value)>
327 =item C<PMC* pow(PMC *value, PMC *dest)>
329 =item C<void i_pow(PMC *value)>
331 =item C<PMC* concatenate(PMC *value, PMC *dest)>
333 =item C<void i_concatenate(PMC *value)>
335 Throws an exception.
337 =cut
340     PMC* add(PMC *value, PMC *dest) {
341         PMC *meth = find_meth(INTERP, SELF, "__add");
342         if (!meth)
343             real_exception(INTERP, NULL, ILL_INHERIT,
344                 "attempt to perform arithmetic on a %Ss value", SELF.name());
346         dest = Parrot_runops_fromc_args(INTERP, meth, "PPP", SELF, value);
348         if (PMC_IS_NULL(dest))
349             return pmc_new(INTERP, dynpmc_LuaNil);
351         return dest;
352     }
354     void i_add(PMC *value) {
355         PMC *meth = find_meth(INTERP, SELF, "__add");
357         if (!meth)
358             real_exception(INTERP, NULL, ILL_INHERIT,
359                 "attempt to perform arithmetic on a %Ss value", SELF.name());
361         SELF = Parrot_runops_fromc_args(INTERP, meth, "PPP", SELF, value);
362         if (PMC_IS_NULL(SELF))
363             SELF = pmc_new(INTERP, dynpmc_LuaNil);
364     }
366     PMC* subtract(PMC *value, PMC *dest) {
367         PMC *meth = find_meth(INTERP, SELF, "__sub");
368         if (!meth)
369             real_exception(INTERP, NULL, ILL_INHERIT,
370                 "attempt to perform arithmetic on a %Ss value", SELF.name());
372         dest = Parrot_runops_fromc_args(INTERP, meth, "PPP", SELF, value);
374         if (PMC_IS_NULL(dest))
375             return pmc_new(INTERP, dynpmc_LuaNil);
377         return dest;
378     }
380     void i_subtract(PMC *value) {
381         PMC *meth = find_meth(INTERP, SELF, "__sub");
382         if (!meth)
383             real_exception(INTERP, NULL, ILL_INHERIT,
384                 "attempt to perform arithmetic on a %Ss value", SELF.name());
386         SELF = Parrot_runops_fromc_args(INTERP, meth, "PPP", SELF, value);
388         if (PMC_IS_NULL(SELF))
389             SELF = pmc_new(INTERP, dynpmc_LuaNil);
390     }
392     PMC* multiply(PMC *value, PMC *dest) {
393         PMC *meth = find_meth(INTERP, SELF, "__mul");
395         if (!meth)
396             real_exception(INTERP, NULL, ILL_INHERIT,
397                 "attempt to perform arithmetic on a %Ss value", SELF.name());
399         dest = Parrot_runops_fromc_args(INTERP, meth, "PPP", SELF, value);
401         if (PMC_IS_NULL(dest))
402             return pmc_new(INTERP, dynpmc_LuaNil);
404         return dest;
405     }
407     void i_multiply(PMC *value) {
408         PMC *meth = find_meth(INTERP, SELF, "__mul");
410         if (!meth)
411             real_exception(INTERP, NULL, ILL_INHERIT,
412                 "attempt to perform arithmetic on a %Ss value", SELF.name());
414         SELF = Parrot_runops_fromc_args(INTERP, meth, "PPP", SELF, value);
416         if (PMC_IS_NULL(SELF))
417             SELF = pmc_new(INTERP, dynpmc_LuaNil);
418     }
420     PMC* divide(PMC *value, PMC *dest) {
421         PMC *meth = find_meth(INTERP, SELF, "__div");
423         if (!meth)
424             real_exception(INTERP, NULL, ILL_INHERIT,
425                 "attempt to perform arithmetic on a %Ss value", SELF.name());
427         dest = Parrot_runops_fromc_args(INTERP, meth, "PPP", SELF, value);
429         if (PMC_IS_NULL(dest))
430             return pmc_new(INTERP, dynpmc_LuaNil);
432         return dest;
433     }
435     void i_divide(PMC *value) {
436         PMC *meth = find_meth(INTERP, SELF, "__div");
438         if (!meth)
439             real_exception(INTERP, NULL, ILL_INHERIT,
440                 "attempt to perform arithmetic on a %Ss value", SELF.name());
442         SELF = Parrot_runops_fromc_args(INTERP, meth, "PPP", SELF, value);
444         if (PMC_IS_NULL(SELF))
445             SELF = pmc_new(INTERP, dynpmc_LuaNil);
446     }
448     PMC* modulus(PMC *value, PMC *dest) {
449         PMC *meth = find_meth(INTERP, SELF, "__mod");
451         if (!meth)
452             real_exception(INTERP, NULL, ILL_INHERIT,
453                 "attempt to perform arithmetic on a %Ss value", SELF.name());
455         dest = Parrot_runops_fromc_args(INTERP, meth, "PPP", SELF, value);
457         if (PMC_IS_NULL(dest))
458             return pmc_new(INTERP, dynpmc_LuaNil);
460         return dest;
461     }
463     void i_modulus(PMC *value) {
464         PMC *meth = find_meth(INTERP, SELF, "__mod");
466         if (!meth)
467             real_exception(INTERP, NULL, ILL_INHERIT,
468                 "attempt to perform arithmetic on a %Ss value", SELF.name());
470         SELF = Parrot_runops_fromc_args(INTERP, meth, "PPP", SELF, value);
472         if (PMC_IS_NULL(SELF))
473             SELF = pmc_new(INTERP, dynpmc_LuaNil);
474     }
476     PMC* pow(PMC *value, PMC *dest) {
477         PMC *meth = find_meth(INTERP, SELF, "__pow");
479         if (!meth)
480             real_exception(INTERP, NULL, ILL_INHERIT,
481                 "attempt to perform arithmetic on a %Ss value", SELF.name());
483         dest = Parrot_runops_fromc_args(INTERP, meth, "PPP", SELF, value);
485         if (PMC_IS_NULL(dest))
486             return pmc_new(INTERP, dynpmc_LuaNil);
488         return dest;
489     }
491     void i_pow(PMC *value) {
492         PMC *meth = find_meth(INTERP, SELF, "__pow");
494         if (!meth)
495             real_exception(INTERP, NULL, ILL_INHERIT,
496                 "attempt to perform arithmetic on a %Ss value", SELF.name());
498         SELF = Parrot_runops_fromc_args(INTERP, meth, "PPP", SELF, value);
500         if (PMC_IS_NULL(SELF))
501             SELF = pmc_new(INTERP, dynpmc_LuaNil);
502     }
504     PMC* concatenate(PMC *value, PMC *dest) {
505         PMC *meth = find_meth(INTERP, SELF, "__concat");
507         if (!meth)
508             real_exception(INTERP, NULL, ILL_INHERIT,
509                 "attempt to concatenate a %Ss value", SELF.name());
511         dest = Parrot_runops_fromc_args(INTERP, meth, "PPP", SELF, value);
513         if (PMC_IS_NULL(dest))
514             return pmc_new(INTERP, dynpmc_LuaNil);
516         return dest;
517     }
519     void i_concatenate(PMC *value) {
520         PMC *meth = find_meth(INTERP, SELF, "__concat");
521         if (!meth)
522             real_exception(INTERP, NULL, ILL_INHERIT,
523                 "attempt to concatenate a %Ss value", SELF.name());
525         SELF = Parrot_runops_fromc_args(INTERP, meth, "PPP", SELF, value);
527         if (PMC_IS_NULL(SELF))
528             SELF = pmc_new(INTERP, dynpmc_LuaNil);
529     }
533 =item C<INTVAL is_equal(PMC *value)>
535 =cut
538     INTVAL is_equal(PMC *value) {
539         return (INTVAL)0;
540     }
544 =item C<INTVAL cmp(PMC *value)>
546 =cut
549     INTVAL cmp(PMC *value) {
550         STRING *self_name = SELF.name();
551         STRING *val_name  = VTABLE_name(INTERP, value);
553         if (string_compare(INTERP, self_name, val_name) != 0)
554             real_exception(INTERP, NULL, ILL_INHERIT,
555                     "attempt to compare %Ss with %Ss", self_name, val_name);
556         else
557             real_exception(INTERP, NULL, ILL_INHERIT,
558                     "attempt to compare two %Ss values", self_name);
559     }
563 =back
565 =head2 Specific Methods
567 =over 4
569 =item C<PMC *get_metatable()>
571 =cut
574     METHOD PMC* get_metatable() {
575         PMC *nil = pmc_new(INTERP, dynpmc_LuaNil);
576         RETURN(PMC *nil);
577     }
581 =item C<PMC* len()>
584 =cut
587     METHOD PMC* len() {
588         PMC *meth = find_meth(INTERP, SELF, "__len");
589         PMC *retval;
591         if (!meth)
592             real_exception(INTERP, NULL, ILL_INHERIT,
593                 "attempt to get length of a %Ss value", SELF.name());
595         retval = Parrot_runops_fromc_args(INTERP, meth, "PP", SELF);
597         if (PMC_IS_NULL(retval))
598             retval = pmc_new(INTERP, dynpmc_LuaNil);
600         RETURN(PMC *retval);
601     }
605 =item C<PMC* tonumber()>
607 Returns C<nil>.
609 =cut
612     METHOD PMC* tonumber() {
613         PMC *nil = pmc_new(INTERP, dynpmc_LuaNil);
614         RETURN(PMC *nil);
615     }
619 =item C<PMC* tostring()>
621 Return a Lua C<string>.
623 Common implementation (use C<__tostring> or C<get_string>).
625 =cut
628     METHOD PMC* tostring() {
629         PMC *meth = find_meth(INTERP, SELF, "__tostring");
630         PMC *retval;
632         if (meth) {
633             retval = Parrot_runops_fromc_args(INTERP, meth, "PP", SELF);
635             if (PMC_IS_NULL(retval))
636                 retval = pmc_new(INTERP, dynpmc_LuaNil);
637         }
638         else {
639             retval = pmc_new(INTERP, dynpmc_LuaString);
640             VTABLE_set_string_native(INTERP, retval, SELF.get_string());
641         }
643         RETURN(PMC *retval);
644     }
649 =back
651 =head1 AUTHORS
653 Francois Perrad.
655 =cut
661  * Local variables:
662  *   c-file-style: "parrot"
663  * End:
664  * vim: expandtab shiftwidth=4:
665  */