-
Notifications
You must be signed in to change notification settings - Fork 17
/
vmanonfn.cpp
119 lines (98 loc) · 2.75 KB
/
vmanonfn.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#ifdef RCSID
static char RCSid[] =
"$Header$";
#endif
/*
* Copyright (c) 2000, 2002 Michael J. Roberts. All Rights Reserved.
*
* Please see the accompanying license file, LICENSE.TXT, for information
* on using and copying this software.
*/
/*
Name
vmanonfn.cpp - anonymous function metaclass
Function
Notes
Modified
03/21/00 MJRoberts - Creation
*/
#include "t3std.h"
#include "vmobj.h"
#include "vmanonfn.h"
#include "vmerr.h"
#include "vmerrnum.h"
#include "vmrun.h"
#include "vmstack.h"
#include "vmpredef.h"
/* ------------------------------------------------------------------------ */
/*
* Statics
*/
/* metaclass registration object */
static CVmMetaclassAnonFn metaclass_reg_obj;
CVmMetaclass *CVmObjAnonFn::metaclass_reg_ = &metaclass_reg_obj;
/* ------------------------------------------------------------------------ */
/*
* create from stack arguments
*/
vm_obj_id_t CVmObjAnonFn::create_from_stack(VMG_ const uchar **pc_ptr,
uint argc)
{
vm_obj_id_t id;
vm_val_t funcptr;
CVmObjAnonFn *new_obj;
uint idx;
/* at least one argument is required (the function pointer) */
if (argc < 1)
err_throw(VMERR_WRONG_NUM_OF_ARGS);
/* retrieve our function pointer argument */
G_stk->pop(&funcptr);
if (funcptr.typ == VM_FUNCPTR)
{
/* it's a regular function pointer - accept it */
}
else if (funcptr.typ == VM_OBJ
&& vm_objp(vmg_ funcptr.val.obj)->get_invoker(vmg_ 0))
{
/* it's a pointer to an invokable object - accept it */
}
else
{
/* it's not a valid function pointer */
err_throw(VMERR_FUNCPTR_VAL_REQD);
}
/* create the new object */
id = vm_new_id(vmg_ FALSE, TRUE, FALSE);
/* create the new object, giving it one slot per constructor argument */
new_obj = new (vmg_ id) CVmObjAnonFn(vmg_ argc);
/* set the first element to our function pointer */
new_obj->set_element(0, &funcptr);
/* set the remaining elements to the context objects */
for (idx = 1 ; idx < argc ; ++idx)
{
vm_val_t val;
/* pop this value */
G_stk->pop(&val);
/* set the element */
new_obj->set_element(idx, &val);
}
/* return the new object ID */
return id;
}
/*
* Invoke
*/
int CVmObjAnonFn::get_invoker(VMG_ vm_val_t *val)
{
/* our first vector element is our function pointer */
if (val != 0)
{
/* get the function pointer */
get_element(0, val);
/* if this is itself an invokable value, get its invoker */
if (val->typ == VM_OBJ)
return vm_objp(vmg_ val->val.obj)->get_invoker(vmg_ val);
}
/* we are indeed invokable */
return TRUE;
}