~ubuntu-branches/ubuntu/wily/gargoyle-free/wily-proposed

« back to all changes in this revision

Viewing changes to tads/tads3/lib/reflect.t

  • Committer: Bazaar Package Importer
  • Author(s): Sylvain Beucler
  • Date: 2009-09-11 20:09:43 UTC
  • Revision ID: james.westby@ubuntu.com-20090911200943-idgzoyupq6650zpn
Tags: upstream-2009-08-25
ImportĀ upstreamĀ versionĀ 2009-08-25

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#charset "us-ascii"
 
2
 
 
3
/* 
 
4
 *   Copyright (c) 2000, 2006 Michael J. Roberts
 
5
 *   
 
6
 *   This file is part of TADS 3.  
 
7
 */
 
8
 
 
9
#include "tads.h"
 
10
#include "reflect.h"
 
11
 
 
12
/* ------------------------------------------------------------------------ */
 
13
/*
 
14
 *   Main reflection services object.
 
15
 *   
 
16
 *   During pre-initialization, we'll plug this into the _main module's
 
17
 *   globals so that the _main module will know it can use reflection
 
18
 *   services.  
 
19
 */
 
20
reflectionServices: PreinitObject
 
21
    /* execute preinitialization */
 
22
    execute()
 
23
    {
 
24
        /* plug ourselves into the main globals */
 
25
        mainGlobal.reflectionObj = self;
 
26
 
 
27
        /* store the main symbol table */
 
28
        symtab_ = t3GetGlobalSymbols();
 
29
 
 
30
        /* create a reverse lookup table from the main symbol table */
 
31
        if (symtab_ != nil)
 
32
        {
 
33
            /* 
 
34
             *   create a lookup table for the reverse table - it'll be
 
35
             *   the same size as the original table, so create it using
 
36
             *   the same statistics 
 
37
             */
 
38
            reverseSymtab_ = new LookupTable(symtab_.getBucketCount(),
 
39
                                             symtab_.getEntryCount());
 
40
 
 
41
            /* 
 
42
             *   for each entry in the main table, create an entry in the
 
43
             *   reverse table with the role of key and value reversed -
 
44
             *   this will allow us to look up any value and find its
 
45
             *   global symbol, if it has one 
 
46
             */
 
47
            symtab_.forEachAssoc({key, val: reverseSymtab_[val] = key});
 
48
        }
 
49
    }
 
50
 
 
51
    /*
 
52
     *   Convert a value to a symbol, or to a string representation if
 
53
     *   it's not of a symbolic type.  
 
54
     */
 
55
    valToSymbol(val)
 
56
    {
 
57
        local sym;
 
58
        
 
59
        /* the representation depends on the type */
 
60
        switch(dataType(val))
 
61
        {
 
62
        case TypeNil:
 
63
            return 'nil';
 
64
 
 
65
        case TypeTrue:
 
66
            return 'true';
 
67
 
 
68
        case TypeInt:
 
69
            return toString(val);
 
70
 
 
71
        case TypeSString:
 
72
        case TypeList:
 
73
        case TypeObject:
 
74
            /* 
 
75
             *   If we're asking about 'self', inherit the handling.  Note
 
76
             *   that, for any object type, x.ofKind(x) is always true, so
 
77
             *   there's no need for a separate test to see if val equals
 
78
             *   self.  
 
79
             */
 
80
            if (val.ofKind(self))
 
81
                return inherited();
 
82
 
 
83
            /* use our special value-to-symbol method on the object itself */
 
84
            return val.valToSymbol();
 
85
            
 
86
        case TypeProp:
 
87
            /* 
 
88
             *   this should usually convert to a symbol, but might have
 
89
             *   been allocated dynamically 
 
90
             */
 
91
            sym = reverseSymtab_[val];
 
92
            return (sym != nil ? sym : '(prop)');
 
93
 
 
94
        case TypeFuncPtr:
 
95
        case TypeEnum:
 
96
            /* these should always convert directly to symbols */
 
97
            sym = reverseSymtab_[val];
 
98
            return (sym != nil ? sym : '???');
 
99
 
 
100
        case TypeNativeCode:
 
101
            return '(native code)';
 
102
 
 
103
        default:
 
104
            return '???';
 
105
        }
 
106
    }
 
