cfad47cfa3/t3compiler/tads3/test/data/fi_util.h

4b825dc642cb6eb9a060e54bf8d69288fbee4904cfad47cfa334b206c65f22086bcc5d63e6f70944
1
#if defined( FINCH_DEBUG_COMPILE )
2
#error entering fi_util.t...
3
#endif
4
5
#if !defined( FINCH_UTILITY_LIBRARY )
6
7
#include "tads.h"
8
#include "t3.h"
9
#include "lookup.h"
10
11
modify TadsObject
12
    _name = nil
13
14
    _init_TadsObject() {}
15
16
    construct() {
17
        _init_();
18
    }
19
20
    _init_( [args] ) {
21
        if (self == TadsObject) return;
22
23
        local obj = (args.length > 0 ? args[1] : self);
24
25
        local lst = getSuperclassList();
26
        foreach (local c in lst)
27
            c._init_( obj );
28
29
        callDefinedMethod( obj, '_init_' + self._name );
30
    }
31
;
32
33
/**
34
 *  Permits the Finch utilities by saving the global symbol hashtable
35
 *  before it gets garbage-collected after preinit.
36
 */
37
FinchUtility: PreinitObject
38
    globalSymbols = nil
39
40
    storeGlobalSymbols = true
41
42
    execute() {
43
        globalSymbols = t3GetGlobalSymbols();
44
45
        t3DebugTrace( T3DebugBreak );
46
47
        globalSymbols.forEach(
48
            { tok, obj :
49
                dataType( obj ) == TypeObject &&
50
                obj.ofKind( TadsObject )
51
                    ? obj._name = tok
52
                    : nil
53
            }
54
        );
55
56
        for (local o = firstObj(); o; o = nextObj( o )) {
57
            if (o.ofKind( TadsObject)) {
58
                o._init_();
59
            }
60
        }
61
    }
62
;
63
64
/**
65
 *  Retrieves the global symbol hashtable, saved by the FinchUtility
66
 *  PreinitObject.
67
 */
68
getGlobalSymbols() {
69
    return FinchUtility.globalSymbols;
70
}
71
72
/**
73
 *  Calls the given method-name on the given object using the given
74
 *  argument list.
75
 *
76
 *  @param  obj     an object reference
77
 *  @param  meth    a string containing a valid property name
78
 *  @param  params  all following parameters will be passed sequentially
79
 *                  to the method
80
 *  @return         whatever the method returned
81
 *  @exception  NoSuchSymbolException if the method name can't be found in
82
 *                  the global symbol table
83
 *  @exception  NoSuchMethodException if the associated entry in the
84
 *                  global symbol table isn't a property
85
 *  @exception  InvocationTargetException if the method itself threw an
86
 *                  exception.
87
 */
88
callMethod( obj, meth, [params] ) {
89
90
    //  get the actual method reference from the symbol table
91
    local prop = (getGlobalSymbols())[ meth ];
92
93
    //  if the symbol doesn't exist, throw an exception
94
    if (prop == nil)
95
        throw new NoSuchSymbolException( meth );
96
97
    //  if the symbol isn't a property, throw an exception
98
    else if (dataType( prop ) != TypeProp)
99
        throw new NoSuchMethodException( meth );
100
101
    else {
102
        try {
103
            return obj.(prop)( params... );
104
        }
105
        catch (Exception e) {
106
            throw new InvocationTargetException( obj, meth, e );
107
        }
108
    }
109
}
110
111
/**
112
 *  Calls the given method-name on the given object using the given
113
 *  argument list.  If the method does not exist, or exists but isn't
114
 *  defined on this object, ignore it (instead of, say, trying to call
115
 *  a method that we know won't ever be valid, since code can never be
116
 *  assigned to a method in the current implementation of the VM).
117
 *
118
 *  @param  obj     an object reference
119
 *  @param  meth    a string containing a valid property name
120
 *  @param  params  all following parameters will be passed sequentially
121
 *                  to the method
122
 *  @return         whatever the method returned
123
 *  @exception  NoSuchMethodException if the associated entry in the
124
 *                  global symbol table isn't a property
125
 *  @exception  InvocationTargetException if the method itself threw an
126
 *                  exception.
127
 */
128
callDefinedMethod( obj, meth, [params] ) {
129
130
    // get the actual method reference from the symbol table
131
    local prop = (getGlobalSymbols())[ meth ];
132
133
    // if the symbol doesn't exist, abort.
134
    if (prop == nil) return nil;
135
136
    // if the property isn't defined by this object, abort.
137
    if (!obj.propDefined( prop )) return nil;
138
139
    // if the symbol isn't a property, throw an exception
140
    else if (dataType( prop ) != TypeProp)
141
        throw new NoSuchMethodException( meth );
142
143
    else {
144
        try {
145
            return obj.(prop)( params... );
146
        }
147
        catch (Exception e) {
148
            throw new InvocationTargetException( obj, meth, e );
149
        }
150
    }
151
}
152
153
/**
154
 *  Creates a new property, updating the global symbol table.
155
 *
156
 *  @param  str     a string to correspond to the new property
157
 *  @return         the new property
158
 */
159
createGlobalProperty( str ) {
160
161
    // allocate a new property id
162
    local prop = t3AllocProp();
163
164
    // assign it to the given string
165
    (getGlobalSymbols())[ str ] = prop;
166
167
    // return the new property
168
    return prop;
169
}
170
171
/**
172
 *  A nearly meta-exception thrown when reflectively invoked code
173
 *  throws an exception.
174
 */
175
class InvocationTargetException: Exception
176
    location = nil
177
    position = nil
178
    datum = nil
179
180
    construct( obj, meth, e ) {
181
        location = obj;
182
        position = meth;
183
        datum = e;
184
    }
185
186
    getMessage() {
187
        "InvocationTargetException: the method << position >>
188
        on the object << location._name >> threw the following
189
        exception: << datum.getMessage() >>. ";
190
    }
191
;
192
193
/**
194
 *  An exception thrown when a reflectively invoked method
195
 *  does't actually exist.
196
 */
197
class NoSuchMethodException: Exception
198
    position = nil
199
200
    construct( meth ) {
201
        position = meth;
202
    }
203
204
    getMessage() {
205
        "NoSuchMethodException: the symbol << position >>
206
        does not correspond to a property address.";
207
    }
208
;
209
210
/**
211
 *  An exception thrown when a reflectively requested symbol
212
 *  does't actually exist.
213
 */
214
class NoSuchSymbolException: Exception
215
    position = nil
216
217
    construct( sym ) {
218
        position = sym;
219
    }
220
221
    getMessage() {
222
        "NoSuchSymbolException: the symbol << position >>
223
        does not exist in the global symbols table.";
224
    }
225
;
226
227
#endif
228