107
 
 
108
    /*
 
109
     *   Format a stack frame object (of class T3StackInfo). 
 
110
     */
 
111
    formatStackFrame(fr, includeSourcePos)
 
112
    {
 
113
        local ret;
 
114
        
 
115
        /* see what kind of frame we have */
 
116
        if (fr.func_ != nil)
 
117
        {
 
118
            /* it's a function */
 
119
            ret = valToSymbol(fr.func_);
 
120
        }
 
121
        else if (fr.obj_ != nil)
 
122
        {
 
123
            /* 
 
124
             *   It's an object.property.  Check for one special case we
 
125
             *   want to show specially: if the object is an AnonFuncPtr
 
126
             *   object, ignore the property and just show it as an
 
127
             *   anonymous function. 
 
128
             */
 
129
            if (fr.obj_.ofKind(AnonFuncPtr))
 
130
                ret = '{anonFunc}';
 
131
            else
 
132
                ret = valToSymbol(fr.self_) + '.' + valToSymbol(fr.prop_);
 
133
        }
 
134
        else
 
135
        {
 
136
            /* no function or object - must be a system routine */
 
137
            ret = '(System)';
 
138
        }
 
139
 
 
140
        /* if it's not a system routine, add the argument list */
 
141
        if (!fr.isSystem())
 
142
        {
 
143
            /* add the open paren */
 
144
            ret += '(';
 
145
 
 
146
            /* add the arguments */
 
147
            for (local i = 1, local len = fr.argList_.length() ;
 
148
                 i <= len ; ++i)
 
149
            {
 
150
                /* if it's not the first one, add a comma */
 
151
                if (i != 1)
 
152
                    ret += ', ';
 
153
 
 
154
                /* add this value */
 
155
                ret += valToSymbol(fr.argList_[i]);
 
156
            }
 
157
 
 
158
            /* add the close paren */
 
159
            ret += ')';
 
160
 
 
161
            /* if desired, add the source location */
 
162
            if (includeSourcePos && fr.srcInfo_ != nil)
 
163
                ret += ' ' + fr.srcInfo_[1] + ', line ' + fr.srcInfo_[2];
 
164
        }
 
165
 
 
166
        /* return the result */
 
167
        return ret;
 
168
    }
 
169
 
 
170
    /* the global symbol table */
 
171
    symtab_ = nil
 
172
 
 
173
    /* the global reverse-lookup symbol table */
 
174
    reverseSymtab_ = nil
 
175
;
 
176
 
 
177
/* ------------------------------------------------------------------------ */
 
178
/*
 
179
 *   Modify the basic Object class to provide a to-symbol mapping
 
180
 */
 
181
modify Object
 
182
    valToSymbol()
 
183
    {
 
184
        local sym;
 
185
        local found;
 
186
        
 
187
        /* get my symbol from the global reflection table */
 
188
        sym = reflectionServices.reverseSymtab_[self];
 
189
 
 
190
        /* if we got a symbol, return it */
 
191
        if (sym != nil)
 
192
            return sym;
 
193
 
 
194
        /* 
 
195
         *   We didn't get a symbol, so there's no source file name.  See
 
196
         *   if we can find source-file names for the superclasses, though.
 
197
         */
 
198
        sym = '(obj:';
 
199
        found = nil;
 
200
        foreach (local sc in getSuperclassList())
 
201
        {
 
202
            local scSym;
 
203
 
 
204
            /* add a comma to the list if this isn't the first element */
 
205
            if (sym != '(obj:')
 
206
                sym += ',';
 
207
                
 
208
            /* if we have a name here, add it to the list */
 
209
            if ((scSym = reflectionServices.reverseSymtab_[sc]) != nil)
 
210
            {
 
211
                /* note that we found a named superclass */
 
212
                found = true;
 
213
 
 
214
                /* add the superclass name to the list */
 
215
                sym += scSym;
 
216
            }
 
217
            else
 
218
            {
 
219
                /* we don't have a name for this superclass; say so */
 
220
                sym += '(anonymous)';
 
221
            }
 
222
        }
 
223
 
 
224
        /* 
 
225
         *   if we found any named superclasses, return the list of names;
 
226
         *   otherwise, just say (obj) 
 
227
         */
 
228
        return (found ? sym + ')' : '(obj)');
 
229
    }
 
230
;
 
231
 
 
232
/* ------------------------------------------------------------------------ */
 
233
/*
 
234
 *   Modify the String intrinsic class to provide a to-symbol mapping 
 
235
 */
 
236
modify String
 
237
    valToSymbol()
 
238
    {
 
239
        local ret;
 
240
        local i;
 
241
        local start;
 
242
        
 
243
        /* start with an open quote */
 
244
        ret = '\'';
 
245
 
 
246
        /* loop through the string to find each special character */
 
247
        for (i = 1, local len = length(), start = 1 ;
 
248
             i <= len ; ++i)
 
249
        {
 
250
            local qu;
 
251
 
 
252
            /* presume we won't add a quoted character on this round */
 
253
            qu = nil;
 
254
            
 
255
            /* see what we have here */
 
256
            switch(substr(i, 1))
 
257
            {
 
258
            case '\\':
 
259
                qu = '\\\\';
 
260
                break;
 
261
                
 
262
            case '\'':
 
263
                qu = '\\\'';
 
264
                break;
 
265
 
 
266
            case '\n':
 
267
                qu = '\\n';
 
268
                break;
 
269
 
 
270
            case '\t':
 
271
                qu = '\\t';
 
272
                break;
 
273
 
 
274
            case '\b':
 
275
                qu = '\\b';
 
276
                break;
 
277
 
 
278
            case '\ ':
 
279
                qu = '\\ ';
 
280
                break;
 
281
 
 
282
            case '\^':
 
283
                qu = '\\^';
 
284
                break;
 
285
 
 
286
            case '\v':
 
287
                qu = '\\v';
 
288
                break;
 
289
            }
 
290
 
 
291
            /* 
 
292
             *   if we have a quoted character, add the part up to the
 
293
             *   quoted character plus the quoted character 
 
294
             */
 
295
            if (qu != nil)
 
296
            {
 
297
                /* add the part up to here but not including this char */
 
298
                if (i != start)
 
299
                    ret += substr(start, i - start);
 
300
 
 
301
                /* add the quoted form of the character */
 
302
                ret += qu;
 
303
 
 
304
                /* start again after this character */
 
305
                start = i + 1;
 
306
            }
 
307
        }
 
308
 
 
309
        /* add the trailing unquoted part if we haven't already */
 
310
        if (i != start)
 
311
            ret += substr(start, i - start);
 
312
 
 
313
        /* add a close quote and return the result */
 
314
        return ret + '\'';
 
315
    }
 
316
;
 
317
 
 
318
/* ------------------------------------------------------------------------ */
 
319
/*
 
320
 *   Modify the List intrinsic class to provide a to-symbol mapping 
 
321
 */
 
322
modify List
 
323
    valToSymbol()
 
324
    {
 
325
        local ret;
 
326
        
 
327
        /* start off with an open bracket */
 
328
        ret = '[';
 
329
 
 
330
        /* convert each element to symbolic form */
 
331
        for (local i = 1, local len = length() ; i <= len ; ++i)
 
332
        {
 
333
            /* add a comma if this isn't the first element */
 
334
            if (i != 1)
 
335
                ret += ', ';
 
336
 
 
337
            /* add this element converted to symbolic form */
 
338
            ret += reflectionServices.valToSymbol(self[i]);
 
339
        }
 
340
 
 
341
        /* add the close bracket and return the result */
 
342
        return ret + ']';
 
343
    }
 
344
;
 
345
 
 
346
 
 
347
/* ------------------------------------------------------------------------ */
 
348
/*
 
349
 *   If desired, modify the BigNumber intrinsic class to provide a
 
350
 *   to-symbol mapping.  We only include this modification if the program
 
351
 *   is compiled with REFLECT_BIGNUM defined.  
 
352
 */
 
353
#ifdef REFLECT_BIGNUM
 
354
#include "bignum.h"
 
355
 
 
356
modify BigNumber
 
357
    valToSymbol()
 
358
    {
 
359
        /* use the default formatting */
 
360
        return formatString(12);
 
361
    }
 
362
;
 
363
 
 
364
#endif /* REFLECT_BIGNUM */