python-on-a-chip online compiler

Dependencies:   mbed TSI

/media/uploads/va009039/p14p-f446re.png

more info: python-on-a-chip

Committer:
va009039
Date:
Sat Mar 02 11:54:20 2013 +0000
Revision:
0:65f1469d6bfb
Child:
1:28afb064a41c
first commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
va009039 0:65f1469d6bfb 1 /*
va009039 0:65f1469d6bfb 2 # This file is Copyright 2002 Dean Hall.
va009039 0:65f1469d6bfb 3 # This file is part of the PyMite VM.
va009039 0:65f1469d6bfb 4 # This file is licensed under the MIT License.
va009039 0:65f1469d6bfb 5 # See the LICENSE file for details.
va009039 0:65f1469d6bfb 6 */
va009039 0:65f1469d6bfb 7
va009039 0:65f1469d6bfb 8
va009039 0:65f1469d6bfb 9 #undef __FILE_ID__
va009039 0:65f1469d6bfb 10 #define __FILE_ID__ 0x09
va009039 0:65f1469d6bfb 11
va009039 0:65f1469d6bfb 12
va009039 0:65f1469d6bfb 13 /**
va009039 0:65f1469d6bfb 14 * \file
va009039 0:65f1469d6bfb 15 * \brief VM Interpreter
va009039 0:65f1469d6bfb 16 *
va009039 0:65f1469d6bfb 17 * VM interpreter operations.
va009039 0:65f1469d6bfb 18 */
va009039 0:65f1469d6bfb 19
va009039 0:65f1469d6bfb 20
va009039 0:65f1469d6bfb 21 #include "pm.h"
va009039 0:65f1469d6bfb 22
va009039 0:65f1469d6bfb 23
va009039 0:65f1469d6bfb 24 PmReturn_t
va009039 0:65f1469d6bfb 25 interpret(const uint8_t returnOnNoThreads)
va009039 0:65f1469d6bfb 26 {
va009039 0:65f1469d6bfb 27 PmReturn_t retval = PM_RET_OK;
va009039 0:65f1469d6bfb 28 pPmObj_t pobj1 = C_NULL;
va009039 0:65f1469d6bfb 29 pPmObj_t pobj2 = C_NULL;
va009039 0:65f1469d6bfb 30 pPmObj_t pobj3 = C_NULL;
va009039 0:65f1469d6bfb 31 int16_t t16 = 0;
va009039 0:65f1469d6bfb 32 int8_t t8 = 0;
va009039 0:65f1469d6bfb 33 uint8_t bc;
va009039 0:65f1469d6bfb 34 uint8_t objid, objid2;
va009039 0:65f1469d6bfb 35
va009039 0:65f1469d6bfb 36 /* Activate a thread the first time */
va009039 0:65f1469d6bfb 37 retval = interp_reschedule();
va009039 0:65f1469d6bfb 38 PM_RETURN_IF_ERROR(retval);
va009039 0:65f1469d6bfb 39
va009039 0:65f1469d6bfb 40 /* Interpret loop */
va009039 0:65f1469d6bfb 41 for (;;)
va009039 0:65f1469d6bfb 42 {
va009039 0:65f1469d6bfb 43 if (gVmGlobal.pthread == C_NULL)
va009039 0:65f1469d6bfb 44 {
va009039 0:65f1469d6bfb 45 if (returnOnNoThreads)
va009039 0:65f1469d6bfb 46 {
va009039 0:65f1469d6bfb 47 /* User chose to return on no threads left */
va009039 0:65f1469d6bfb 48 return retval;
va009039 0:65f1469d6bfb 49 }
va009039 0:65f1469d6bfb 50
va009039 0:65f1469d6bfb 51 /*
va009039 0:65f1469d6bfb 52 * Without a frame there is nothing to execute, so reschedule
va009039 0:65f1469d6bfb 53 * (possibly activating a recently added thread).
va009039 0:65f1469d6bfb 54 */
va009039 0:65f1469d6bfb 55 retval = interp_reschedule();
va009039 0:65f1469d6bfb 56 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 57 continue;
va009039 0:65f1469d6bfb 58 }
va009039 0:65f1469d6bfb 59
va009039 0:65f1469d6bfb 60 /* Reschedule threads if flag is true? */
va009039 0:65f1469d6bfb 61 if (gVmGlobal.reschedule)
va009039 0:65f1469d6bfb 62 {
va009039 0:65f1469d6bfb 63 retval = interp_reschedule();
va009039 0:65f1469d6bfb 64 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 65 }
va009039 0:65f1469d6bfb 66
va009039 0:65f1469d6bfb 67 /* Get byte; the func post-incrs PM_IP */
va009039 0:65f1469d6bfb 68 bc = mem_getByte(PM_FP->fo_memspace, &PM_IP);
va009039 0:65f1469d6bfb 69 switch (bc)
va009039 0:65f1469d6bfb 70 {
va009039 0:65f1469d6bfb 71 case POP_TOP:
va009039 0:65f1469d6bfb 72 pobj1 = PM_POP();
va009039 0:65f1469d6bfb 73 continue;
va009039 0:65f1469d6bfb 74
va009039 0:65f1469d6bfb 75 case ROT_TWO:
va009039 0:65f1469d6bfb 76 pobj1 = TOS;
va009039 0:65f1469d6bfb 77 TOS = TOS1;
va009039 0:65f1469d6bfb 78 TOS1 = pobj1;
va009039 0:65f1469d6bfb 79 continue;
va009039 0:65f1469d6bfb 80
va009039 0:65f1469d6bfb 81 case ROT_THREE:
va009039 0:65f1469d6bfb 82 pobj1 = TOS;
va009039 0:65f1469d6bfb 83 TOS = TOS1;
va009039 0:65f1469d6bfb 84 TOS1 = TOS2;
va009039 0:65f1469d6bfb 85 TOS2 = pobj1;
va009039 0:65f1469d6bfb 86 continue;
va009039 0:65f1469d6bfb 87
va009039 0:65f1469d6bfb 88 case DUP_TOP:
va009039 0:65f1469d6bfb 89 pobj1 = TOS;
va009039 0:65f1469d6bfb 90 PM_PUSH(pobj1);
va009039 0:65f1469d6bfb 91 continue;
va009039 0:65f1469d6bfb 92
va009039 0:65f1469d6bfb 93 case ROT_FOUR:
va009039 0:65f1469d6bfb 94 pobj1 = TOS;
va009039 0:65f1469d6bfb 95 TOS = TOS1;
va009039 0:65f1469d6bfb 96 TOS1 = TOS2;
va009039 0:65f1469d6bfb 97 TOS2 = TOS3;
va009039 0:65f1469d6bfb 98 TOS3 = pobj1;
va009039 0:65f1469d6bfb 99 continue;
va009039 0:65f1469d6bfb 100
va009039 0:65f1469d6bfb 101 case NOP:
va009039 0:65f1469d6bfb 102 continue;
va009039 0:65f1469d6bfb 103
va009039 0:65f1469d6bfb 104 case UNARY_POSITIVE:
va009039 0:65f1469d6bfb 105 /* Raise TypeError if TOS is not an int */
va009039 0:65f1469d6bfb 106 if ((OBJ_GET_TYPE(TOS) != OBJ_TYPE_INT)
va009039 0:65f1469d6bfb 107 #ifdef HAVE_FLOAT
va009039 0:65f1469d6bfb 108 && (OBJ_GET_TYPE(TOS) != OBJ_TYPE_FLT)
va009039 0:65f1469d6bfb 109 #endif /* HAVE_FLOAT */
va009039 0:65f1469d6bfb 110 )
va009039 0:65f1469d6bfb 111 {
va009039 0:65f1469d6bfb 112 PM_RAISE(retval, PM_RET_EX_TYPE);
va009039 0:65f1469d6bfb 113 break;
va009039 0:65f1469d6bfb 114 }
va009039 0:65f1469d6bfb 115
va009039 0:65f1469d6bfb 116 /* When TOS is an int, this is a no-op */
va009039 0:65f1469d6bfb 117 continue;
va009039 0:65f1469d6bfb 118
va009039 0:65f1469d6bfb 119 case UNARY_NEGATIVE:
va009039 0:65f1469d6bfb 120 #ifdef HAVE_FLOAT
va009039 0:65f1469d6bfb 121 if (OBJ_GET_TYPE(TOS) == OBJ_TYPE_FLT)
va009039 0:65f1469d6bfb 122 {
va009039 0:65f1469d6bfb 123 retval = float_negative(TOS, &pobj2);
va009039 0:65f1469d6bfb 124 }
va009039 0:65f1469d6bfb 125 else
va009039 0:65f1469d6bfb 126 #endif /* HAVE_FLOAT */
va009039 0:65f1469d6bfb 127 {
va009039 0:65f1469d6bfb 128 retval = int_negative(TOS, &pobj2);
va009039 0:65f1469d6bfb 129 }
va009039 0:65f1469d6bfb 130 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 131 TOS = pobj2;
va009039 0:65f1469d6bfb 132 continue;
va009039 0:65f1469d6bfb 133
va009039 0:65f1469d6bfb 134 case UNARY_NOT:
va009039 0:65f1469d6bfb 135 pobj1 = PM_POP();
va009039 0:65f1469d6bfb 136 if (obj_isFalse(pobj1))
va009039 0:65f1469d6bfb 137 {
va009039 0:65f1469d6bfb 138 PM_PUSH(PM_TRUE);
va009039 0:65f1469d6bfb 139 }
va009039 0:65f1469d6bfb 140 else
va009039 0:65f1469d6bfb 141 {
va009039 0:65f1469d6bfb 142 PM_PUSH(PM_FALSE);
va009039 0:65f1469d6bfb 143 }
va009039 0:65f1469d6bfb 144 continue;
va009039 0:65f1469d6bfb 145
va009039 0:65f1469d6bfb 146 #ifdef HAVE_BACKTICK
va009039 0:65f1469d6bfb 147 /* #244 Add support for the backtick operation (UNARY_CONVERT) */
va009039 0:65f1469d6bfb 148 case UNARY_CONVERT:
va009039 0:65f1469d6bfb 149 retval = obj_repr(TOS, &pobj3);
va009039 0:65f1469d6bfb 150 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 151 TOS = pobj3;
va009039 0:65f1469d6bfb 152 continue;
va009039 0:65f1469d6bfb 153 #endif /* HAVE_BACKTICK */
va009039 0:65f1469d6bfb 154
va009039 0:65f1469d6bfb 155 case UNARY_INVERT:
va009039 0:65f1469d6bfb 156 /* Raise TypeError if it's not an int */
va009039 0:65f1469d6bfb 157 if (OBJ_GET_TYPE(TOS) != OBJ_TYPE_INT)
va009039 0:65f1469d6bfb 158 {
va009039 0:65f1469d6bfb 159 PM_RAISE(retval, PM_RET_EX_TYPE);
va009039 0:65f1469d6bfb 160 break;
va009039 0:65f1469d6bfb 161 }
va009039 0:65f1469d6bfb 162
va009039 0:65f1469d6bfb 163 /* Otherwise perform bit-wise complement */
va009039 0:65f1469d6bfb 164 retval = int_bitInvert(TOS, &pobj2);
va009039 0:65f1469d6bfb 165 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 166 TOS = pobj2;
va009039 0:65f1469d6bfb 167 continue;
va009039 0:65f1469d6bfb 168
va009039 0:65f1469d6bfb 169 case LIST_APPEND:
va009039 0:65f1469d6bfb 170 /* list_append will raise a TypeError if TOS1 is not a list */
va009039 0:65f1469d6bfb 171 retval = list_append(TOS1, TOS);
va009039 0:65f1469d6bfb 172 PM_SP -= 2;
va009039 0:65f1469d6bfb 173 continue;
va009039 0:65f1469d6bfb 174
va009039 0:65f1469d6bfb 175 case BINARY_POWER:
va009039 0:65f1469d6bfb 176 case INPLACE_POWER:
va009039 0:65f1469d6bfb 177
va009039 0:65f1469d6bfb 178 #ifdef HAVE_FLOAT
va009039 0:65f1469d6bfb 179 if ((OBJ_GET_TYPE(TOS) == OBJ_TYPE_FLT)
va009039 0:65f1469d6bfb 180 || (OBJ_GET_TYPE(TOS1) == OBJ_TYPE_FLT))
va009039 0:65f1469d6bfb 181 {
va009039 0:65f1469d6bfb 182 /* Calculate float power */
va009039 0:65f1469d6bfb 183 retval = float_op(TOS1, TOS, &pobj3, 'P');
va009039 0:65f1469d6bfb 184 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 185 PM_SP--;
va009039 0:65f1469d6bfb 186 TOS = pobj3;
va009039 0:65f1469d6bfb 187 continue;
va009039 0:65f1469d6bfb 188 }
va009039 0:65f1469d6bfb 189 #endif /* HAVE_FLOAT */
va009039 0:65f1469d6bfb 190
va009039 0:65f1469d6bfb 191 /* Calculate integer power */
va009039 0:65f1469d6bfb 192 retval = int_pow(TOS1, TOS, &pobj3);
va009039 0:65f1469d6bfb 193 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 194
va009039 0:65f1469d6bfb 195 /* Set return value */
va009039 0:65f1469d6bfb 196 PM_SP--;
va009039 0:65f1469d6bfb 197 TOS = pobj3;
va009039 0:65f1469d6bfb 198 continue;
va009039 0:65f1469d6bfb 199
va009039 0:65f1469d6bfb 200 case GET_ITER:
va009039 0:65f1469d6bfb 201 #ifdef HAVE_GENERATORS
va009039 0:65f1469d6bfb 202 /* Raise TypeError if TOS is an instance, but not iterable */
va009039 0:65f1469d6bfb 203 if (OBJ_GET_TYPE(TOS) == OBJ_TYPE_CLI)
va009039 0:65f1469d6bfb 204 {
va009039 0:65f1469d6bfb 205 retval = class_getAttr(TOS, PM_NEXT_STR, &pobj1);
va009039 0:65f1469d6bfb 206 if (retval != PM_RET_OK)
va009039 0:65f1469d6bfb 207 {
va009039 0:65f1469d6bfb 208 PM_RAISE(retval, PM_RET_EX_TYPE);
va009039 0:65f1469d6bfb 209 break;
va009039 0:65f1469d6bfb 210 }
va009039 0:65f1469d6bfb 211 }
va009039 0:65f1469d6bfb 212 else
va009039 0:65f1469d6bfb 213 #endif /* HAVE_GENERATORS */
va009039 0:65f1469d6bfb 214 {
va009039 0:65f1469d6bfb 215 /* Convert sequence to sequence-iterator */
va009039 0:65f1469d6bfb 216 retval = seqiter_new(TOS, &pobj1);
va009039 0:65f1469d6bfb 217 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 218
va009039 0:65f1469d6bfb 219 /* Put sequence-iterator on top of stack */
va009039 0:65f1469d6bfb 220 TOS = pobj1;
va009039 0:65f1469d6bfb 221 }
va009039 0:65f1469d6bfb 222 continue;
va009039 0:65f1469d6bfb 223
va009039 0:65f1469d6bfb 224 case BINARY_MULTIPLY:
va009039 0:65f1469d6bfb 225 case INPLACE_MULTIPLY:
va009039 0:65f1469d6bfb 226 /* If both objs are ints, perform the op */
va009039 0:65f1469d6bfb 227 if ((OBJ_GET_TYPE(TOS) == OBJ_TYPE_INT)
va009039 0:65f1469d6bfb 228 && (OBJ_GET_TYPE(TOS1) == OBJ_TYPE_INT))
va009039 0:65f1469d6bfb 229 {
va009039 0:65f1469d6bfb 230 retval = int_new(((pPmInt_t)TOS1)->val *
va009039 0:65f1469d6bfb 231 ((pPmInt_t)TOS)->val, &pobj3);
va009039 0:65f1469d6bfb 232 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 233 PM_SP--;
va009039 0:65f1469d6bfb 234 TOS = pobj3;
va009039 0:65f1469d6bfb 235 continue;
va009039 0:65f1469d6bfb 236 }
va009039 0:65f1469d6bfb 237
va009039 0:65f1469d6bfb 238 #ifdef HAVE_FLOAT
va009039 0:65f1469d6bfb 239 else if ((OBJ_GET_TYPE(TOS) == OBJ_TYPE_FLT)
va009039 0:65f1469d6bfb 240 || (OBJ_GET_TYPE(TOS1) == OBJ_TYPE_FLT))
va009039 0:65f1469d6bfb 241 {
va009039 0:65f1469d6bfb 242 retval = float_op(TOS1, TOS, &pobj3, '*');
va009039 0:65f1469d6bfb 243 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 244 PM_SP--;
va009039 0:65f1469d6bfb 245 TOS = pobj3;
va009039 0:65f1469d6bfb 246 continue;
va009039 0:65f1469d6bfb 247 }
va009039 0:65f1469d6bfb 248 #endif /* HAVE_FLOAT */
va009039 0:65f1469d6bfb 249
va009039 0:65f1469d6bfb 250 #ifdef HAVE_REPLICATION
va009039 0:65f1469d6bfb 251 /* If it's a list replication operation */
va009039 0:65f1469d6bfb 252 else if ((OBJ_GET_TYPE(TOS) == OBJ_TYPE_INT)
va009039 0:65f1469d6bfb 253 && (OBJ_GET_TYPE(TOS1) == OBJ_TYPE_LST))
va009039 0:65f1469d6bfb 254 {
va009039 0:65f1469d6bfb 255 t16 = (int16_t)((pPmInt_t)TOS)->val;
va009039 0:65f1469d6bfb 256 if (t16 < 0)
va009039 0:65f1469d6bfb 257 {
va009039 0:65f1469d6bfb 258 t16 = 0;
va009039 0:65f1469d6bfb 259 }
va009039 0:65f1469d6bfb 260
va009039 0:65f1469d6bfb 261 retval = list_replicate(TOS1, t16, &pobj3);
va009039 0:65f1469d6bfb 262 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 263 PM_SP--;
va009039 0:65f1469d6bfb 264 TOS = pobj3;
va009039 0:65f1469d6bfb 265 continue;
va009039 0:65f1469d6bfb 266 }
va009039 0:65f1469d6bfb 267
va009039 0:65f1469d6bfb 268 /* If it's a tuple replication operation */
va009039 0:65f1469d6bfb 269 else if ((OBJ_GET_TYPE(TOS) == OBJ_TYPE_INT)
va009039 0:65f1469d6bfb 270 && (OBJ_GET_TYPE(TOS1) == OBJ_TYPE_TUP))
va009039 0:65f1469d6bfb 271 {
va009039 0:65f1469d6bfb 272 t16 = (int16_t)((pPmInt_t)TOS)->val;
va009039 0:65f1469d6bfb 273 if (t16 < 0)
va009039 0:65f1469d6bfb 274 {
va009039 0:65f1469d6bfb 275 t16 = 0;
va009039 0:65f1469d6bfb 276 }
va009039 0:65f1469d6bfb 277
va009039 0:65f1469d6bfb 278 retval = tuple_replicate(TOS1, t16, &pobj3);
va009039 0:65f1469d6bfb 279 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 280 PM_SP--;
va009039 0:65f1469d6bfb 281 TOS = pobj3;
va009039 0:65f1469d6bfb 282 continue;
va009039 0:65f1469d6bfb 283 }
va009039 0:65f1469d6bfb 284
va009039 0:65f1469d6bfb 285 /* If it's a string replication operation */
va009039 0:65f1469d6bfb 286 else if ((OBJ_GET_TYPE(TOS) == OBJ_TYPE_INT)
va009039 0:65f1469d6bfb 287 && (OBJ_GET_TYPE(TOS1) == OBJ_TYPE_STR))
va009039 0:65f1469d6bfb 288 {
va009039 0:65f1469d6bfb 289 t16 = (int16_t)((pPmInt_t)TOS)->val;
va009039 0:65f1469d6bfb 290 if (t16 < 0)
va009039 0:65f1469d6bfb 291 {
va009039 0:65f1469d6bfb 292 t16 = 0;
va009039 0:65f1469d6bfb 293 }
va009039 0:65f1469d6bfb 294
va009039 0:65f1469d6bfb 295 pobj2 = TOS1;
va009039 0:65f1469d6bfb 296 pobj2 = (pPmObj_t)&((pPmString_t)pobj2)->val;
va009039 0:65f1469d6bfb 297 retval = string_replicate(
va009039 0:65f1469d6bfb 298 (uint8_t const **)(uint8_t *)&pobj2, t16, &pobj3);
va009039 0:65f1469d6bfb 299 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 300 PM_SP--;
va009039 0:65f1469d6bfb 301 TOS = pobj3;
va009039 0:65f1469d6bfb 302 continue;
va009039 0:65f1469d6bfb 303 }
va009039 0:65f1469d6bfb 304 #endif /* HAVE_REPLICATION */
va009039 0:65f1469d6bfb 305
va009039 0:65f1469d6bfb 306 /* Otherwise raise a TypeError */
va009039 0:65f1469d6bfb 307 PM_RAISE(retval, PM_RET_EX_TYPE);
va009039 0:65f1469d6bfb 308 break;
va009039 0:65f1469d6bfb 309
va009039 0:65f1469d6bfb 310 case BINARY_DIVIDE:
va009039 0:65f1469d6bfb 311 case INPLACE_DIVIDE:
va009039 0:65f1469d6bfb 312 case BINARY_FLOOR_DIVIDE:
va009039 0:65f1469d6bfb 313 case INPLACE_FLOOR_DIVIDE:
va009039 0:65f1469d6bfb 314
va009039 0:65f1469d6bfb 315 #ifdef HAVE_FLOAT
va009039 0:65f1469d6bfb 316 if ((OBJ_GET_TYPE(TOS) == OBJ_TYPE_FLT)
va009039 0:65f1469d6bfb 317 || (OBJ_GET_TYPE(TOS1) == OBJ_TYPE_FLT))
va009039 0:65f1469d6bfb 318 {
va009039 0:65f1469d6bfb 319 retval = float_op(TOS1, TOS, &pobj3, '/');
va009039 0:65f1469d6bfb 320 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 321 PM_SP--;
va009039 0:65f1469d6bfb 322 TOS = pobj3;
va009039 0:65f1469d6bfb 323 continue;
va009039 0:65f1469d6bfb 324 }
va009039 0:65f1469d6bfb 325 #endif /* HAVE_FLOAT */
va009039 0:65f1469d6bfb 326
va009039 0:65f1469d6bfb 327 /* Otherwise perform operation */
va009039 0:65f1469d6bfb 328 retval = int_divmod(TOS1, TOS, '/', &pobj3);
va009039 0:65f1469d6bfb 329 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 330 PM_SP--;
va009039 0:65f1469d6bfb 331 TOS = pobj3;
va009039 0:65f1469d6bfb 332 continue;
va009039 0:65f1469d6bfb 333
va009039 0:65f1469d6bfb 334 case BINARY_MODULO:
va009039 0:65f1469d6bfb 335 case INPLACE_MODULO:
va009039 0:65f1469d6bfb 336
va009039 0:65f1469d6bfb 337 #ifdef HAVE_STRING_FORMAT
va009039 0:65f1469d6bfb 338 /* If it's a string, perform string format */
va009039 0:65f1469d6bfb 339 if (OBJ_GET_TYPE(TOS1) == OBJ_TYPE_STR)
va009039 0:65f1469d6bfb 340 {
va009039 0:65f1469d6bfb 341 retval = string_format((pPmString_t)TOS1, TOS, &pobj3);
va009039 0:65f1469d6bfb 342 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 343 PM_SP--;
va009039 0:65f1469d6bfb 344 TOS = pobj3;
va009039 0:65f1469d6bfb 345 continue;
va009039 0:65f1469d6bfb 346 }
va009039 0:65f1469d6bfb 347 #endif /* HAVE_STRING_FORMAT */
va009039 0:65f1469d6bfb 348
va009039 0:65f1469d6bfb 349 #ifdef HAVE_FLOAT
va009039 0:65f1469d6bfb 350 if ((OBJ_GET_TYPE(TOS) == OBJ_TYPE_FLT)
va009039 0:65f1469d6bfb 351 || (OBJ_GET_TYPE(TOS1) == OBJ_TYPE_FLT))
va009039 0:65f1469d6bfb 352 {
va009039 0:65f1469d6bfb 353 retval = float_op(TOS1, TOS, &pobj3, '%');
va009039 0:65f1469d6bfb 354 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 355 PM_SP--;
va009039 0:65f1469d6bfb 356 TOS = pobj3;
va009039 0:65f1469d6bfb 357 continue;
va009039 0:65f1469d6bfb 358 }
va009039 0:65f1469d6bfb 359 #endif /* HAVE_FLOAT */
va009039 0:65f1469d6bfb 360
va009039 0:65f1469d6bfb 361 /* Otherwise perform operation */
va009039 0:65f1469d6bfb 362 retval = int_divmod(TOS1, TOS, '%', &pobj3);
va009039 0:65f1469d6bfb 363 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 364 PM_SP--;
va009039 0:65f1469d6bfb 365 TOS = pobj3;
va009039 0:65f1469d6bfb 366 continue;
va009039 0:65f1469d6bfb 367
va009039 0:65f1469d6bfb 368 case STORE_MAP:
va009039 0:65f1469d6bfb 369 /* #213: Add support for Python 2.6 bytecodes */
va009039 0:65f1469d6bfb 370 C_ASSERT(OBJ_GET_TYPE(TOS2) == OBJ_TYPE_DIC);
va009039 0:65f1469d6bfb 371 retval = dict_setItem(TOS2, TOS, TOS1);
va009039 0:65f1469d6bfb 372 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 373 PM_SP -= 2;
va009039 0:65f1469d6bfb 374 continue;
va009039 0:65f1469d6bfb 375
va009039 0:65f1469d6bfb 376 case BINARY_ADD:
va009039 0:65f1469d6bfb 377 case INPLACE_ADD:
va009039 0:65f1469d6bfb 378
va009039 0:65f1469d6bfb 379 #ifdef HAVE_FLOAT
va009039 0:65f1469d6bfb 380 if ((OBJ_GET_TYPE(TOS) == OBJ_TYPE_FLT)
va009039 0:65f1469d6bfb 381 || (OBJ_GET_TYPE(TOS1) == OBJ_TYPE_FLT))
va009039 0:65f1469d6bfb 382 {
va009039 0:65f1469d6bfb 383 retval = float_op(TOS1, TOS, &pobj3, '+');
va009039 0:65f1469d6bfb 384 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 385 PM_SP--;
va009039 0:65f1469d6bfb 386 TOS = pobj3;
va009039 0:65f1469d6bfb 387 continue;
va009039 0:65f1469d6bfb 388 }
va009039 0:65f1469d6bfb 389 #endif /* HAVE_FLOAT */
va009039 0:65f1469d6bfb 390
va009039 0:65f1469d6bfb 391 /* If both objs are ints, perform the op */
va009039 0:65f1469d6bfb 392 if ((OBJ_GET_TYPE(TOS) == OBJ_TYPE_INT)
va009039 0:65f1469d6bfb 393 && (OBJ_GET_TYPE(TOS1) == OBJ_TYPE_INT))
va009039 0:65f1469d6bfb 394 {
va009039 0:65f1469d6bfb 395 retval = int_new(((pPmInt_t)TOS1)->val +
va009039 0:65f1469d6bfb 396 ((pPmInt_t)TOS)->val, &pobj3);
va009039 0:65f1469d6bfb 397 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 398 PM_SP--;
va009039 0:65f1469d6bfb 399 TOS = pobj3;
va009039 0:65f1469d6bfb 400 continue;
va009039 0:65f1469d6bfb 401 }
va009039 0:65f1469d6bfb 402
va009039 0:65f1469d6bfb 403 /* #242: If both objs are strings, perform concatenation */
va009039 0:65f1469d6bfb 404 if ((OBJ_GET_TYPE(TOS) == OBJ_TYPE_STR)
va009039 0:65f1469d6bfb 405 && (OBJ_GET_TYPE(TOS1) == OBJ_TYPE_STR))
va009039 0:65f1469d6bfb 406 {
va009039 0:65f1469d6bfb 407 retval = string_concat((pPmString_t)TOS1,
va009039 0:65f1469d6bfb 408 (pPmString_t)TOS,
va009039 0:65f1469d6bfb 409 &pobj3);
va009039 0:65f1469d6bfb 410 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 411 PM_SP--;
va009039 0:65f1469d6bfb 412 TOS = pobj3;
va009039 0:65f1469d6bfb 413 continue;
va009039 0:65f1469d6bfb 414 }
va009039 0:65f1469d6bfb 415
va009039 0:65f1469d6bfb 416 /* Otherwise raise a TypeError */
va009039 0:65f1469d6bfb 417 PM_RAISE(retval, PM_RET_EX_TYPE);
va009039 0:65f1469d6bfb 418 break;
va009039 0:65f1469d6bfb 419
va009039 0:65f1469d6bfb 420 case BINARY_SUBTRACT:
va009039 0:65f1469d6bfb 421 case INPLACE_SUBTRACT:
va009039 0:65f1469d6bfb 422
va009039 0:65f1469d6bfb 423 #ifdef HAVE_FLOAT
va009039 0:65f1469d6bfb 424 if ((OBJ_GET_TYPE(TOS) == OBJ_TYPE_FLT)
va009039 0:65f1469d6bfb 425 || (OBJ_GET_TYPE(TOS1) == OBJ_TYPE_FLT))
va009039 0:65f1469d6bfb 426 {
va009039 0:65f1469d6bfb 427 retval = float_op(TOS1, TOS, &pobj3, '-');
va009039 0:65f1469d6bfb 428 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 429 PM_SP--;
va009039 0:65f1469d6bfb 430 TOS = pobj3;
va009039 0:65f1469d6bfb 431 continue;
va009039 0:65f1469d6bfb 432 }
va009039 0:65f1469d6bfb 433 #endif /* HAVE_FLOAT */
va009039 0:65f1469d6bfb 434
va009039 0:65f1469d6bfb 435 /* If both objs are ints, perform the op */
va009039 0:65f1469d6bfb 436 if ((OBJ_GET_TYPE(TOS) == OBJ_TYPE_INT)
va009039 0:65f1469d6bfb 437 && (OBJ_GET_TYPE(TOS1) == OBJ_TYPE_INT))
va009039 0:65f1469d6bfb 438 {
va009039 0:65f1469d6bfb 439 retval = int_new(((pPmInt_t)TOS1)->val -
va009039 0:65f1469d6bfb 440 ((pPmInt_t)TOS)->val, &pobj3);
va009039 0:65f1469d6bfb 441 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 442 PM_SP--;
va009039 0:65f1469d6bfb 443 TOS = pobj3;
va009039 0:65f1469d6bfb 444 continue;
va009039 0:65f1469d6bfb 445 }
va009039 0:65f1469d6bfb 446
va009039 0:65f1469d6bfb 447 /* Otherwise raise a TypeError */
va009039 0:65f1469d6bfb 448 PM_RAISE(retval, PM_RET_EX_TYPE);
va009039 0:65f1469d6bfb 449 break;
va009039 0:65f1469d6bfb 450
va009039 0:65f1469d6bfb 451 case BINARY_SUBSCR:
va009039 0:65f1469d6bfb 452 /* Implements TOS = TOS1[TOS]. */
va009039 0:65f1469d6bfb 453
va009039 0:65f1469d6bfb 454 if (OBJ_GET_TYPE(TOS1) == OBJ_TYPE_DIC)
va009039 0:65f1469d6bfb 455 {
va009039 0:65f1469d6bfb 456 retval = dict_getItem(TOS1, TOS, &pobj3);
va009039 0:65f1469d6bfb 457 }
va009039 0:65f1469d6bfb 458 else
va009039 0:65f1469d6bfb 459 {
va009039 0:65f1469d6bfb 460 /* Raise a TypeError if index is not an Integer or Bool */
va009039 0:65f1469d6bfb 461 if ((OBJ_GET_TYPE(TOS) != OBJ_TYPE_INT)
va009039 0:65f1469d6bfb 462 && (OBJ_GET_TYPE(TOS) != OBJ_TYPE_BOOL))
va009039 0:65f1469d6bfb 463 {
va009039 0:65f1469d6bfb 464 PM_RAISE(retval, PM_RET_EX_TYPE);
va009039 0:65f1469d6bfb 465 break;
va009039 0:65f1469d6bfb 466 }
va009039 0:65f1469d6bfb 467
va009039 0:65f1469d6bfb 468 pobj1 = TOS1;
va009039 0:65f1469d6bfb 469 #ifdef HAVE_BYTEARRAY
va009039 0:65f1469d6bfb 470 /* If object is an instance, get the thing it contains */
va009039 0:65f1469d6bfb 471 if (OBJ_GET_TYPE(pobj1) == OBJ_TYPE_CLI)
va009039 0:65f1469d6bfb 472 {
va009039 0:65f1469d6bfb 473 retval = dict_getItem((pPmObj_t)((pPmInstance_t)pobj1)->cli_attrs,
va009039 0:65f1469d6bfb 474 PM_NONE,
va009039 0:65f1469d6bfb 475 &pobj2);
va009039 0:65f1469d6bfb 476 PM_RETURN_IF_ERROR(retval);
va009039 0:65f1469d6bfb 477 pobj1 = pobj2;
va009039 0:65f1469d6bfb 478 }
va009039 0:65f1469d6bfb 479 #endif /* HAVE_BYTEARRAY */
va009039 0:65f1469d6bfb 480
va009039 0:65f1469d6bfb 481 /* Ensure the index doesn't overflow */
va009039 0:65f1469d6bfb 482 C_ASSERT(((pPmInt_t)TOS)->val <= 0x0000FFFF);
va009039 0:65f1469d6bfb 483 t16 = (int16_t)((pPmInt_t)TOS)->val;
va009039 0:65f1469d6bfb 484
va009039 0:65f1469d6bfb 485 retval = seq_getSubscript(pobj1, t16, &pobj3);
va009039 0:65f1469d6bfb 486 }
va009039 0:65f1469d6bfb 487 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 488 PM_SP--;
va009039 0:65f1469d6bfb 489 TOS = pobj3;
va009039 0:65f1469d6bfb 490 continue;
va009039 0:65f1469d6bfb 491
va009039 0:65f1469d6bfb 492 #ifdef HAVE_FLOAT
va009039 0:65f1469d6bfb 493 /* #213: Add support for Python 2.6 bytecodes */
va009039 0:65f1469d6bfb 494 case BINARY_TRUE_DIVIDE:
va009039 0:65f1469d6bfb 495 case INPLACE_TRUE_DIVIDE:
va009039 0:65f1469d6bfb 496
va009039 0:65f1469d6bfb 497 /* Perform division; float_op() checks for types and zero-div */
va009039 0:65f1469d6bfb 498 retval = float_op(TOS1, TOS, &pobj3, '/');
va009039 0:65f1469d6bfb 499 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 500 PM_SP--;
va009039 0:65f1469d6bfb 501 TOS = pobj3;
va009039 0:65f1469d6bfb 502 continue;
va009039 0:65f1469d6bfb 503 #endif /* HAVE_FLOAT */
va009039 0:65f1469d6bfb 504
va009039 0:65f1469d6bfb 505 case SLICE_0:
va009039 0:65f1469d6bfb 506 /* Implements TOS = TOS[:], push a copy of the sequence */
va009039 0:65f1469d6bfb 507
va009039 0:65f1469d6bfb 508 /* Create a copy if it is a list */
va009039 0:65f1469d6bfb 509 if (OBJ_GET_TYPE(TOS) == OBJ_TYPE_LST)
va009039 0:65f1469d6bfb 510 {
va009039 0:65f1469d6bfb 511 retval = list_copy(TOS, &pobj2);
va009039 0:65f1469d6bfb 512 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 513
va009039 0:65f1469d6bfb 514 TOS = pobj2;
va009039 0:65f1469d6bfb 515 }
va009039 0:65f1469d6bfb 516
va009039 0:65f1469d6bfb 517 /* If TOS is an immutable sequence leave it (no op) */
va009039 0:65f1469d6bfb 518
va009039 0:65f1469d6bfb 519 /* Raise a TypeError for types that can not be sliced */
va009039 0:65f1469d6bfb 520 else if ((OBJ_GET_TYPE(TOS) != OBJ_TYPE_STR)
va009039 0:65f1469d6bfb 521 && (OBJ_GET_TYPE(TOS) != OBJ_TYPE_TUP))
va009039 0:65f1469d6bfb 522 {
va009039 0:65f1469d6bfb 523 PM_RAISE(retval, PM_RET_EX_TYPE);
va009039 0:65f1469d6bfb 524 break;
va009039 0:65f1469d6bfb 525 }
va009039 0:65f1469d6bfb 526 continue;
va009039 0:65f1469d6bfb 527
va009039 0:65f1469d6bfb 528 case STORE_SUBSCR:
va009039 0:65f1469d6bfb 529 /* Implements TOS1[TOS] = TOS2 */
va009039 0:65f1469d6bfb 530
va009039 0:65f1469d6bfb 531 /* If it's a list */
va009039 0:65f1469d6bfb 532 if (OBJ_GET_TYPE(TOS1) == OBJ_TYPE_LST)
va009039 0:65f1469d6bfb 533 {
va009039 0:65f1469d6bfb 534 /* Ensure subscr is an int or bool */
va009039 0:65f1469d6bfb 535 if ((OBJ_GET_TYPE(TOS) != OBJ_TYPE_INT)
va009039 0:65f1469d6bfb 536 && (OBJ_GET_TYPE(TOS) != OBJ_TYPE_BOOL))
va009039 0:65f1469d6bfb 537 {
va009039 0:65f1469d6bfb 538 PM_RAISE(retval, PM_RET_EX_TYPE);
va009039 0:65f1469d6bfb 539 break;
va009039 0:65f1469d6bfb 540 }
va009039 0:65f1469d6bfb 541
va009039 0:65f1469d6bfb 542 /* Set the list item */
va009039 0:65f1469d6bfb 543 retval = list_setItem(TOS1,
va009039 0:65f1469d6bfb 544 (int16_t)(((pPmInt_t)TOS)->val),
va009039 0:65f1469d6bfb 545 TOS2);
va009039 0:65f1469d6bfb 546 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 547 PM_SP -= 3;
va009039 0:65f1469d6bfb 548 continue;
va009039 0:65f1469d6bfb 549 }
va009039 0:65f1469d6bfb 550
va009039 0:65f1469d6bfb 551 /* If it's a dict */
va009039 0:65f1469d6bfb 552 if (OBJ_GET_TYPE(TOS1) == OBJ_TYPE_DIC)
va009039 0:65f1469d6bfb 553 {
va009039 0:65f1469d6bfb 554 /* Set the dict item */
va009039 0:65f1469d6bfb 555 retval = dict_setItem(TOS1, TOS, TOS2);
va009039 0:65f1469d6bfb 556 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 557 PM_SP -= 3;
va009039 0:65f1469d6bfb 558 continue;
va009039 0:65f1469d6bfb 559 }
va009039 0:65f1469d6bfb 560
va009039 0:65f1469d6bfb 561 #ifdef HAVE_BYTEARRAY
va009039 0:65f1469d6bfb 562 /* If object is an instance, get the thing it contains */
va009039 0:65f1469d6bfb 563 if (OBJ_GET_TYPE(TOS1) == OBJ_TYPE_CLI)
va009039 0:65f1469d6bfb 564 {
va009039 0:65f1469d6bfb 565 retval = dict_getItem((pPmObj_t)((pPmInstance_t)TOS1)->cli_attrs,
va009039 0:65f1469d6bfb 566 PM_NONE,
va009039 0:65f1469d6bfb 567 &pobj2);
va009039 0:65f1469d6bfb 568
va009039 0:65f1469d6bfb 569 /* Raise TypeError if instance isn't a ByteArray */
va009039 0:65f1469d6bfb 570 if ((retval == PM_RET_EX_KEY)
va009039 0:65f1469d6bfb 571 || (OBJ_GET_TYPE(pobj2) != OBJ_TYPE_BYA))
va009039 0:65f1469d6bfb 572 {
va009039 0:65f1469d6bfb 573 PM_RAISE(retval, PM_RET_EX_TYPE);
va009039 0:65f1469d6bfb 574 break;
va009039 0:65f1469d6bfb 575 }
va009039 0:65f1469d6bfb 576 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 577
va009039 0:65f1469d6bfb 578 /* Ensure subscr is an int or bool */
va009039 0:65f1469d6bfb 579 if ((OBJ_GET_TYPE(TOS) != OBJ_TYPE_INT)
va009039 0:65f1469d6bfb 580 && (OBJ_GET_TYPE(TOS) != OBJ_TYPE_BOOL))
va009039 0:65f1469d6bfb 581 {
va009039 0:65f1469d6bfb 582 PM_RAISE(retval, PM_RET_EX_TYPE);
va009039 0:65f1469d6bfb 583 break;
va009039 0:65f1469d6bfb 584 }
va009039 0:65f1469d6bfb 585
va009039 0:65f1469d6bfb 586 retval = bytearray_setItem(pobj2,
va009039 0:65f1469d6bfb 587 (int16_t)(((pPmInt_t)TOS)->val),
va009039 0:65f1469d6bfb 588 TOS2);
va009039 0:65f1469d6bfb 589 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 590 PM_SP -= 3;
va009039 0:65f1469d6bfb 591 continue;
va009039 0:65f1469d6bfb 592 }
va009039 0:65f1469d6bfb 593 #endif /* HAVE_BYTEARRAY */
va009039 0:65f1469d6bfb 594
va009039 0:65f1469d6bfb 595 /* TypeError for all else */
va009039 0:65f1469d6bfb 596 PM_RAISE(retval, PM_RET_EX_TYPE);
va009039 0:65f1469d6bfb 597 break;
va009039 0:65f1469d6bfb 598
va009039 0:65f1469d6bfb 599 #ifdef HAVE_DEL
va009039 0:65f1469d6bfb 600 case DELETE_SUBSCR:
va009039 0:65f1469d6bfb 601
va009039 0:65f1469d6bfb 602 if ((OBJ_GET_TYPE(TOS1) == OBJ_TYPE_LST)
va009039 0:65f1469d6bfb 603 && (OBJ_GET_TYPE(TOS) == OBJ_TYPE_INT))
va009039 0:65f1469d6bfb 604 {
va009039 0:65f1469d6bfb 605 retval = list_delItem(TOS1,
va009039 0:65f1469d6bfb 606 (int16_t)((pPmInt_t)TOS)->val);
va009039 0:65f1469d6bfb 607 }
va009039 0:65f1469d6bfb 608
va009039 0:65f1469d6bfb 609 else if ((OBJ_GET_TYPE(TOS1) == OBJ_TYPE_DIC)
va009039 0:65f1469d6bfb 610 && (OBJ_GET_TYPE(TOS) <= OBJ_TYPE_HASHABLE_MAX))
va009039 0:65f1469d6bfb 611 {
va009039 0:65f1469d6bfb 612 retval = dict_delItem(TOS1, TOS);
va009039 0:65f1469d6bfb 613 }
va009039 0:65f1469d6bfb 614
va009039 0:65f1469d6bfb 615 /* Raise TypeError if obj is not a list or dict */
va009039 0:65f1469d6bfb 616 else
va009039 0:65f1469d6bfb 617 {
va009039 0:65f1469d6bfb 618 PM_RAISE(retval, PM_RET_EX_TYPE);
va009039 0:65f1469d6bfb 619 }
va009039 0:65f1469d6bfb 620
va009039 0:65f1469d6bfb 621 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 622 PM_SP -= 2;
va009039 0:65f1469d6bfb 623 continue;
va009039 0:65f1469d6bfb 624 #endif /* HAVE_DEL */
va009039 0:65f1469d6bfb 625
va009039 0:65f1469d6bfb 626 case BINARY_LSHIFT:
va009039 0:65f1469d6bfb 627 case INPLACE_LSHIFT:
va009039 0:65f1469d6bfb 628 /* If both objs are ints, perform the op */
va009039 0:65f1469d6bfb 629 if ((OBJ_GET_TYPE(TOS) == OBJ_TYPE_INT)
va009039 0:65f1469d6bfb 630 && (OBJ_GET_TYPE(TOS1) == OBJ_TYPE_INT))
va009039 0:65f1469d6bfb 631 {
va009039 0:65f1469d6bfb 632 retval = int_new(((pPmInt_t)TOS1)->val <<
va009039 0:65f1469d6bfb 633 ((pPmInt_t)TOS)->val, &pobj3);
va009039 0:65f1469d6bfb 634 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 635 PM_SP--;
va009039 0:65f1469d6bfb 636 TOS = pobj3;
va009039 0:65f1469d6bfb 637 continue;
va009039 0:65f1469d6bfb 638 }
va009039 0:65f1469d6bfb 639
va009039 0:65f1469d6bfb 640 /* Otherwise raise a TypeError */
va009039 0:65f1469d6bfb 641 PM_RAISE(retval, PM_RET_EX_TYPE);
va009039 0:65f1469d6bfb 642 break;
va009039 0:65f1469d6bfb 643
va009039 0:65f1469d6bfb 644 case BINARY_RSHIFT:
va009039 0:65f1469d6bfb 645 case INPLACE_RSHIFT:
va009039 0:65f1469d6bfb 646 /* If both objs are ints, perform the op */
va009039 0:65f1469d6bfb 647 if ((OBJ_GET_TYPE(TOS) == OBJ_TYPE_INT)
va009039 0:65f1469d6bfb 648 && (OBJ_GET_TYPE(TOS1) == OBJ_TYPE_INT))
va009039 0:65f1469d6bfb 649 {
va009039 0:65f1469d6bfb 650 retval = int_new(((pPmInt_t)TOS1)->val >>
va009039 0:65f1469d6bfb 651 ((pPmInt_t)TOS)->val, &pobj3);
va009039 0:65f1469d6bfb 652 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 653 PM_SP--;
va009039 0:65f1469d6bfb 654 TOS = pobj3;
va009039 0:65f1469d6bfb 655 continue;
va009039 0:65f1469d6bfb 656 }
va009039 0:65f1469d6bfb 657
va009039 0:65f1469d6bfb 658 /* Otherwise raise a TypeError */
va009039 0:65f1469d6bfb 659 PM_RAISE(retval, PM_RET_EX_TYPE);
va009039 0:65f1469d6bfb 660 break;
va009039 0:65f1469d6bfb 661
va009039 0:65f1469d6bfb 662 case BINARY_AND:
va009039 0:65f1469d6bfb 663 case INPLACE_AND:
va009039 0:65f1469d6bfb 664 /* If both objs are ints, perform the op */
va009039 0:65f1469d6bfb 665 if ((OBJ_GET_TYPE(TOS) == OBJ_TYPE_INT)
va009039 0:65f1469d6bfb 666 && (OBJ_GET_TYPE(TOS1) == OBJ_TYPE_INT))
va009039 0:65f1469d6bfb 667 {
va009039 0:65f1469d6bfb 668 retval = int_new(((pPmInt_t)TOS1)->val &
va009039 0:65f1469d6bfb 669 ((pPmInt_t)TOS)->val, &pobj3);
va009039 0:65f1469d6bfb 670 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 671 PM_SP--;
va009039 0:65f1469d6bfb 672 TOS = pobj3;
va009039 0:65f1469d6bfb 673 continue;
va009039 0:65f1469d6bfb 674 }
va009039 0:65f1469d6bfb 675
va009039 0:65f1469d6bfb 676 /* Otherwise raise a TypeError */
va009039 0:65f1469d6bfb 677 PM_RAISE(retval, PM_RET_EX_TYPE);
va009039 0:65f1469d6bfb 678 break;
va009039 0:65f1469d6bfb 679
va009039 0:65f1469d6bfb 680 case BINARY_XOR:
va009039 0:65f1469d6bfb 681 case INPLACE_XOR:
va009039 0:65f1469d6bfb 682 /* If both objs are ints, perform the op */
va009039 0:65f1469d6bfb 683 if ((OBJ_GET_TYPE(TOS) == OBJ_TYPE_INT)
va009039 0:65f1469d6bfb 684 && (OBJ_GET_TYPE(TOS1) == OBJ_TYPE_INT))
va009039 0:65f1469d6bfb 685 {
va009039 0:65f1469d6bfb 686 retval = int_new(((pPmInt_t)TOS1)->val ^
va009039 0:65f1469d6bfb 687 ((pPmInt_t)TOS)->val, &pobj3);
va009039 0:65f1469d6bfb 688 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 689 PM_SP--;
va009039 0:65f1469d6bfb 690 TOS = pobj3;
va009039 0:65f1469d6bfb 691 continue;
va009039 0:65f1469d6bfb 692 }
va009039 0:65f1469d6bfb 693
va009039 0:65f1469d6bfb 694 /* Otherwise raise a TypeError */
va009039 0:65f1469d6bfb 695 PM_RAISE(retval, PM_RET_EX_TYPE);
va009039 0:65f1469d6bfb 696 break;
va009039 0:65f1469d6bfb 697
va009039 0:65f1469d6bfb 698 case BINARY_OR:
va009039 0:65f1469d6bfb 699 case INPLACE_OR:
va009039 0:65f1469d6bfb 700 /* If both objs are ints, perform the op */
va009039 0:65f1469d6bfb 701 if ((OBJ_GET_TYPE(TOS) == OBJ_TYPE_INT)
va009039 0:65f1469d6bfb 702 && (OBJ_GET_TYPE(TOS1) == OBJ_TYPE_INT))
va009039 0:65f1469d6bfb 703 {
va009039 0:65f1469d6bfb 704 retval = int_new(((pPmInt_t)TOS1)->val |
va009039 0:65f1469d6bfb 705 ((pPmInt_t)TOS)->val, &pobj3);
va009039 0:65f1469d6bfb 706 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 707 PM_SP--;
va009039 0:65f1469d6bfb 708 TOS = pobj3;
va009039 0:65f1469d6bfb 709 continue;
va009039 0:65f1469d6bfb 710 }
va009039 0:65f1469d6bfb 711
va009039 0:65f1469d6bfb 712 /* Otherwise raise a TypeError */
va009039 0:65f1469d6bfb 713 PM_RAISE(retval, PM_RET_EX_TYPE);
va009039 0:65f1469d6bfb 714 break;
va009039 0:65f1469d6bfb 715
va009039 0:65f1469d6bfb 716 #ifdef HAVE_PRINT
va009039 0:65f1469d6bfb 717 case PRINT_EXPR:
va009039 0:65f1469d6bfb 718 /* Print interactive expression */
va009039 0:65f1469d6bfb 719 /* Fallthrough */
va009039 0:65f1469d6bfb 720
va009039 0:65f1469d6bfb 721 case PRINT_ITEM:
va009039 0:65f1469d6bfb 722 if (gVmGlobal.needSoftSpace && (bc == PRINT_ITEM))
va009039 0:65f1469d6bfb 723 {
va009039 0:65f1469d6bfb 724 retval = plat_putByte(' ');
va009039 0:65f1469d6bfb 725 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 726 }
va009039 0:65f1469d6bfb 727 gVmGlobal.needSoftSpace = C_TRUE;
va009039 0:65f1469d6bfb 728
va009039 0:65f1469d6bfb 729 /* Print out topmost stack element */
va009039 0:65f1469d6bfb 730 retval = obj_print(TOS, (uint8_t)(bc == PRINT_EXPR), C_FALSE);
va009039 0:65f1469d6bfb 731 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 732 PM_SP--;
va009039 0:65f1469d6bfb 733 if (bc != PRINT_EXPR)
va009039 0:65f1469d6bfb 734 {
va009039 0:65f1469d6bfb 735 continue;
va009039 0:65f1469d6bfb 736 }
va009039 0:65f1469d6bfb 737 /* If PRINT_EXPR, Fallthrough to print a newline */
va009039 0:65f1469d6bfb 738
va009039 0:65f1469d6bfb 739 case PRINT_NEWLINE:
va009039 0:65f1469d6bfb 740 gVmGlobal.needSoftSpace = C_FALSE;
va009039 0:65f1469d6bfb 741 if (gVmGlobal.somethingPrinted)
va009039 0:65f1469d6bfb 742 {
va009039 0:65f1469d6bfb 743 retval = plat_putByte('\n');
va009039 0:65f1469d6bfb 744 gVmGlobal.somethingPrinted = C_FALSE;
va009039 0:65f1469d6bfb 745 }
va009039 0:65f1469d6bfb 746 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 747 continue;
va009039 0:65f1469d6bfb 748 #endif /* HAVE_PRINT */
va009039 0:65f1469d6bfb 749
va009039 0:65f1469d6bfb 750 case BREAK_LOOP:
va009039 0:65f1469d6bfb 751 {
va009039 0:65f1469d6bfb 752 pPmBlock_t pb1 = PM_FP->fo_blockstack;
va009039 0:65f1469d6bfb 753
va009039 0:65f1469d6bfb 754 /* Ensure there's a block */
va009039 0:65f1469d6bfb 755 C_ASSERT(pb1 != C_NULL);
va009039 0:65f1469d6bfb 756
va009039 0:65f1469d6bfb 757 /* Delete blocks until first loop block */
va009039 0:65f1469d6bfb 758 while ((pb1->b_type != B_LOOP) && (pb1->next != C_NULL))
va009039 0:65f1469d6bfb 759 {
va009039 0:65f1469d6bfb 760 pobj2 = (pPmObj_t)pb1;
va009039 0:65f1469d6bfb 761 pb1 = pb1->next;
va009039 0:65f1469d6bfb 762 retval = heap_freeChunk(pobj2);
va009039 0:65f1469d6bfb 763 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 764 }
va009039 0:65f1469d6bfb 765
va009039 0:65f1469d6bfb 766 /* Test again outside while loop */
va009039 0:65f1469d6bfb 767 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 768
va009039 0:65f1469d6bfb 769 /* Restore PM_SP */
va009039 0:65f1469d6bfb 770 PM_SP = pb1->b_sp;
va009039 0:65f1469d6bfb 771
va009039 0:65f1469d6bfb 772 /* Goto handler */
va009039 0:65f1469d6bfb 773 PM_IP = pb1->b_handler;
va009039 0:65f1469d6bfb 774
va009039 0:65f1469d6bfb 775 /* Pop and delete this block */
va009039 0:65f1469d6bfb 776 PM_FP->fo_blockstack = pb1->next;
va009039 0:65f1469d6bfb 777 retval = heap_freeChunk((pPmObj_t)pb1);
va009039 0:65f1469d6bfb 778 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 779 }
va009039 0:65f1469d6bfb 780 continue;
va009039 0:65f1469d6bfb 781
va009039 0:65f1469d6bfb 782 case LOAD_LOCALS:
va009039 0:65f1469d6bfb 783 /* Pushes local attrs dict of current frame */
va009039 0:65f1469d6bfb 784 /* WARNING: does not copy fo_locals to attrs */
va009039 0:65f1469d6bfb 785 PM_PUSH((pPmObj_t)PM_FP->fo_attrs);
va009039 0:65f1469d6bfb 786 continue;
va009039 0:65f1469d6bfb 787
va009039 0:65f1469d6bfb 788 case RETURN_VALUE:
va009039 0:65f1469d6bfb 789 /* Get expiring frame's TOS */
va009039 0:65f1469d6bfb 790 pobj2 = PM_POP();
va009039 0:65f1469d6bfb 791
va009039 0:65f1469d6bfb 792 #if 0 /*__DEBUG__*/
va009039 0:65f1469d6bfb 793 /* #251: This safety check is disabled because it breaks ipm */
va009039 0:65f1469d6bfb 794 /* #109: Check that stack should now be empty */
va009039 0:65f1469d6bfb 795 /* If this is regular frame (not native and not a generator) */
va009039 0:65f1469d6bfb 796 if ((PM_FP != (pPmFrame_t)(&gVmGlobal.nativeframe)) &&
va009039 0:65f1469d6bfb 797 !(PM_FP->fo_func->f_co->co_flags & CO_GENERATOR))
va009039 0:65f1469d6bfb 798 {
va009039 0:65f1469d6bfb 799 /* An empty stack points one past end of locals */
va009039 0:65f1469d6bfb 800 t8 = PM_FP->fo_func->f_co->co_nlocals;
va009039 0:65f1469d6bfb 801 C_ASSERT(PM_SP == &(PM_FP->fo_locals[t8]));
va009039 0:65f1469d6bfb 802 }
va009039 0:65f1469d6bfb 803 #endif /* __DEBUG__ */
va009039 0:65f1469d6bfb 804
va009039 0:65f1469d6bfb 805 /* Keep ref of expiring frame */
va009039 0:65f1469d6bfb 806 pobj1 = (pPmObj_t)PM_FP;
va009039 0:65f1469d6bfb 807 C_ASSERT(OBJ_GET_TYPE(pobj1) == OBJ_TYPE_FRM);
va009039 0:65f1469d6bfb 808
va009039 0:65f1469d6bfb 809 /* If no previous frame, quit thread */
va009039 0:65f1469d6bfb 810 if (PM_FP->fo_back == C_NULL)
va009039 0:65f1469d6bfb 811 {
va009039 0:65f1469d6bfb 812 gVmGlobal.pthread->interpctrl = INTERP_CTRL_EXIT;
va009039 0:65f1469d6bfb 813 retval = PM_RET_OK;
va009039 0:65f1469d6bfb 814 break;
va009039 0:65f1469d6bfb 815 }
va009039 0:65f1469d6bfb 816
va009039 0:65f1469d6bfb 817 /* Otherwise return to previous frame */
va009039 0:65f1469d6bfb 818 PM_FP = PM_FP->fo_back;
va009039 0:65f1469d6bfb 819
va009039 0:65f1469d6bfb 820 #ifdef HAVE_GENERATORS
va009039 0:65f1469d6bfb 821 /* If returning function was a generator */
va009039 0:65f1469d6bfb 822 if (((pPmFrame_t)pobj1)->fo_func->f_co->co_flags & CO_GENERATOR)
va009039 0:65f1469d6bfb 823 {
va009039 0:65f1469d6bfb 824 /* Raise a StopIteration exception */
va009039 0:65f1469d6bfb 825 PM_RAISE(retval, PM_RET_EX_STOP);
va009039 0:65f1469d6bfb 826 break;
va009039 0:65f1469d6bfb 827 }
va009039 0:65f1469d6bfb 828 #endif /* HAVE_GENERATORS */
va009039 0:65f1469d6bfb 829
va009039 0:65f1469d6bfb 830 #ifdef HAVE_CLASSES
va009039 0:65f1469d6bfb 831 /*
va009039 0:65f1469d6bfb 832 * If returning function was class initializer
va009039 0:65f1469d6bfb 833 * do not push a return object
va009039 0:65f1469d6bfb 834 */
va009039 0:65f1469d6bfb 835 if (((pPmFrame_t)pobj1)->fo_isInit)
va009039 0:65f1469d6bfb 836 {
va009039 0:65f1469d6bfb 837 /* Raise TypeError if __init__ did not return None */
va009039 0:65f1469d6bfb 838 if (pobj2 != PM_NONE)
va009039 0:65f1469d6bfb 839 {
va009039 0:65f1469d6bfb 840 PM_RAISE(retval, PM_RET_EX_TYPE);
va009039 0:65f1469d6bfb 841 break;
va009039 0:65f1469d6bfb 842 }
va009039 0:65f1469d6bfb 843 }
va009039 0:65f1469d6bfb 844 else
va009039 0:65f1469d6bfb 845 #endif /* HAVE_CLASSES */
va009039 0:65f1469d6bfb 846
va009039 0:65f1469d6bfb 847 /*
va009039 0:65f1469d6bfb 848 * Push frame's return val, except if the expiring frame
va009039 0:65f1469d6bfb 849 * was due to an import statement
va009039 0:65f1469d6bfb 850 */
va009039 0:65f1469d6bfb 851 if (!(((pPmFrame_t)pobj1)->fo_isImport))
va009039 0:65f1469d6bfb 852 {
va009039 0:65f1469d6bfb 853 PM_PUSH(pobj2);
va009039 0:65f1469d6bfb 854 }
va009039 0:65f1469d6bfb 855
va009039 0:65f1469d6bfb 856 /* Deallocate expired frame */
va009039 0:65f1469d6bfb 857 PM_BREAK_IF_ERROR(heap_freeChunk(pobj1));
va009039 0:65f1469d6bfb 858 continue;
va009039 0:65f1469d6bfb 859
va009039 0:65f1469d6bfb 860 #ifdef HAVE_IMPORTS
va009039 0:65f1469d6bfb 861 case IMPORT_STAR:
va009039 0:65f1469d6bfb 862 /* #102: Implement the remaining IMPORT_ bytecodes */
va009039 0:65f1469d6bfb 863 /* Expect a module on the top of the stack */
va009039 0:65f1469d6bfb 864 C_ASSERT(OBJ_GET_TYPE(TOS) == OBJ_TYPE_MOD);
va009039 0:65f1469d6bfb 865
va009039 0:65f1469d6bfb 866 /* Update PM_FP's attrs with those of the module on the stack */
va009039 0:65f1469d6bfb 867 retval = dict_update((pPmObj_t)PM_FP->fo_attrs,
va009039 0:65f1469d6bfb 868 (pPmObj_t)((pPmFunc_t)TOS)->f_attrs,
va009039 0:65f1469d6bfb 869 C_TRUE);
va009039 0:65f1469d6bfb 870 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 871 PM_SP--;
va009039 0:65f1469d6bfb 872 continue;
va009039 0:65f1469d6bfb 873 #endif /* HAVE_IMPORTS */
va009039 0:65f1469d6bfb 874
va009039 0:65f1469d6bfb 875 #ifdef HAVE_GENERATORS
va009039 0:65f1469d6bfb 876 case YIELD_VALUE:
va009039 0:65f1469d6bfb 877 /* #207: Add support for the yield keyword */
va009039 0:65f1469d6bfb 878 /* Get expiring frame's TOS */
va009039 0:65f1469d6bfb 879 pobj1 = PM_POP();
va009039 0:65f1469d6bfb 880
va009039 0:65f1469d6bfb 881 /* Raise TypeError if __init__ did not return None */
va009039 0:65f1469d6bfb 882 /* (Yield means this is a generator) */
va009039 0:65f1469d6bfb 883 if ((PM_FP)->fo_isInit)
va009039 0:65f1469d6bfb 884 {
va009039 0:65f1469d6bfb 885 PM_RAISE(retval, PM_RET_EX_TYPE);
va009039 0:65f1469d6bfb 886 break;
va009039 0:65f1469d6bfb 887 }
va009039 0:65f1469d6bfb 888
va009039 0:65f1469d6bfb 889 /* Return to previous frame */
va009039 0:65f1469d6bfb 890 PM_FP = PM_FP->fo_back;
va009039 0:65f1469d6bfb 891
va009039 0:65f1469d6bfb 892 /* Push yield value onto caller's TOS */
va009039 0:65f1469d6bfb 893 PM_PUSH(pobj1);
va009039 0:65f1469d6bfb 894 continue;
va009039 0:65f1469d6bfb 895 #endif /* HAVE_GENERATORS */
va009039 0:65f1469d6bfb 896
va009039 0:65f1469d6bfb 897 case POP_BLOCK:
va009039 0:65f1469d6bfb 898 /* Get ptr to top block */
va009039 0:65f1469d6bfb 899 pobj1 = (pPmObj_t)PM_FP->fo_blockstack;
va009039 0:65f1469d6bfb 900
va009039 0:65f1469d6bfb 901 /* If there's no block, raise SystemError */
va009039 0:65f1469d6bfb 902 C_ASSERT(pobj1 != C_NULL);
va009039 0:65f1469d6bfb 903
va009039 0:65f1469d6bfb 904 /* Pop block */
va009039 0:65f1469d6bfb 905 PM_FP->fo_blockstack = PM_FP->fo_blockstack->next;
va009039 0:65f1469d6bfb 906
va009039 0:65f1469d6bfb 907 /* Set stack to previous level, jump to code outside block */
va009039 0:65f1469d6bfb 908 PM_SP = ((pPmBlock_t)pobj1)->b_sp;
va009039 0:65f1469d6bfb 909 PM_IP = ((pPmBlock_t)pobj1)->b_handler;
va009039 0:65f1469d6bfb 910
va009039 0:65f1469d6bfb 911 PM_BREAK_IF_ERROR(heap_freeChunk(pobj1));
va009039 0:65f1469d6bfb 912 continue;
va009039 0:65f1469d6bfb 913
va009039 0:65f1469d6bfb 914 #ifdef HAVE_CLASSES
va009039 0:65f1469d6bfb 915 case BUILD_CLASS:
va009039 0:65f1469d6bfb 916 /* Create and push new class */
va009039 0:65f1469d6bfb 917 retval = class_new(TOS, TOS1, TOS2, &pobj2);
va009039 0:65f1469d6bfb 918 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 919 PM_SP -= 2;
va009039 0:65f1469d6bfb 920 TOS = pobj2;
va009039 0:65f1469d6bfb 921 continue;
va009039 0:65f1469d6bfb 922 #endif /* HAVE_CLASSES */
va009039 0:65f1469d6bfb 923
va009039 0:65f1469d6bfb 924
va009039 0:65f1469d6bfb 925 /***************************************************
va009039 0:65f1469d6bfb 926 * All bytecodes after 90 (0x5A) have a 2-byte arg
va009039 0:65f1469d6bfb 927 * that needs to be swallowed using GET_ARG().
va009039 0:65f1469d6bfb 928 **************************************************/
va009039 0:65f1469d6bfb 929
va009039 0:65f1469d6bfb 930 case STORE_NAME:
va009039 0:65f1469d6bfb 931 /* Get name index */
va009039 0:65f1469d6bfb 932 t16 = GET_ARG();
va009039 0:65f1469d6bfb 933
va009039 0:65f1469d6bfb 934 /* Get key */
va009039 0:65f1469d6bfb 935 pobj2 = PM_FP->fo_func->f_co->co_names->val[t16];
va009039 0:65f1469d6bfb 936
va009039 0:65f1469d6bfb 937 /* Set key=val in current frame's attrs dict */
va009039 0:65f1469d6bfb 938 retval = dict_setItem((pPmObj_t)PM_FP->fo_attrs, pobj2, TOS);
va009039 0:65f1469d6bfb 939 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 940 PM_SP--;
va009039 0:65f1469d6bfb 941 continue;
va009039 0:65f1469d6bfb 942
va009039 0:65f1469d6bfb 943 #ifdef HAVE_DEL
va009039 0:65f1469d6bfb 944 case DELETE_NAME:
va009039 0:65f1469d6bfb 945 /* Get name index */
va009039 0:65f1469d6bfb 946 t16 = GET_ARG();
va009039 0:65f1469d6bfb 947
va009039 0:65f1469d6bfb 948 /* Get key */
va009039 0:65f1469d6bfb 949 pobj2 = PM_FP->fo_func->f_co->co_names->val[t16];
va009039 0:65f1469d6bfb 950
va009039 0:65f1469d6bfb 951 /* Remove key,val pair from current frame's attrs dict */
va009039 0:65f1469d6bfb 952 retval = dict_delItem((pPmObj_t)PM_FP->fo_attrs, pobj2);
va009039 0:65f1469d6bfb 953 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 954 continue;
va009039 0:65f1469d6bfb 955 #endif /* HAVE_DEL */
va009039 0:65f1469d6bfb 956
va009039 0:65f1469d6bfb 957 case UNPACK_SEQUENCE:
va009039 0:65f1469d6bfb 958 /* Get ptr to sequence */
va009039 0:65f1469d6bfb 959 pobj1 = PM_POP();
va009039 0:65f1469d6bfb 960
va009039 0:65f1469d6bfb 961 #ifdef HAVE_BYTEARRAY
va009039 0:65f1469d6bfb 962 /* If object is an instance, get the thing it contains */
va009039 0:65f1469d6bfb 963 if (OBJ_GET_TYPE(pobj1) == OBJ_TYPE_CLI)
va009039 0:65f1469d6bfb 964 {
va009039 0:65f1469d6bfb 965 retval = dict_getItem((pPmObj_t)((pPmInstance_t)pobj1)->cli_attrs,
va009039 0:65f1469d6bfb 966 PM_NONE,
va009039 0:65f1469d6bfb 967 &pobj2);
va009039 0:65f1469d6bfb 968 PM_RETURN_IF_ERROR(retval);
va009039 0:65f1469d6bfb 969 pobj1 = pobj2;
va009039 0:65f1469d6bfb 970 }
va009039 0:65f1469d6bfb 971 #endif /* HAVE_BYTEARRAY */
va009039 0:65f1469d6bfb 972
va009039 0:65f1469d6bfb 973 /*
va009039 0:65f1469d6bfb 974 * Get the length of the sequence; this will
va009039 0:65f1469d6bfb 975 * raise TypeError if obj is not a sequence.
va009039 0:65f1469d6bfb 976 *
va009039 0:65f1469d6bfb 977 * #59: Unpacking to a Dict shall not be supported
va009039 0:65f1469d6bfb 978 */
va009039 0:65f1469d6bfb 979 retval = seq_getLength(pobj1, (uint16_t *)&t16);
va009039 0:65f1469d6bfb 980 if (retval != PM_RET_OK)
va009039 0:65f1469d6bfb 981 {
va009039 0:65f1469d6bfb 982 GET_ARG();
va009039 0:65f1469d6bfb 983 break;
va009039 0:65f1469d6bfb 984 }
va009039 0:65f1469d6bfb 985
va009039 0:65f1469d6bfb 986 /* Raise ValueError if seq length does not match num args */
va009039 0:65f1469d6bfb 987 if (t16 != GET_ARG())
va009039 0:65f1469d6bfb 988 {
va009039 0:65f1469d6bfb 989 PM_RAISE(retval, PM_RET_EX_VAL);
va009039 0:65f1469d6bfb 990 break;
va009039 0:65f1469d6bfb 991 }
va009039 0:65f1469d6bfb 992
va009039 0:65f1469d6bfb 993 /* Push sequence's objs onto stack */
va009039 0:65f1469d6bfb 994 for (; --t16 >= 0;)
va009039 0:65f1469d6bfb 995 {
va009039 0:65f1469d6bfb 996 retval = seq_getSubscript(pobj1, t16, &pobj2);
va009039 0:65f1469d6bfb 997 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 998 PM_PUSH(pobj2);
va009039 0:65f1469d6bfb 999 }
va009039 0:65f1469d6bfb 1000
va009039 0:65f1469d6bfb 1001 /* Test again outside the for loop */
va009039 0:65f1469d6bfb 1002 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 1003 continue;
va009039 0:65f1469d6bfb 1004
va009039 0:65f1469d6bfb 1005 case FOR_ITER:
va009039 0:65f1469d6bfb 1006 t16 = GET_ARG();
va009039 0:65f1469d6bfb 1007
va009039 0:65f1469d6bfb 1008 #ifdef HAVE_GENERATORS
va009039 0:65f1469d6bfb 1009 /* If TOS is an instance, call next method */
va009039 0:65f1469d6bfb 1010 if (OBJ_GET_TYPE(TOS) == OBJ_TYPE_CLI)
va009039 0:65f1469d6bfb 1011 {
va009039 0:65f1469d6bfb 1012 /* Get the next() func */
va009039 0:65f1469d6bfb 1013 retval = class_getAttr(TOS, PM_NEXT_STR, &pobj1);
va009039 0:65f1469d6bfb 1014 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 1015
va009039 0:65f1469d6bfb 1016 /* Push the func and instance as an arg */
va009039 0:65f1469d6bfb 1017 pobj2 = TOS;
va009039 0:65f1469d6bfb 1018 PM_PUSH(pobj1);
va009039 0:65f1469d6bfb 1019 PM_PUSH(pobj2);
va009039 0:65f1469d6bfb 1020 t16 = 1;
va009039 0:65f1469d6bfb 1021
va009039 0:65f1469d6bfb 1022 /* Ensure pobj1 is the func */
va009039 0:65f1469d6bfb 1023 goto CALL_FUNC_FOR_ITER;
va009039 0:65f1469d6bfb 1024 }
va009039 0:65f1469d6bfb 1025 else
va009039 0:65f1469d6bfb 1026 #endif /* HAVE_GENERATORS */
va009039 0:65f1469d6bfb 1027 {
va009039 0:65f1469d6bfb 1028 /* Get the next item in the sequence iterator */
va009039 0:65f1469d6bfb 1029 retval = seqiter_getNext(TOS, &pobj2);
va009039 0:65f1469d6bfb 1030 }
va009039 0:65f1469d6bfb 1031
va009039 0:65f1469d6bfb 1032 /* Catch StopIteration early: pop iterator and break loop */
va009039 0:65f1469d6bfb 1033 if (retval == PM_RET_EX_STOP)
va009039 0:65f1469d6bfb 1034 {
va009039 0:65f1469d6bfb 1035 PM_SP--;
va009039 0:65f1469d6bfb 1036 retval = PM_RET_OK;
va009039 0:65f1469d6bfb 1037 PM_IP += t16;
va009039 0:65f1469d6bfb 1038 continue;
va009039 0:65f1469d6bfb 1039 }
va009039 0:65f1469d6bfb 1040 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 1041
va009039 0:65f1469d6bfb 1042 /* Push the next item onto the stack */
va009039 0:65f1469d6bfb 1043 PM_PUSH(pobj2);
va009039 0:65f1469d6bfb 1044 continue;
va009039 0:65f1469d6bfb 1045
va009039 0:65f1469d6bfb 1046 case STORE_ATTR:
va009039 0:65f1469d6bfb 1047 /* TOS.name = TOS1 */
va009039 0:65f1469d6bfb 1048 /* Get names index */
va009039 0:65f1469d6bfb 1049 t16 = GET_ARG();
va009039 0:65f1469d6bfb 1050
va009039 0:65f1469d6bfb 1051 /* Get attrs dict from obj */
va009039 0:65f1469d6bfb 1052 if ((OBJ_GET_TYPE(TOS) == OBJ_TYPE_FXN)
va009039 0:65f1469d6bfb 1053 || (OBJ_GET_TYPE(TOS) == OBJ_TYPE_MOD))
va009039 0:65f1469d6bfb 1054 {
va009039 0:65f1469d6bfb 1055 pobj2 = (pPmObj_t)((pPmFunc_t)TOS)->f_attrs;
va009039 0:65f1469d6bfb 1056 }
va009039 0:65f1469d6bfb 1057
va009039 0:65f1469d6bfb 1058 #ifdef HAVE_CLASSES
va009039 0:65f1469d6bfb 1059 else if (OBJ_GET_TYPE(TOS) == OBJ_TYPE_CLO)
va009039 0:65f1469d6bfb 1060 {
va009039 0:65f1469d6bfb 1061 pobj2 = (pPmObj_t)((pPmClass_t)TOS)->cl_attrs;
va009039 0:65f1469d6bfb 1062 }
va009039 0:65f1469d6bfb 1063 else if (OBJ_GET_TYPE(TOS) == OBJ_TYPE_CLI)
va009039 0:65f1469d6bfb 1064 {
va009039 0:65f1469d6bfb 1065 pobj2 = (pPmObj_t)((pPmInstance_t)TOS)->cli_attrs;
va009039 0:65f1469d6bfb 1066 }
va009039 0:65f1469d6bfb 1067 else if (OBJ_GET_TYPE(TOS) == OBJ_TYPE_MTH)
va009039 0:65f1469d6bfb 1068 {
va009039 0:65f1469d6bfb 1069 pobj2 = (pPmObj_t)((pPmMethod_t)TOS)->m_attrs;
va009039 0:65f1469d6bfb 1070 }
va009039 0:65f1469d6bfb 1071 #endif /* HAVE_CLASSES */
va009039 0:65f1469d6bfb 1072
va009039 0:65f1469d6bfb 1073 /* Other types result in an AttributeError */
va009039 0:65f1469d6bfb 1074 else
va009039 0:65f1469d6bfb 1075 {
va009039 0:65f1469d6bfb 1076 PM_RAISE(retval, PM_RET_EX_ATTR);
va009039 0:65f1469d6bfb 1077 break;
va009039 0:65f1469d6bfb 1078 }
va009039 0:65f1469d6bfb 1079
va009039 0:65f1469d6bfb 1080 /* If attrs is not a dict, raise SystemError */
va009039 0:65f1469d6bfb 1081 if (OBJ_GET_TYPE(pobj2) != OBJ_TYPE_DIC)
va009039 0:65f1469d6bfb 1082 {
va009039 0:65f1469d6bfb 1083 PM_RAISE(retval, PM_RET_EX_SYS);
va009039 0:65f1469d6bfb 1084 break;
va009039 0:65f1469d6bfb 1085 }
va009039 0:65f1469d6bfb 1086
va009039 0:65f1469d6bfb 1087 /* Get name/key obj */
va009039 0:65f1469d6bfb 1088 pobj3 = PM_FP->fo_func->f_co->co_names->val[t16];
va009039 0:65f1469d6bfb 1089
va009039 0:65f1469d6bfb 1090 /* Set key=val in obj's dict */
va009039 0:65f1469d6bfb 1091 retval = dict_setItem(pobj2, pobj3, TOS1);
va009039 0:65f1469d6bfb 1092 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 1093 PM_SP -= 2;
va009039 0:65f1469d6bfb 1094 continue;
va009039 0:65f1469d6bfb 1095
va009039 0:65f1469d6bfb 1096 #ifdef HAVE_DEL
va009039 0:65f1469d6bfb 1097 case DELETE_ATTR:
va009039 0:65f1469d6bfb 1098 /* del TOS.name */
va009039 0:65f1469d6bfb 1099 /* Get names index */
va009039 0:65f1469d6bfb 1100 t16 = GET_ARG();
va009039 0:65f1469d6bfb 1101
va009039 0:65f1469d6bfb 1102 /* Get attrs dict from obj */
va009039 0:65f1469d6bfb 1103 if ((OBJ_GET_TYPE(TOS) == OBJ_TYPE_FXN)
va009039 0:65f1469d6bfb 1104 || (OBJ_GET_TYPE(TOS) == OBJ_TYPE_MOD))
va009039 0:65f1469d6bfb 1105 {
va009039 0:65f1469d6bfb 1106 pobj2 = (pPmObj_t)((pPmFunc_t)TOS)->f_attrs;
va009039 0:65f1469d6bfb 1107 }
va009039 0:65f1469d6bfb 1108
va009039 0:65f1469d6bfb 1109 #ifdef HAVE_CLASSES
va009039 0:65f1469d6bfb 1110 else if (OBJ_GET_TYPE(TOS) == OBJ_TYPE_CLO)
va009039 0:65f1469d6bfb 1111 {
va009039 0:65f1469d6bfb 1112 pobj2 = (pPmObj_t)((pPmClass_t)TOS)->cl_attrs;
va009039 0:65f1469d6bfb 1113 }
va009039 0:65f1469d6bfb 1114 else if (OBJ_GET_TYPE(TOS) == OBJ_TYPE_CLI)
va009039 0:65f1469d6bfb 1115 {
va009039 0:65f1469d6bfb 1116 pobj2 = (pPmObj_t)((pPmInstance_t)TOS)->cli_attrs;
va009039 0:65f1469d6bfb 1117 }
va009039 0:65f1469d6bfb 1118 else if (OBJ_GET_TYPE(TOS) == OBJ_TYPE_MTH)
va009039 0:65f1469d6bfb 1119 {
va009039 0:65f1469d6bfb 1120 pobj2 = (pPmObj_t)((pPmMethod_t)TOS)->m_attrs;
va009039 0:65f1469d6bfb 1121 }
va009039 0:65f1469d6bfb 1122 #endif /* HAVE_CLASSES */
va009039 0:65f1469d6bfb 1123
va009039 0:65f1469d6bfb 1124 /* Other types result in an AttributeError */
va009039 0:65f1469d6bfb 1125 else
va009039 0:65f1469d6bfb 1126 {
va009039 0:65f1469d6bfb 1127 PM_RAISE(retval, PM_RET_EX_ATTR);
va009039 0:65f1469d6bfb 1128 break;
va009039 0:65f1469d6bfb 1129 }
va009039 0:65f1469d6bfb 1130
va009039 0:65f1469d6bfb 1131 /* If attrs is not a dict, raise SystemError */
va009039 0:65f1469d6bfb 1132 if (OBJ_GET_TYPE(pobj2) != OBJ_TYPE_DIC)
va009039 0:65f1469d6bfb 1133 {
va009039 0:65f1469d6bfb 1134 PM_RAISE(retval, PM_RET_EX_SYS);
va009039 0:65f1469d6bfb 1135 break;
va009039 0:65f1469d6bfb 1136 }
va009039 0:65f1469d6bfb 1137
va009039 0:65f1469d6bfb 1138 /* Get name/key obj */
va009039 0:65f1469d6bfb 1139 pobj3 = PM_FP->fo_func->f_co->co_names->val[t16];
va009039 0:65f1469d6bfb 1140
va009039 0:65f1469d6bfb 1141 /* Remove key,val from obj's dict */
va009039 0:65f1469d6bfb 1142 retval = dict_delItem(pobj2, pobj3);
va009039 0:65f1469d6bfb 1143
va009039 0:65f1469d6bfb 1144 /* Raise an AttributeError if key is not found */
va009039 0:65f1469d6bfb 1145 if (retval == PM_RET_EX_KEY)
va009039 0:65f1469d6bfb 1146 {
va009039 0:65f1469d6bfb 1147 PM_RAISE(retval, PM_RET_EX_ATTR);
va009039 0:65f1469d6bfb 1148 }
va009039 0:65f1469d6bfb 1149
va009039 0:65f1469d6bfb 1150 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 1151 PM_SP--;
va009039 0:65f1469d6bfb 1152 continue;
va009039 0:65f1469d6bfb 1153 #endif /* HAVE_DEL */
va009039 0:65f1469d6bfb 1154
va009039 0:65f1469d6bfb 1155 case STORE_GLOBAL:
va009039 0:65f1469d6bfb 1156 /* Get name index */
va009039 0:65f1469d6bfb 1157 t16 = GET_ARG();
va009039 0:65f1469d6bfb 1158
va009039 0:65f1469d6bfb 1159 /* Get key */
va009039 0:65f1469d6bfb 1160 pobj2 = PM_FP->fo_func->f_co->co_names->val[t16];
va009039 0:65f1469d6bfb 1161
va009039 0:65f1469d6bfb 1162 /* Set key=val in global dict */
va009039 0:65f1469d6bfb 1163 retval = dict_setItem((pPmObj_t)PM_FP->fo_globals, pobj2, TOS);
va009039 0:65f1469d6bfb 1164 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 1165 PM_SP--;
va009039 0:65f1469d6bfb 1166 continue;
va009039 0:65f1469d6bfb 1167
va009039 0:65f1469d6bfb 1168 #ifdef HAVE_DEL
va009039 0:65f1469d6bfb 1169 case DELETE_GLOBAL:
va009039 0:65f1469d6bfb 1170 /* Get name index */
va009039 0:65f1469d6bfb 1171 t16 = GET_ARG();
va009039 0:65f1469d6bfb 1172
va009039 0:65f1469d6bfb 1173 /* Get key */
va009039 0:65f1469d6bfb 1174 pobj2 = PM_FP->fo_func->f_co->co_names->val[t16];
va009039 0:65f1469d6bfb 1175
va009039 0:65f1469d6bfb 1176 /* Remove key,val from globals */
va009039 0:65f1469d6bfb 1177 retval = dict_delItem((pPmObj_t)PM_FP->fo_globals, pobj2);
va009039 0:65f1469d6bfb 1178 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 1179 continue;
va009039 0:65f1469d6bfb 1180 #endif /* HAVE_DEL */
va009039 0:65f1469d6bfb 1181
va009039 0:65f1469d6bfb 1182 case DUP_TOPX:
va009039 0:65f1469d6bfb 1183 t16 = GET_ARG();
va009039 0:65f1469d6bfb 1184 C_ASSERT(t16 <= 3);
va009039 0:65f1469d6bfb 1185
va009039 0:65f1469d6bfb 1186 pobj1 = TOS;
va009039 0:65f1469d6bfb 1187 pobj2 = TOS1;
va009039 0:65f1469d6bfb 1188 pobj3 = TOS2;
va009039 0:65f1469d6bfb 1189 if (t16 >= 3)
va009039 0:65f1469d6bfb 1190 PM_PUSH(pobj3);
va009039 0:65f1469d6bfb 1191 if (t16 >= 2)
va009039 0:65f1469d6bfb 1192 PM_PUSH(pobj2);
va009039 0:65f1469d6bfb 1193 if (t16 >= 1)
va009039 0:65f1469d6bfb 1194 PM_PUSH(pobj1);
va009039 0:65f1469d6bfb 1195 continue;
va009039 0:65f1469d6bfb 1196
va009039 0:65f1469d6bfb 1197 case LOAD_CONST:
va009039 0:65f1469d6bfb 1198 /* Get const's index in CO */
va009039 0:65f1469d6bfb 1199 t16 = GET_ARG();
va009039 0:65f1469d6bfb 1200
va009039 0:65f1469d6bfb 1201 /* Push const on stack */
va009039 0:65f1469d6bfb 1202 PM_PUSH(PM_FP->fo_func->f_co->co_consts->val[t16]);
va009039 0:65f1469d6bfb 1203 continue;
va009039 0:65f1469d6bfb 1204
va009039 0:65f1469d6bfb 1205 case LOAD_NAME:
va009039 0:65f1469d6bfb 1206 /* Get name index */
va009039 0:65f1469d6bfb 1207 t16 = GET_ARG();
va009039 0:65f1469d6bfb 1208
va009039 0:65f1469d6bfb 1209 /* Get name from names tuple */
va009039 0:65f1469d6bfb 1210 pobj1 = PM_FP->fo_func->f_co->co_names->val[t16];
va009039 0:65f1469d6bfb 1211
va009039 0:65f1469d6bfb 1212 /* Get value from frame's attrs dict */
va009039 0:65f1469d6bfb 1213 retval = dict_getItem((pPmObj_t)PM_FP->fo_attrs, pobj1, &pobj2);
va009039 0:65f1469d6bfb 1214 if (retval == PM_RET_EX_KEY)
va009039 0:65f1469d6bfb 1215 {
va009039 0:65f1469d6bfb 1216 /* Get val from globals */
va009039 0:65f1469d6bfb 1217 retval = dict_getItem((pPmObj_t)PM_FP->fo_globals,
va009039 0:65f1469d6bfb 1218 pobj1, &pobj2);
va009039 0:65f1469d6bfb 1219
va009039 0:65f1469d6bfb 1220 /* Check for name in the builtins module if it is loaded */
va009039 0:65f1469d6bfb 1221 if ((retval == PM_RET_EX_KEY) && (PM_PBUILTINS != C_NULL))
va009039 0:65f1469d6bfb 1222 {
va009039 0:65f1469d6bfb 1223 /* Get val from builtins */
va009039 0:65f1469d6bfb 1224 retval = dict_getItem(PM_PBUILTINS, pobj1, &pobj2);
va009039 0:65f1469d6bfb 1225 if (retval == PM_RET_EX_KEY)
va009039 0:65f1469d6bfb 1226 {
va009039 0:65f1469d6bfb 1227 /* Name not defined, raise NameError */
va009039 0:65f1469d6bfb 1228 PM_RAISE(retval, PM_RET_EX_NAME);
va009039 0:65f1469d6bfb 1229 break;
va009039 0:65f1469d6bfb 1230 }
va009039 0:65f1469d6bfb 1231 }
va009039 0:65f1469d6bfb 1232 }
va009039 0:65f1469d6bfb 1233 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 1234 PM_PUSH(pobj2);
va009039 0:65f1469d6bfb 1235 continue;
va009039 0:65f1469d6bfb 1236
va009039 0:65f1469d6bfb 1237 case BUILD_TUPLE:
va009039 0:65f1469d6bfb 1238 /* Get num items */
va009039 0:65f1469d6bfb 1239 t16 = GET_ARG();
va009039 0:65f1469d6bfb 1240 retval = tuple_new(t16, &pobj1);
va009039 0:65f1469d6bfb 1241 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 1242
va009039 0:65f1469d6bfb 1243 /* Fill tuple with ptrs to objs */
va009039 0:65f1469d6bfb 1244 for (; --t16 >= 0;)
va009039 0:65f1469d6bfb 1245 {
va009039 0:65f1469d6bfb 1246 ((pPmTuple_t)pobj1)->val[t16] = PM_POP();
va009039 0:65f1469d6bfb 1247 }
va009039 0:65f1469d6bfb 1248 PM_PUSH(pobj1);
va009039 0:65f1469d6bfb 1249 continue;
va009039 0:65f1469d6bfb 1250
va009039 0:65f1469d6bfb 1251 case BUILD_LIST:
va009039 0:65f1469d6bfb 1252 t16 = GET_ARG();
va009039 0:65f1469d6bfb 1253 retval = list_new(&pobj1);
va009039 0:65f1469d6bfb 1254 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 1255 for (; --t16 >= 0;)
va009039 0:65f1469d6bfb 1256 {
va009039 0:65f1469d6bfb 1257 /* Insert obj into list */
va009039 0:65f1469d6bfb 1258 heap_gcPushTempRoot(pobj1, &objid);
va009039 0:65f1469d6bfb 1259 retval = list_insert(pobj1, 0, TOS);
va009039 0:65f1469d6bfb 1260 heap_gcPopTempRoot(objid);
va009039 0:65f1469d6bfb 1261 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 1262 PM_SP--;
va009039 0:65f1469d6bfb 1263 }
va009039 0:65f1469d6bfb 1264 /* Test again outside for loop */
va009039 0:65f1469d6bfb 1265 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 1266
va009039 0:65f1469d6bfb 1267 /* push list onto stack */
va009039 0:65f1469d6bfb 1268 PM_PUSH(pobj1);
va009039 0:65f1469d6bfb 1269 continue;
va009039 0:65f1469d6bfb 1270
va009039 0:65f1469d6bfb 1271 case BUILD_MAP:
va009039 0:65f1469d6bfb 1272 /* Argument is ignored */
va009039 0:65f1469d6bfb 1273 t16 = GET_ARG();
va009039 0:65f1469d6bfb 1274 retval = dict_new(&pobj1);
va009039 0:65f1469d6bfb 1275 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 1276 PM_PUSH(pobj1);
va009039 0:65f1469d6bfb 1277 continue;
va009039 0:65f1469d6bfb 1278
va009039 0:65f1469d6bfb 1279 case LOAD_ATTR:
va009039 0:65f1469d6bfb 1280 /* Implements TOS.attr */
va009039 0:65f1469d6bfb 1281 t16 = GET_ARG();
va009039 0:65f1469d6bfb 1282
va009039 0:65f1469d6bfb 1283 #ifdef HAVE_AUTOBOX
va009039 0:65f1469d6bfb 1284 /* Autobox the object, if necessary */
va009039 0:65f1469d6bfb 1285 retval = class_autobox(&TOS);
va009039 0:65f1469d6bfb 1286 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 1287 #endif
va009039 0:65f1469d6bfb 1288
va009039 0:65f1469d6bfb 1289 /* Get attrs dict from obj */
va009039 0:65f1469d6bfb 1290 if ((OBJ_GET_TYPE(TOS) == OBJ_TYPE_FXN) ||
va009039 0:65f1469d6bfb 1291 (OBJ_GET_TYPE(TOS) == OBJ_TYPE_MOD))
va009039 0:65f1469d6bfb 1292 {
va009039 0:65f1469d6bfb 1293 pobj1 = (pPmObj_t)((pPmFunc_t)TOS)->f_attrs;
va009039 0:65f1469d6bfb 1294 }
va009039 0:65f1469d6bfb 1295
va009039 0:65f1469d6bfb 1296 #ifdef HAVE_CLASSES
va009039 0:65f1469d6bfb 1297 else if (OBJ_GET_TYPE(TOS) == OBJ_TYPE_CLO)
va009039 0:65f1469d6bfb 1298 {
va009039 0:65f1469d6bfb 1299 pobj1 = (pPmObj_t)((pPmClass_t)TOS)->cl_attrs;
va009039 0:65f1469d6bfb 1300 }
va009039 0:65f1469d6bfb 1301 else if (OBJ_GET_TYPE(TOS) == OBJ_TYPE_CLI)
va009039 0:65f1469d6bfb 1302 {
va009039 0:65f1469d6bfb 1303 pobj1 = (pPmObj_t)((pPmInstance_t)TOS)->cli_attrs;
va009039 0:65f1469d6bfb 1304 }
va009039 0:65f1469d6bfb 1305 else if (OBJ_GET_TYPE(TOS) == OBJ_TYPE_MTH)
va009039 0:65f1469d6bfb 1306 {
va009039 0:65f1469d6bfb 1307 pobj1 = (pPmObj_t)((pPmMethod_t)TOS)->m_attrs;
va009039 0:65f1469d6bfb 1308 }
va009039 0:65f1469d6bfb 1309 #endif /* HAVE_CLASSES */
va009039 0:65f1469d6bfb 1310
va009039 0:65f1469d6bfb 1311 /* Other types result in an AttributeError */
va009039 0:65f1469d6bfb 1312 else
va009039 0:65f1469d6bfb 1313 {
va009039 0:65f1469d6bfb 1314 PM_RAISE(retval, PM_RET_EX_ATTR);
va009039 0:65f1469d6bfb 1315 break;
va009039 0:65f1469d6bfb 1316 }
va009039 0:65f1469d6bfb 1317
va009039 0:65f1469d6bfb 1318 /* If attrs is not a dict, raise SystemError */
va009039 0:65f1469d6bfb 1319 if (OBJ_GET_TYPE(pobj1) != OBJ_TYPE_DIC)
va009039 0:65f1469d6bfb 1320 {
va009039 0:65f1469d6bfb 1321 PM_RAISE(retval, PM_RET_EX_SYS);
va009039 0:65f1469d6bfb 1322 break;
va009039 0:65f1469d6bfb 1323 }
va009039 0:65f1469d6bfb 1324
va009039 0:65f1469d6bfb 1325 /* Get name */
va009039 0:65f1469d6bfb 1326 pobj2 = PM_FP->fo_func->f_co->co_names->val[t16];
va009039 0:65f1469d6bfb 1327
va009039 0:65f1469d6bfb 1328 /* Get attr with given name */
va009039 0:65f1469d6bfb 1329 retval = dict_getItem(pobj1, pobj2, &pobj3);
va009039 0:65f1469d6bfb 1330
va009039 0:65f1469d6bfb 1331 #ifdef HAVE_CLASSES
va009039 0:65f1469d6bfb 1332 /*
va009039 0:65f1469d6bfb 1333 * If attr is not found and object is a class or instance,
va009039 0:65f1469d6bfb 1334 * try to get the attribute from the class attrs or parent(s)
va009039 0:65f1469d6bfb 1335 */
va009039 0:65f1469d6bfb 1336 if ((retval == PM_RET_EX_KEY) &&
va009039 0:65f1469d6bfb 1337 ((OBJ_GET_TYPE(TOS) == OBJ_TYPE_CLO)
va009039 0:65f1469d6bfb 1338 || (OBJ_GET_TYPE(TOS) == OBJ_TYPE_CLI)))
va009039 0:65f1469d6bfb 1339 {
va009039 0:65f1469d6bfb 1340 retval = class_getAttr(TOS, pobj2, &pobj3);
va009039 0:65f1469d6bfb 1341 }
va009039 0:65f1469d6bfb 1342 #endif /* HAVE_CLASSES */
va009039 0:65f1469d6bfb 1343
va009039 0:65f1469d6bfb 1344 /* Raise an AttributeError if key is not found */
va009039 0:65f1469d6bfb 1345 if (retval == PM_RET_EX_KEY)
va009039 0:65f1469d6bfb 1346 {
va009039 0:65f1469d6bfb 1347 PM_RAISE(retval, PM_RET_EX_ATTR);
va009039 0:65f1469d6bfb 1348 }
va009039 0:65f1469d6bfb 1349 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 1350
va009039 0:65f1469d6bfb 1351 #ifdef HAVE_CLASSES
va009039 0:65f1469d6bfb 1352 /* If obj is an instance and attr is a func, create method */
va009039 0:65f1469d6bfb 1353 if ((OBJ_GET_TYPE(TOS) == OBJ_TYPE_CLI) &&
va009039 0:65f1469d6bfb 1354 (OBJ_GET_TYPE(pobj3) == OBJ_TYPE_FXN))
va009039 0:65f1469d6bfb 1355 {
va009039 0:65f1469d6bfb 1356 pobj2 = pobj3;
va009039 0:65f1469d6bfb 1357 retval = class_method(TOS, pobj2, &pobj3);
va009039 0:65f1469d6bfb 1358 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 1359 }
va009039 0:65f1469d6bfb 1360 #endif /* HAVE_CLASSES */
va009039 0:65f1469d6bfb 1361
va009039 0:65f1469d6bfb 1362 /* Put attr on the stack */
va009039 0:65f1469d6bfb 1363 TOS = pobj3;
va009039 0:65f1469d6bfb 1364 continue;
va009039 0:65f1469d6bfb 1365
va009039 0:65f1469d6bfb 1366 case COMPARE_OP:
va009039 0:65f1469d6bfb 1367 retval = PM_RET_OK;
va009039 0:65f1469d6bfb 1368 t16 = GET_ARG();
va009039 0:65f1469d6bfb 1369
va009039 0:65f1469d6bfb 1370 #ifdef HAVE_FLOAT
va009039 0:65f1469d6bfb 1371 if ((OBJ_GET_TYPE(TOS) == OBJ_TYPE_FLT)
va009039 0:65f1469d6bfb 1372 || (OBJ_GET_TYPE(TOS1) == OBJ_TYPE_FLT))
va009039 0:65f1469d6bfb 1373 {
va009039 0:65f1469d6bfb 1374 retval = float_compare(TOS1, TOS, &pobj3, (PmCompare_t)t16);
va009039 0:65f1469d6bfb 1375 PM_SP--;
va009039 0:65f1469d6bfb 1376 TOS = pobj3;
va009039 0:65f1469d6bfb 1377 continue;
va009039 0:65f1469d6bfb 1378 }
va009039 0:65f1469d6bfb 1379 #endif /* HAVE_FLOAT */
va009039 0:65f1469d6bfb 1380
va009039 0:65f1469d6bfb 1381 /* Handle all integer-to-integer (or bool) comparisons */
va009039 0:65f1469d6bfb 1382 if (((OBJ_GET_TYPE(TOS) == OBJ_TYPE_INT)
va009039 0:65f1469d6bfb 1383 || (OBJ_GET_TYPE(TOS) == OBJ_TYPE_BOOL))
va009039 0:65f1469d6bfb 1384 && ((OBJ_GET_TYPE(TOS1) == OBJ_TYPE_INT)
va009039 0:65f1469d6bfb 1385 || (OBJ_GET_TYPE(TOS1) == OBJ_TYPE_BOOL)))
va009039 0:65f1469d6bfb 1386 {
va009039 0:65f1469d6bfb 1387 int32_t a = ((pPmInt_t)TOS1)->val;
va009039 0:65f1469d6bfb 1388 int32_t b = ((pPmInt_t)TOS)->val;
va009039 0:65f1469d6bfb 1389
va009039 0:65f1469d6bfb 1390 switch (t16)
va009039 0:65f1469d6bfb 1391 {
va009039 0:65f1469d6bfb 1392 /* *INDENT-OFF* */
va009039 0:65f1469d6bfb 1393 case COMP_LT: t8 = (int8_t)(a < b); break;
va009039 0:65f1469d6bfb 1394 case COMP_LE: t8 = (int8_t)(a <= b); break;
va009039 0:65f1469d6bfb 1395 case COMP_EQ: t8 = (int8_t)(a == b); break;
va009039 0:65f1469d6bfb 1396 case COMP_NE: t8 = (int8_t)(a != b); break;
va009039 0:65f1469d6bfb 1397 case COMP_GT: t8 = (int8_t)(a > b); break;
va009039 0:65f1469d6bfb 1398 case COMP_GE: t8 = (int8_t)(a >= b); break;
va009039 0:65f1469d6bfb 1399 case COMP_IS: t8 = (int8_t)(TOS == TOS1); break;
va009039 0:65f1469d6bfb 1400 case COMP_IS_NOT: t8 = (int8_t)(TOS != TOS1);break;
va009039 0:65f1469d6bfb 1401 case COMP_IN:
va009039 0:65f1469d6bfb 1402 case COMP_NOT_IN:
va009039 0:65f1469d6bfb 1403 PM_RAISE(retval, PM_RET_EX_TYPE);
va009039 0:65f1469d6bfb 1404 break;
va009039 0:65f1469d6bfb 1405
va009039 0:65f1469d6bfb 1406 default:
va009039 0:65f1469d6bfb 1407 /* Other compares are not yet supported */
va009039 0:65f1469d6bfb 1408 PM_RAISE(retval, PM_RET_EX_SYS);
va009039 0:65f1469d6bfb 1409 break;
va009039 0:65f1469d6bfb 1410 /* *INDENT-ON* */
va009039 0:65f1469d6bfb 1411 }
va009039 0:65f1469d6bfb 1412 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 1413 pobj3 = (t8) ? PM_TRUE : PM_FALSE;
va009039 0:65f1469d6bfb 1414 }
va009039 0:65f1469d6bfb 1415
va009039 0:65f1469d6bfb 1416 /* Handle non-integer comparisons */
va009039 0:65f1469d6bfb 1417 else
va009039 0:65f1469d6bfb 1418 {
va009039 0:65f1469d6bfb 1419 retval = PM_RET_OK;
va009039 0:65f1469d6bfb 1420 switch (t16)
va009039 0:65f1469d6bfb 1421 {
va009039 0:65f1469d6bfb 1422 case COMP_EQ:
va009039 0:65f1469d6bfb 1423 case COMP_NE:
va009039 0:65f1469d6bfb 1424 /* Handle equality for non-int types */
va009039 0:65f1469d6bfb 1425 pobj3 = PM_FALSE;
va009039 0:65f1469d6bfb 1426 t8 = obj_compare(TOS, TOS1);
va009039 0:65f1469d6bfb 1427 if (((t8 == C_SAME) && (t16 == COMP_EQ))
va009039 0:65f1469d6bfb 1428 || ((t8 == C_DIFFER) && (t16 == COMP_NE)))
va009039 0:65f1469d6bfb 1429 {
va009039 0:65f1469d6bfb 1430 pobj3 = PM_TRUE;
va009039 0:65f1469d6bfb 1431 }
va009039 0:65f1469d6bfb 1432 break;
va009039 0:65f1469d6bfb 1433
va009039 0:65f1469d6bfb 1434 case COMP_IN:
va009039 0:65f1469d6bfb 1435 case COMP_NOT_IN:
va009039 0:65f1469d6bfb 1436 /* Handle membership comparisons */
va009039 0:65f1469d6bfb 1437 pobj3 = PM_FALSE;
va009039 0:65f1469d6bfb 1438 retval = obj_isIn(TOS, TOS1);
va009039 0:65f1469d6bfb 1439 if (retval == PM_RET_OK)
va009039 0:65f1469d6bfb 1440 {
va009039 0:65f1469d6bfb 1441 if (t16 == COMP_IN)
va009039 0:65f1469d6bfb 1442 {
va009039 0:65f1469d6bfb 1443 pobj3 = PM_TRUE;
va009039 0:65f1469d6bfb 1444 }
va009039 0:65f1469d6bfb 1445 }
va009039 0:65f1469d6bfb 1446 else if (retval == PM_RET_NO)
va009039 0:65f1469d6bfb 1447 {
va009039 0:65f1469d6bfb 1448 retval = PM_RET_OK;
va009039 0:65f1469d6bfb 1449 if (t16 == COMP_NOT_IN)
va009039 0:65f1469d6bfb 1450 {
va009039 0:65f1469d6bfb 1451 pobj3 = PM_TRUE;
va009039 0:65f1469d6bfb 1452 }
va009039 0:65f1469d6bfb 1453 }
va009039 0:65f1469d6bfb 1454 break;
va009039 0:65f1469d6bfb 1455
va009039 0:65f1469d6bfb 1456 case COMP_IS:
va009039 0:65f1469d6bfb 1457 pobj3 = (TOS == TOS1) ? PM_TRUE : PM_FALSE;
va009039 0:65f1469d6bfb 1458 break;
va009039 0:65f1469d6bfb 1459
va009039 0:65f1469d6bfb 1460 case COMP_IS_NOT:
va009039 0:65f1469d6bfb 1461 pobj3 = (TOS != TOS1) ? PM_TRUE : PM_FALSE;
va009039 0:65f1469d6bfb 1462 break;
va009039 0:65f1469d6bfb 1463
va009039 0:65f1469d6bfb 1464 default:
va009039 0:65f1469d6bfb 1465 /* Other comparisons are not implemented */
va009039 0:65f1469d6bfb 1466 PM_RAISE(retval, PM_RET_EX_SYS);
va009039 0:65f1469d6bfb 1467 break;
va009039 0:65f1469d6bfb 1468 }
va009039 0:65f1469d6bfb 1469 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 1470 }
va009039 0:65f1469d6bfb 1471 PM_SP--;
va009039 0:65f1469d6bfb 1472 TOS = pobj3;
va009039 0:65f1469d6bfb 1473 continue;
va009039 0:65f1469d6bfb 1474
va009039 0:65f1469d6bfb 1475 case IMPORT_NAME:
va009039 0:65f1469d6bfb 1476 /* Get name index */
va009039 0:65f1469d6bfb 1477 t16 = GET_ARG();
va009039 0:65f1469d6bfb 1478
va009039 0:65f1469d6bfb 1479 /* Get name String obj */
va009039 0:65f1469d6bfb 1480 pobj1 = PM_FP->fo_func->f_co->co_names->val[t16];
va009039 0:65f1469d6bfb 1481
va009039 0:65f1469d6bfb 1482 /* Pop unused None object */
va009039 0:65f1469d6bfb 1483 PM_SP--;
va009039 0:65f1469d6bfb 1484
va009039 0:65f1469d6bfb 1485 /* Ensure "level" is -1; no support for relative import yet */
va009039 0:65f1469d6bfb 1486 C_ASSERT(obj_compare(TOS, PM_NEGONE) == C_SAME);
va009039 0:65f1469d6bfb 1487
va009039 0:65f1469d6bfb 1488 /* #178: Fix import so modules are reused */
va009039 0:65f1469d6bfb 1489 /* Return the module if found in the modules dict (cache) */
va009039 0:65f1469d6bfb 1490 retval = dict_getItem(PM_PBUILTINS, PM_MD_STR, &pobj3);
va009039 0:65f1469d6bfb 1491 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 1492 retval = dict_getItem(pobj3, pobj1, &pobj2);
va009039 0:65f1469d6bfb 1493 if (retval == PM_RET_OK)
va009039 0:65f1469d6bfb 1494 {
va009039 0:65f1469d6bfb 1495 TOS = pobj2;
va009039 0:65f1469d6bfb 1496 continue;
va009039 0:65f1469d6bfb 1497 }
va009039 0:65f1469d6bfb 1498 if (retval != PM_RET_EX_KEY)
va009039 0:65f1469d6bfb 1499 {
va009039 0:65f1469d6bfb 1500 break;
va009039 0:65f1469d6bfb 1501 }
va009039 0:65f1469d6bfb 1502
va009039 0:65f1469d6bfb 1503 /* Load module from image */
va009039 0:65f1469d6bfb 1504 retval = mod_import(pobj1, &pobj2);
va009039 0:65f1469d6bfb 1505 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 1506
va009039 0:65f1469d6bfb 1507 /* #178: Fix import so modules are reused */
va009039 0:65f1469d6bfb 1508 /*
va009039 0:65f1469d6bfb 1509 * Store the module's attrs/globals under the module's name
va009039 0:65f1469d6bfb 1510 * in the global module dict (cache)
va009039 0:65f1469d6bfb 1511 */
va009039 0:65f1469d6bfb 1512 heap_gcPushTempRoot(pobj2, &objid);
va009039 0:65f1469d6bfb 1513 retval = dict_setItem(pobj3, pobj1, pobj2);
va009039 0:65f1469d6bfb 1514 heap_gcPopTempRoot(objid);
va009039 0:65f1469d6bfb 1515 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 1516
va009039 0:65f1469d6bfb 1517 /* Put Module on top of stack */
va009039 0:65f1469d6bfb 1518 TOS = pobj2;
va009039 0:65f1469d6bfb 1519
va009039 0:65f1469d6bfb 1520 /* Code after here is a duplicate of CALL_FUNCTION */
va009039 0:65f1469d6bfb 1521 /* Make frame object to interpret the module's root code */
va009039 0:65f1469d6bfb 1522 heap_gcPushTempRoot(pobj2, &objid);
va009039 0:65f1469d6bfb 1523 retval = frame_new(pobj2, &pobj3);
va009039 0:65f1469d6bfb 1524 heap_gcPopTempRoot(objid);
va009039 0:65f1469d6bfb 1525 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 1526
va009039 0:65f1469d6bfb 1527 /* No arguments to pass */
va009039 0:65f1469d6bfb 1528
va009039 0:65f1469d6bfb 1529 /* Keep ref to current frame */
va009039 0:65f1469d6bfb 1530 ((pPmFrame_t)pobj3)->fo_back = PM_FP;
va009039 0:65f1469d6bfb 1531
va009039 0:65f1469d6bfb 1532 /* Handle to have None popped on return */
va009039 0:65f1469d6bfb 1533 ((pPmFrame_t)pobj3)->fo_isImport = (uint8_t)1;
va009039 0:65f1469d6bfb 1534
va009039 0:65f1469d6bfb 1535 /* Set new frame */
va009039 0:65f1469d6bfb 1536 PM_FP = (pPmFrame_t)pobj3;
va009039 0:65f1469d6bfb 1537 continue;
va009039 0:65f1469d6bfb 1538
va009039 0:65f1469d6bfb 1539 #ifdef HAVE_IMPORTS
va009039 0:65f1469d6bfb 1540 case IMPORT_FROM:
va009039 0:65f1469d6bfb 1541 /* #102: Implement the remaining IMPORT_ bytecodes */
va009039 0:65f1469d6bfb 1542 /* Expect the module on the top of the stack */
va009039 0:65f1469d6bfb 1543 C_ASSERT(OBJ_GET_TYPE(TOS) == OBJ_TYPE_MOD);
va009039 0:65f1469d6bfb 1544 pobj1 = TOS;
va009039 0:65f1469d6bfb 1545
va009039 0:65f1469d6bfb 1546 /* Get the name of the object to import */
va009039 0:65f1469d6bfb 1547 t16 = GET_ARG();
va009039 0:65f1469d6bfb 1548 pobj2 = PM_FP->fo_func->f_co->co_names->val[t16];
va009039 0:65f1469d6bfb 1549
va009039 0:65f1469d6bfb 1550 /* Get the object from the module's attributes */
va009039 0:65f1469d6bfb 1551 retval = dict_getItem((pPmObj_t)((pPmFunc_t)pobj1)->f_attrs,
va009039 0:65f1469d6bfb 1552 pobj2, &pobj3);
va009039 0:65f1469d6bfb 1553 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 1554
va009039 0:65f1469d6bfb 1555 /* Push the object onto the top of the stack */
va009039 0:65f1469d6bfb 1556 PM_PUSH(pobj3);
va009039 0:65f1469d6bfb 1557 continue;
va009039 0:65f1469d6bfb 1558 #endif /* HAVE_IMPORTS */
va009039 0:65f1469d6bfb 1559
va009039 0:65f1469d6bfb 1560 case JUMP_FORWARD:
va009039 0:65f1469d6bfb 1561 t16 = GET_ARG();
va009039 0:65f1469d6bfb 1562 PM_IP += t16;
va009039 0:65f1469d6bfb 1563 continue;
va009039 0:65f1469d6bfb 1564
va009039 0:65f1469d6bfb 1565 case JUMP_IF_FALSE:
va009039 0:65f1469d6bfb 1566 t16 = GET_ARG();
va009039 0:65f1469d6bfb 1567 if (obj_isFalse(TOS))
va009039 0:65f1469d6bfb 1568 {
va009039 0:65f1469d6bfb 1569 PM_IP += t16;
va009039 0:65f1469d6bfb 1570 }
va009039 0:65f1469d6bfb 1571 continue;
va009039 0:65f1469d6bfb 1572
va009039 0:65f1469d6bfb 1573 case JUMP_IF_TRUE:
va009039 0:65f1469d6bfb 1574 t16 = GET_ARG();
va009039 0:65f1469d6bfb 1575 if (!obj_isFalse(TOS))
va009039 0:65f1469d6bfb 1576 {
va009039 0:65f1469d6bfb 1577 PM_IP += t16;
va009039 0:65f1469d6bfb 1578 }
va009039 0:65f1469d6bfb 1579 continue;
va009039 0:65f1469d6bfb 1580
va009039 0:65f1469d6bfb 1581 case JUMP_ABSOLUTE:
va009039 0:65f1469d6bfb 1582 case CONTINUE_LOOP:
va009039 0:65f1469d6bfb 1583 /* Get target offset (bytes) */
va009039 0:65f1469d6bfb 1584 t16 = GET_ARG();
va009039 0:65f1469d6bfb 1585
va009039 0:65f1469d6bfb 1586 /* Jump to base_ip + arg */
va009039 0:65f1469d6bfb 1587 PM_IP = PM_FP->fo_func->f_co->co_codeaddr + t16;
va009039 0:65f1469d6bfb 1588 continue;
va009039 0:65f1469d6bfb 1589
va009039 0:65f1469d6bfb 1590 case LOAD_GLOBAL:
va009039 0:65f1469d6bfb 1591 /* Get name */
va009039 0:65f1469d6bfb 1592 t16 = GET_ARG();
va009039 0:65f1469d6bfb 1593 pobj1 = PM_FP->fo_func->f_co->co_names->val[t16];
va009039 0:65f1469d6bfb 1594
va009039 0:65f1469d6bfb 1595 /* Try globals first */
va009039 0:65f1469d6bfb 1596 retval = dict_getItem((pPmObj_t)PM_FP->fo_globals,
va009039 0:65f1469d6bfb 1597 pobj1, &pobj2);
va009039 0:65f1469d6bfb 1598
va009039 0:65f1469d6bfb 1599 /* If that didn't work, try builtins */
va009039 0:65f1469d6bfb 1600 if (retval == PM_RET_EX_KEY)
va009039 0:65f1469d6bfb 1601 {
va009039 0:65f1469d6bfb 1602 retval = dict_getItem(PM_PBUILTINS, pobj1, &pobj2);
va009039 0:65f1469d6bfb 1603
va009039 0:65f1469d6bfb 1604 /* No such global, raise NameError */
va009039 0:65f1469d6bfb 1605 if (retval == PM_RET_EX_KEY)
va009039 0:65f1469d6bfb 1606 {
va009039 0:65f1469d6bfb 1607 PM_RAISE(retval, PM_RET_EX_NAME);
va009039 0:65f1469d6bfb 1608 break;
va009039 0:65f1469d6bfb 1609 }
va009039 0:65f1469d6bfb 1610 }
va009039 0:65f1469d6bfb 1611 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 1612 PM_PUSH(pobj2);
va009039 0:65f1469d6bfb 1613 continue;
va009039 0:65f1469d6bfb 1614
va009039 0:65f1469d6bfb 1615 case SETUP_LOOP:
va009039 0:65f1469d6bfb 1616 {
va009039 0:65f1469d6bfb 1617 uint8_t *pchunk;
va009039 0:65f1469d6bfb 1618
va009039 0:65f1469d6bfb 1619 /* Get block span (bytes) */
va009039 0:65f1469d6bfb 1620 t16 = GET_ARG();
va009039 0:65f1469d6bfb 1621
va009039 0:65f1469d6bfb 1622 /* Create block */
va009039 0:65f1469d6bfb 1623 retval = heap_getChunk(sizeof(PmBlock_t), &pchunk);
va009039 0:65f1469d6bfb 1624 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 1625 pobj1 = (pPmObj_t)pchunk;
va009039 0:65f1469d6bfb 1626 OBJ_SET_TYPE(pobj1, OBJ_TYPE_BLK);
va009039 0:65f1469d6bfb 1627
va009039 0:65f1469d6bfb 1628 /* Store current stack pointer */
va009039 0:65f1469d6bfb 1629 ((pPmBlock_t)pobj1)->b_sp = PM_SP;
va009039 0:65f1469d6bfb 1630
va009039 0:65f1469d6bfb 1631 /* Default handler is to exit block/loop */
va009039 0:65f1469d6bfb 1632 ((pPmBlock_t)pobj1)->b_handler = PM_IP + t16;
va009039 0:65f1469d6bfb 1633 ((pPmBlock_t)pobj1)->b_type = B_LOOP;
va009039 0:65f1469d6bfb 1634
va009039 0:65f1469d6bfb 1635 /* Insert block into blockstack */
va009039 0:65f1469d6bfb 1636 ((pPmBlock_t)pobj1)->next = PM_FP->fo_blockstack;
va009039 0:65f1469d6bfb 1637 PM_FP->fo_blockstack = (pPmBlock_t)pobj1;
va009039 0:65f1469d6bfb 1638 continue;
va009039 0:65f1469d6bfb 1639 }
va009039 0:65f1469d6bfb 1640
va009039 0:65f1469d6bfb 1641 case LOAD_FAST:
va009039 0:65f1469d6bfb 1642 t16 = GET_ARG();
va009039 0:65f1469d6bfb 1643 PM_PUSH(PM_FP->fo_locals[t16]);
va009039 0:65f1469d6bfb 1644 continue;
va009039 0:65f1469d6bfb 1645
va009039 0:65f1469d6bfb 1646 case STORE_FAST:
va009039 0:65f1469d6bfb 1647 t16 = GET_ARG();
va009039 0:65f1469d6bfb 1648 PM_FP->fo_locals[t16] = PM_POP();
va009039 0:65f1469d6bfb 1649 continue;
va009039 0:65f1469d6bfb 1650
va009039 0:65f1469d6bfb 1651 #ifdef HAVE_DEL
va009039 0:65f1469d6bfb 1652 case DELETE_FAST:
va009039 0:65f1469d6bfb 1653 t16 = GET_ARG();
va009039 0:65f1469d6bfb 1654 PM_FP->fo_locals[t16] = PM_NONE;
va009039 0:65f1469d6bfb 1655 continue;
va009039 0:65f1469d6bfb 1656 #endif /* HAVE_DEL */
va009039 0:65f1469d6bfb 1657
va009039 0:65f1469d6bfb 1658 #ifdef HAVE_ASSERT
va009039 0:65f1469d6bfb 1659 case RAISE_VARARGS:
va009039 0:65f1469d6bfb 1660 t16 = GET_ARG();
va009039 0:65f1469d6bfb 1661
va009039 0:65f1469d6bfb 1662 /* Only supports taking 1 arg for now */
va009039 0:65f1469d6bfb 1663 if (t16 != 1)
va009039 0:65f1469d6bfb 1664 {
va009039 0:65f1469d6bfb 1665 PM_RAISE(retval, PM_RET_EX_SYS);
va009039 0:65f1469d6bfb 1666 break;
va009039 0:65f1469d6bfb 1667 }
va009039 0:65f1469d6bfb 1668
va009039 0:65f1469d6bfb 1669 /* Load Exception class from builtins */
va009039 0:65f1469d6bfb 1670 retval = dict_getItem(PM_PBUILTINS, PM_EXCEPTION_STR, &pobj2);
va009039 0:65f1469d6bfb 1671 if (retval != PM_RET_OK)
va009039 0:65f1469d6bfb 1672 {
va009039 0:65f1469d6bfb 1673 PM_RAISE(retval, PM_RET_EX_SYS);
va009039 0:65f1469d6bfb 1674 break;
va009039 0:65f1469d6bfb 1675 }
va009039 0:65f1469d6bfb 1676
va009039 0:65f1469d6bfb 1677 /* Raise TypeError if TOS is not an instance of Exception */
va009039 0:65f1469d6bfb 1678 pobj1 = TOS;
va009039 0:65f1469d6bfb 1679 if ((OBJ_GET_TYPE(pobj1) != OBJ_TYPE_CLO)
va009039 0:65f1469d6bfb 1680 || !class_isSubclass(pobj1, pobj2))
va009039 0:65f1469d6bfb 1681 {
va009039 0:65f1469d6bfb 1682 PM_RAISE(retval, PM_RET_EX_TYPE);
va009039 0:65f1469d6bfb 1683 break;
va009039 0:65f1469d6bfb 1684 }
va009039 0:65f1469d6bfb 1685
va009039 0:65f1469d6bfb 1686 /* Push the traceback, parameter and exception object */
va009039 0:65f1469d6bfb 1687 TOS = PM_NONE;
va009039 0:65f1469d6bfb 1688 PM_PUSH(PM_NONE);
va009039 0:65f1469d6bfb 1689 PM_PUSH(pobj1);
va009039 0:65f1469d6bfb 1690
va009039 0:65f1469d6bfb 1691 /* Get the exception's code attr */
va009039 0:65f1469d6bfb 1692 retval = dict_getItem((pPmObj_t)((pPmClass_t)pobj1)->cl_attrs,
va009039 0:65f1469d6bfb 1693 PM_CODE_STR, &pobj2);
va009039 0:65f1469d6bfb 1694 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 1695
va009039 0:65f1469d6bfb 1696 /* Raise exception by breaking with retval set to code */
va009039 0:65f1469d6bfb 1697 PM_RAISE(retval, (PmReturn_t)(((pPmInt_t)pobj2)->val & 0xFF));
va009039 0:65f1469d6bfb 1698 break;
va009039 0:65f1469d6bfb 1699 #endif /* HAVE_ASSERT */
va009039 0:65f1469d6bfb 1700
va009039 0:65f1469d6bfb 1701 case CALL_FUNCTION:
va009039 0:65f1469d6bfb 1702 /* Get num args */
va009039 0:65f1469d6bfb 1703 t16 = GET_ARG();
va009039 0:65f1469d6bfb 1704
va009039 0:65f1469d6bfb 1705 /* Ensure no keyword args */
va009039 0:65f1469d6bfb 1706 if ((t16 & (uint16_t)0xFF00) != 0)
va009039 0:65f1469d6bfb 1707 {
va009039 0:65f1469d6bfb 1708 PM_RAISE(retval, PM_RET_EX_SYS);
va009039 0:65f1469d6bfb 1709 break;
va009039 0:65f1469d6bfb 1710 }
va009039 0:65f1469d6bfb 1711
va009039 0:65f1469d6bfb 1712 /* Get the callable */
va009039 0:65f1469d6bfb 1713 pobj1 = STACK(t16);
va009039 0:65f1469d6bfb 1714
va009039 0:65f1469d6bfb 1715 /* Useless push to get temp-roots stack level used in cleanup */
va009039 0:65f1469d6bfb 1716 heap_gcPushTempRoot(pobj1, &objid);
va009039 0:65f1469d6bfb 1717
va009039 0:65f1469d6bfb 1718 C_DEBUG_PRINT(VERBOSITY_LOW,
va009039 0:65f1469d6bfb 1719 "interpret(), CALL_FUNCTION on <obj type=%d @ %p>\n",
va009039 0:65f1469d6bfb 1720 OBJ_GET_TYPE(pobj1), pobj1);
va009039 0:65f1469d6bfb 1721
va009039 0:65f1469d6bfb 1722 #ifdef HAVE_GENERATORS
va009039 0:65f1469d6bfb 1723 /* If the callable is a generator function (can't be native) */
va009039 0:65f1469d6bfb 1724 if ((OBJ_GET_TYPE(pobj1) == OBJ_TYPE_FXN)
va009039 0:65f1469d6bfb 1725 && (OBJ_GET_TYPE(((pPmFunc_t)pobj1)->f_co) == OBJ_TYPE_COB)
va009039 0:65f1469d6bfb 1726 && (((pPmFunc_t)pobj1)->f_co->co_flags & CO_GENERATOR))
va009039 0:65f1469d6bfb 1727 {
va009039 0:65f1469d6bfb 1728 #ifdef HAVE_DEFAULTARGS
va009039 0:65f1469d6bfb 1729 /* Num required args := argcount - num default args */
va009039 0:65f1469d6bfb 1730 t8 = ((pPmFunc_t)pobj1)->f_co->co_argcount;
va009039 0:65f1469d6bfb 1731 if (((pPmFunc_t)pobj1)->f_defaultargs != C_NULL)
va009039 0:65f1469d6bfb 1732 {
va009039 0:65f1469d6bfb 1733 t8 -= ((pPmTuple_t)((pPmFunc_t)pobj1)->f_defaultargs)->
va009039 0:65f1469d6bfb 1734 length;
va009039 0:65f1469d6bfb 1735 }
va009039 0:65f1469d6bfb 1736
va009039 0:65f1469d6bfb 1737 /*
va009039 0:65f1469d6bfb 1738 * Raise a TypeError if num args passed
va009039 0:65f1469d6bfb 1739 * is more than allowed or less than required
va009039 0:65f1469d6bfb 1740 */
va009039 0:65f1469d6bfb 1741 if (((t16 & ((uint8_t)0xFF))
va009039 0:65f1469d6bfb 1742 > ((pPmFunc_t)pobj1)->f_co->co_argcount)
va009039 0:65f1469d6bfb 1743 || ((t16 & ((uint8_t)0xFF)) < t8))
va009039 0:65f1469d6bfb 1744 #else
va009039 0:65f1469d6bfb 1745 if ((t16 & ((uint8_t)0xFF)) !=
va009039 0:65f1469d6bfb 1746 ((pPmFunc_t)pobj1)->f_co->co_argcount)
va009039 0:65f1469d6bfb 1747 #endif /* HAVE_DEFAULTARGS */
va009039 0:65f1469d6bfb 1748 {
va009039 0:65f1469d6bfb 1749 PM_RAISE(retval, PM_RET_EX_TYPE);
va009039 0:65f1469d6bfb 1750 break;
va009039 0:65f1469d6bfb 1751 }
va009039 0:65f1469d6bfb 1752
va009039 0:65f1469d6bfb 1753 /* Collect the function and arguments into a tuple */
va009039 0:65f1469d6bfb 1754 retval = tuple_new(t16 + 1, &pobj2);
va009039 0:65f1469d6bfb 1755 heap_gcPushTempRoot(pobj2, &objid2);
va009039 0:65f1469d6bfb 1756 PM_GOTO_IF_ERROR(retval, CALL_FUNC_CLEANUP);
va009039 0:65f1469d6bfb 1757 sli_memcpy((uint8_t *)&((pPmTuple_t)pobj2)->val,
va009039 0:65f1469d6bfb 1758 (uint8_t *)&STACK(t16),
va009039 0:65f1469d6bfb 1759 (t16 + 1) * sizeof(pPmObj_t));
va009039 0:65f1469d6bfb 1760
va009039 0:65f1469d6bfb 1761 /* Remove old args, push func/args tuple as one arg */
va009039 0:65f1469d6bfb 1762 PM_SP -= t16;
va009039 0:65f1469d6bfb 1763 PM_PUSH(pobj2);
va009039 0:65f1469d6bfb 1764 t16 = 1;
va009039 0:65f1469d6bfb 1765
va009039 0:65f1469d6bfb 1766 /* Set pobj1 and stack to create an instance of Generator */
va009039 0:65f1469d6bfb 1767 retval = dict_getItem(PM_PBUILTINS, PM_GENERATOR_STR,
va009039 0:65f1469d6bfb 1768 &pobj1);
va009039 0:65f1469d6bfb 1769 C_ASSERT(retval == PM_RET_OK);
va009039 0:65f1469d6bfb 1770 STACK(t16) = pobj1;
va009039 0:65f1469d6bfb 1771 }
va009039 0:65f1469d6bfb 1772 #endif /* HAVE_GENERATORS */
va009039 0:65f1469d6bfb 1773
va009039 0:65f1469d6bfb 1774 #ifdef HAVE_CLASSES
va009039 0:65f1469d6bfb 1775 /* If the callable is a class, create an instance of it */
va009039 0:65f1469d6bfb 1776 if (OBJ_GET_TYPE(pobj1) == OBJ_TYPE_CLO)
va009039 0:65f1469d6bfb 1777 {
va009039 0:65f1469d6bfb 1778 /* This marks that the original callable was a class */
va009039 0:65f1469d6bfb 1779 bc = 0;
va009039 0:65f1469d6bfb 1780
va009039 0:65f1469d6bfb 1781 /* Replace class with new instance */
va009039 0:65f1469d6bfb 1782 retval = class_instantiate(pobj1, &pobj2);
va009039 0:65f1469d6bfb 1783 heap_gcPushTempRoot(pobj2, &objid2);
va009039 0:65f1469d6bfb 1784 STACK(t16) = pobj2;
va009039 0:65f1469d6bfb 1785
va009039 0:65f1469d6bfb 1786 /* If __init__ does not exist */
va009039 0:65f1469d6bfb 1787 pobj3 = C_NULL;
va009039 0:65f1469d6bfb 1788 retval = class_getAttr(pobj1, PM_INIT_STR, &pobj3);
va009039 0:65f1469d6bfb 1789 if (retval == PM_RET_EX_KEY)
va009039 0:65f1469d6bfb 1790 {
va009039 0:65f1469d6bfb 1791 /* Raise TypeError if there are args */
va009039 0:65f1469d6bfb 1792 if (t16 > 0)
va009039 0:65f1469d6bfb 1793 {
va009039 0:65f1469d6bfb 1794 PM_RAISE(retval, PM_RET_EX_TYPE);
va009039 0:65f1469d6bfb 1795 goto CALL_FUNC_CLEANUP;
va009039 0:65f1469d6bfb 1796 }
va009039 0:65f1469d6bfb 1797
va009039 0:65f1469d6bfb 1798 /* Otherwise, continue with instance */
va009039 0:65f1469d6bfb 1799 heap_gcPopTempRoot(objid);
va009039 0:65f1469d6bfb 1800 continue;
va009039 0:65f1469d6bfb 1801 }
va009039 0:65f1469d6bfb 1802 else if (retval != PM_RET_OK)
va009039 0:65f1469d6bfb 1803 {
va009039 0:65f1469d6bfb 1804 PM_GOTO_IF_ERROR(retval, CALL_FUNC_CLEANUP);
va009039 0:65f1469d6bfb 1805 }
va009039 0:65f1469d6bfb 1806
va009039 0:65f1469d6bfb 1807 /* Slide the arguments up 1 slot in the stack */
va009039 0:65f1469d6bfb 1808 PM_SP++;
va009039 0:65f1469d6bfb 1809 for (t8 = 0; t8 < t16; t8++)
va009039 0:65f1469d6bfb 1810 {
va009039 0:65f1469d6bfb 1811 STACK(t8) = STACK(t8 + 1);
va009039 0:65f1469d6bfb 1812 }
va009039 0:65f1469d6bfb 1813
va009039 0:65f1469d6bfb 1814 /* Convert __init__ to method, insert it as the callable */
va009039 0:65f1469d6bfb 1815 retval = class_method(pobj2, pobj3, &pobj1);
va009039 0:65f1469d6bfb 1816 PM_GOTO_IF_ERROR(retval, CALL_FUNC_CLEANUP);
va009039 0:65f1469d6bfb 1817 heap_gcPushTempRoot(pobj2, &objid2);
va009039 0:65f1469d6bfb 1818 STACK(t16) = pobj1;
va009039 0:65f1469d6bfb 1819 /* Fall through to call the method */
va009039 0:65f1469d6bfb 1820 }
va009039 0:65f1469d6bfb 1821
va009039 0:65f1469d6bfb 1822 if (OBJ_GET_TYPE(pobj1) == OBJ_TYPE_MTH)
va009039 0:65f1469d6bfb 1823 {
va009039 0:65f1469d6bfb 1824 /* Set the method's func to be the callable */
va009039 0:65f1469d6bfb 1825 STACK(t16) = (pPmObj_t)((pPmMethod_t)pobj1)->m_func;
va009039 0:65f1469d6bfb 1826
va009039 0:65f1469d6bfb 1827 /* Slide the arguments up 1 slot in the stack */
va009039 0:65f1469d6bfb 1828 PM_SP++;
va009039 0:65f1469d6bfb 1829 for (t8 = 0; t8 < t16; t8++)
va009039 0:65f1469d6bfb 1830 {
va009039 0:65f1469d6bfb 1831 STACK(t8) = STACK(t8 + 1);
va009039 0:65f1469d6bfb 1832 }
va009039 0:65f1469d6bfb 1833
va009039 0:65f1469d6bfb 1834 /* Insert instance as "self" arg to the method */
va009039 0:65f1469d6bfb 1835 STACK(t16++) = (pPmObj_t)((pPmMethod_t)pobj1)->m_instance;
va009039 0:65f1469d6bfb 1836
va009039 0:65f1469d6bfb 1837 /* Refresh the callable */
va009039 0:65f1469d6bfb 1838 pobj1 = (pPmObj_t)((pPmMethod_t)pobj1)->m_func;
va009039 0:65f1469d6bfb 1839 }
va009039 0:65f1469d6bfb 1840 #endif /* HAVE_CLASSES */
va009039 0:65f1469d6bfb 1841
va009039 0:65f1469d6bfb 1842 #ifdef HAVE_GENERATORS
va009039 0:65f1469d6bfb 1843 CALL_FUNC_FOR_ITER:
va009039 0:65f1469d6bfb 1844 #endif /* HAVE_GENERATORS */
va009039 0:65f1469d6bfb 1845 /* Raise a TypeError if object is not callable */
va009039 0:65f1469d6bfb 1846 if (OBJ_GET_TYPE(pobj1) != OBJ_TYPE_FXN)
va009039 0:65f1469d6bfb 1847 {
va009039 0:65f1469d6bfb 1848 PM_RAISE(retval, PM_RET_EX_TYPE);
va009039 0:65f1469d6bfb 1849 goto CALL_FUNC_CLEANUP;
va009039 0:65f1469d6bfb 1850 }
va009039 0:65f1469d6bfb 1851
va009039 0:65f1469d6bfb 1852 /* If it is a regular func (not native) */
va009039 0:65f1469d6bfb 1853 if (OBJ_GET_TYPE(((pPmFunc_t)pobj1)->f_co) == OBJ_TYPE_COB)
va009039 0:65f1469d6bfb 1854 {
va009039 0:65f1469d6bfb 1855 /*
va009039 0:65f1469d6bfb 1856 * #132 Raise TypeError if num args does not match the
va009039 0:65f1469d6bfb 1857 * code object's expected argcount
va009039 0:65f1469d6bfb 1858 */
va009039 0:65f1469d6bfb 1859
va009039 0:65f1469d6bfb 1860 #ifdef HAVE_DEFAULTARGS
va009039 0:65f1469d6bfb 1861 /* Num required args := argcount - num default args */
va009039 0:65f1469d6bfb 1862 t8 = ((pPmFunc_t)pobj1)->f_co->co_argcount;
va009039 0:65f1469d6bfb 1863 if (((pPmFunc_t)pobj1)->f_defaultargs != C_NULL)
va009039 0:65f1469d6bfb 1864 {
va009039 0:65f1469d6bfb 1865 t8 -= ((pPmTuple_t)((pPmFunc_t)pobj1)->f_defaultargs)->
va009039 0:65f1469d6bfb 1866 length;
va009039 0:65f1469d6bfb 1867 }
va009039 0:65f1469d6bfb 1868
va009039 0:65f1469d6bfb 1869 /*
va009039 0:65f1469d6bfb 1870 * Raise a TypeError if num args passed
va009039 0:65f1469d6bfb 1871 * is more than allowed or less than required
va009039 0:65f1469d6bfb 1872 */
va009039 0:65f1469d6bfb 1873 if (((t16 & ((uint8_t)0xFF))
va009039 0:65f1469d6bfb 1874 > ((pPmFunc_t)pobj1)->f_co->co_argcount)
va009039 0:65f1469d6bfb 1875 || ((t16 & ((uint8_t)0xFF)) < t8))
va009039 0:65f1469d6bfb 1876 #else
va009039 0:65f1469d6bfb 1877 if ((t16 & ((uint8_t)0xFF)) !=
va009039 0:65f1469d6bfb 1878 ((pPmFunc_t)pobj1)->f_co->co_argcount)
va009039 0:65f1469d6bfb 1879 #endif /* HAVE_DEFAULTARGS */
va009039 0:65f1469d6bfb 1880 {
va009039 0:65f1469d6bfb 1881 PM_RAISE(retval, PM_RET_EX_TYPE);
va009039 0:65f1469d6bfb 1882 break;
va009039 0:65f1469d6bfb 1883 }
va009039 0:65f1469d6bfb 1884
va009039 0:65f1469d6bfb 1885 /* Make frame object to run the func object */
va009039 0:65f1469d6bfb 1886 retval = frame_new(pobj1, &pobj2);
va009039 0:65f1469d6bfb 1887 heap_gcPushTempRoot(pobj2, &objid2);
va009039 0:65f1469d6bfb 1888 PM_GOTO_IF_ERROR(retval, CALL_FUNC_CLEANUP);
va009039 0:65f1469d6bfb 1889
va009039 0:65f1469d6bfb 1890 #ifdef HAVE_CLASSES
va009039 0:65f1469d6bfb 1891 /*
va009039 0:65f1469d6bfb 1892 * If the original callable was a class, indicate that
va009039 0:65f1469d6bfb 1893 * the frame is running the initializer so that
va009039 0:65f1469d6bfb 1894 * its return object is checked for None and ignored.
va009039 0:65f1469d6bfb 1895 */
va009039 0:65f1469d6bfb 1896 if (bc == 0)
va009039 0:65f1469d6bfb 1897 {
va009039 0:65f1469d6bfb 1898 ((pPmFrame_t)pobj2)->fo_isInit = C_TRUE;
va009039 0:65f1469d6bfb 1899 }
va009039 0:65f1469d6bfb 1900 #endif /* HAVE_CLASSES */
va009039 0:65f1469d6bfb 1901
va009039 0:65f1469d6bfb 1902 #ifdef HAVE_DEFAULTARGS
va009039 0:65f1469d6bfb 1903 /* If this func has default arguments, put them in place */
va009039 0:65f1469d6bfb 1904 if (((pPmFunc_t)pobj1)->f_defaultargs != C_NULL)
va009039 0:65f1469d6bfb 1905 {
va009039 0:65f1469d6bfb 1906 int8_t i = 0;
va009039 0:65f1469d6bfb 1907
va009039 0:65f1469d6bfb 1908 /* Copy default args into the new frame's locals */
va009039 0:65f1469d6bfb 1909 for ( /* t8 set above */ ;
va009039 0:65f1469d6bfb 1910 t8 < ((pPmFunc_t)pobj1)->f_co->co_argcount; t8++)
va009039 0:65f1469d6bfb 1911 {
va009039 0:65f1469d6bfb 1912 ((pPmFrame_t)pobj2)->fo_locals[t8] =
va009039 0:65f1469d6bfb 1913 ((pPmTuple_t)((pPmFunc_t)pobj1)->
va009039 0:65f1469d6bfb 1914 f_defaultargs)->val[i++];
va009039 0:65f1469d6bfb 1915 }
va009039 0:65f1469d6bfb 1916 }
va009039 0:65f1469d6bfb 1917 #endif /* HAVE_DEFAULTARGS */
va009039 0:65f1469d6bfb 1918
va009039 0:65f1469d6bfb 1919 /* Pass args to new frame */
va009039 0:65f1469d6bfb 1920 while (--t16 >= 0)
va009039 0:65f1469d6bfb 1921 {
va009039 0:65f1469d6bfb 1922 /*
va009039 0:65f1469d6bfb 1923 * Pop args from stack right to left,
va009039 0:65f1469d6bfb 1924 * since args are pushed left to right,
va009039 0:65f1469d6bfb 1925 */
va009039 0:65f1469d6bfb 1926 ((pPmFrame_t)pobj2)->fo_locals[t16] = PM_POP();
va009039 0:65f1469d6bfb 1927 }
va009039 0:65f1469d6bfb 1928
va009039 0:65f1469d6bfb 1929 #ifdef HAVE_CLOSURES
va009039 0:65f1469d6bfb 1930 /* #256: Add support for closures */
va009039 0:65f1469d6bfb 1931 /* Copy arguments that become cellvars */
va009039 0:65f1469d6bfb 1932 if (((pPmFunc_t)pobj1)->f_co->co_cellvars != C_NULL)
va009039 0:65f1469d6bfb 1933 {
va009039 0:65f1469d6bfb 1934 for (t8 = 0;
va009039 0:65f1469d6bfb 1935 t8 < ((pPmFunc_t)pobj1)->f_co->co_cellvars->length;
va009039 0:65f1469d6bfb 1936 t8++)
va009039 0:65f1469d6bfb 1937 {
va009039 0:65f1469d6bfb 1938 if (((pPmInt_t)((pPmFunc_t)pobj1)->
va009039 0:65f1469d6bfb 1939 f_co->co_cellvars->val[t8])->val >= 0)
va009039 0:65f1469d6bfb 1940 {
va009039 0:65f1469d6bfb 1941 ((pPmFrame_t)pobj2)->fo_locals[
va009039 0:65f1469d6bfb 1942 ((pPmFunc_t)pobj1)->f_co->co_nlocals + t8] =
va009039 0:65f1469d6bfb 1943 ((pPmFrame_t)pobj2)->fo_locals[
va009039 0:65f1469d6bfb 1944 ((pPmInt_t)(((pPmFunc_t)pobj1)->
va009039 0:65f1469d6bfb 1945 f_co->co_cellvars->val[t8]))->val
va009039 0:65f1469d6bfb 1946 ];
va009039 0:65f1469d6bfb 1947 }
va009039 0:65f1469d6bfb 1948 }
va009039 0:65f1469d6bfb 1949 }
va009039 0:65f1469d6bfb 1950
va009039 0:65f1469d6bfb 1951 /* Fill frame's freevars with references from closure */
va009039 0:65f1469d6bfb 1952 for (t8 = 0;
va009039 0:65f1469d6bfb 1953 t8 < ((pPmFunc_t)pobj1)->f_co->co_nfreevars;
va009039 0:65f1469d6bfb 1954 t8++)
va009039 0:65f1469d6bfb 1955 {
va009039 0:65f1469d6bfb 1956 C_ASSERT(((pPmFunc_t)pobj1)->f_closure != C_NULL);
va009039 0:65f1469d6bfb 1957 ((pPmFrame_t)pobj2)->fo_locals[
va009039 0:65f1469d6bfb 1958 ((pPmFunc_t)pobj1)->f_co->co_nlocals
va009039 0:65f1469d6bfb 1959 + ((((pPmFunc_t)pobj1)->f_co->co_cellvars == C_NULL) ? 0 : ((pPmFunc_t)pobj1)->f_co->co_cellvars->length)
va009039 0:65f1469d6bfb 1960 + t8] = ((pPmFunc_t)pobj1)->f_closure->val[t8];
va009039 0:65f1469d6bfb 1961 }
va009039 0:65f1469d6bfb 1962 #endif /* HAVE_CLOSURES */
va009039 0:65f1469d6bfb 1963
va009039 0:65f1469d6bfb 1964 /* Pop func obj */
va009039 0:65f1469d6bfb 1965 pobj3 = PM_POP();
va009039 0:65f1469d6bfb 1966
va009039 0:65f1469d6bfb 1967 /* Keep ref to current frame */
va009039 0:65f1469d6bfb 1968 ((pPmFrame_t)pobj2)->fo_back = PM_FP;
va009039 0:65f1469d6bfb 1969
va009039 0:65f1469d6bfb 1970 /* Set new frame */
va009039 0:65f1469d6bfb 1971 PM_FP = (pPmFrame_t)pobj2;
va009039 0:65f1469d6bfb 1972 }
va009039 0:65f1469d6bfb 1973
va009039 0:65f1469d6bfb 1974 /* If it's native func */
va009039 0:65f1469d6bfb 1975 else if (OBJ_GET_TYPE(((pPmFunc_t)pobj1)->f_co) ==
va009039 0:65f1469d6bfb 1976 OBJ_TYPE_NOB)
va009039 0:65f1469d6bfb 1977 {
va009039 0:65f1469d6bfb 1978 /* Set number of locals (arguments) */
va009039 0:65f1469d6bfb 1979 gVmGlobal.nativeframe.nf_numlocals = (uint8_t)t16;
va009039 0:65f1469d6bfb 1980
va009039 0:65f1469d6bfb 1981 /* Pop args from stack */
va009039 0:65f1469d6bfb 1982 while (--t16 >= 0)
va009039 0:65f1469d6bfb 1983 {
va009039 0:65f1469d6bfb 1984 gVmGlobal.nativeframe.nf_locals[t16] = PM_POP();
va009039 0:65f1469d6bfb 1985 }
va009039 0:65f1469d6bfb 1986
va009039 0:65f1469d6bfb 1987 /* Set flag, so the GC knows a native session is active */
va009039 0:65f1469d6bfb 1988 gVmGlobal.nativeframe.nf_active = C_TRUE;
va009039 0:65f1469d6bfb 1989
va009039 0:65f1469d6bfb 1990 #ifdef HAVE_GC
va009039 0:65f1469d6bfb 1991 /* If the heap is low on memory, run the GC */
va009039 0:65f1469d6bfb 1992 if (heap_getAvail() < HEAP_GC_NF_THRESHOLD)
va009039 0:65f1469d6bfb 1993 {
va009039 0:65f1469d6bfb 1994 retval = heap_gcRun();
va009039 0:65f1469d6bfb 1995 PM_GOTO_IF_ERROR(retval, CALL_FUNC_CLEANUP);
va009039 0:65f1469d6bfb 1996 }
va009039 0:65f1469d6bfb 1997 #endif /* HAVE_GC */
va009039 0:65f1469d6bfb 1998
va009039 0:65f1469d6bfb 1999 /* Pop the function object */
va009039 0:65f1469d6bfb 2000 PM_SP--;
va009039 0:65f1469d6bfb 2001
va009039 0:65f1469d6bfb 2002 /* Get native function index */
va009039 0:65f1469d6bfb 2003 pobj2 = (pPmObj_t)((pPmFunc_t)pobj1)->f_co;
va009039 0:65f1469d6bfb 2004 t16 = ((pPmNo_t)pobj2)->no_funcindx;
va009039 0:65f1469d6bfb 2005
va009039 0:65f1469d6bfb 2006 /*
va009039 0:65f1469d6bfb 2007 * CALL NATIVE FXN: pass caller's frame and numargs
va009039 0:65f1469d6bfb 2008 */
va009039 0:65f1469d6bfb 2009 /* Positive index is a stdlib func */
va009039 0:65f1469d6bfb 2010 if (t16 >= 0)
va009039 0:65f1469d6bfb 2011 {
va009039 0:65f1469d6bfb 2012 retval = std_nat_fxn_table[t16] (&PM_FP);
va009039 0:65f1469d6bfb 2013 }
va009039 0:65f1469d6bfb 2014
va009039 0:65f1469d6bfb 2015 /* Negative index is a usrlib func */
va009039 0:65f1469d6bfb 2016 else
va009039 0:65f1469d6bfb 2017 {
va009039 0:65f1469d6bfb 2018 retval = usr_nat_fxn_table[-t16] (&PM_FP);
va009039 0:65f1469d6bfb 2019 }
va009039 0:65f1469d6bfb 2020
va009039 0:65f1469d6bfb 2021 /*
va009039 0:65f1469d6bfb 2022 * RETURN FROM NATIVE FXN
va009039 0:65f1469d6bfb 2023 */
va009039 0:65f1469d6bfb 2024
va009039 0:65f1469d6bfb 2025 /* Clear flag, so frame will not be marked by the GC */
va009039 0:65f1469d6bfb 2026 gVmGlobal.nativeframe.nf_active = C_FALSE;
va009039 0:65f1469d6bfb 2027
va009039 0:65f1469d6bfb 2028 #ifdef HAVE_CLASSES
va009039 0:65f1469d6bfb 2029 /* If class's __init__ called, do not push a return obj */
va009039 0:65f1469d6bfb 2030 if (bc == 0)
va009039 0:65f1469d6bfb 2031 {
va009039 0:65f1469d6bfb 2032 /* Raise TypeError if returned obj was not None */
va009039 0:65f1469d6bfb 2033 if ((retval == PM_RET_OK)
va009039 0:65f1469d6bfb 2034 && (gVmGlobal.nativeframe.nf_stack != PM_NONE))
va009039 0:65f1469d6bfb 2035 {
va009039 0:65f1469d6bfb 2036 PM_RAISE(retval, PM_RET_EX_TYPE);
va009039 0:65f1469d6bfb 2037 goto CALL_FUNC_CLEANUP;
va009039 0:65f1469d6bfb 2038 }
va009039 0:65f1469d6bfb 2039 }
va009039 0:65f1469d6bfb 2040 else
va009039 0:65f1469d6bfb 2041 #endif /* HAVE_CLASSES */
va009039 0:65f1469d6bfb 2042
va009039 0:65f1469d6bfb 2043 /* If the frame pointer was switched, do nothing to TOS */
va009039 0:65f1469d6bfb 2044 if (retval == PM_RET_FRAME_SWITCH)
va009039 0:65f1469d6bfb 2045 {
va009039 0:65f1469d6bfb 2046 retval = PM_RET_OK;
va009039 0:65f1469d6bfb 2047 }
va009039 0:65f1469d6bfb 2048
va009039 0:65f1469d6bfb 2049 /* Otherwise, return the result from the native function */
va009039 0:65f1469d6bfb 2050 else
va009039 0:65f1469d6bfb 2051 {
va009039 0:65f1469d6bfb 2052 PM_PUSH(gVmGlobal.nativeframe.nf_stack);
va009039 0:65f1469d6bfb 2053 }
va009039 0:65f1469d6bfb 2054 }
va009039 0:65f1469d6bfb 2055 CALL_FUNC_CLEANUP:
va009039 0:65f1469d6bfb 2056 heap_gcPopTempRoot(objid);
va009039 0:65f1469d6bfb 2057 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 2058 continue;
va009039 0:65f1469d6bfb 2059
va009039 0:65f1469d6bfb 2060 case MAKE_FUNCTION:
va009039 0:65f1469d6bfb 2061 /* Get num default args to fxn */
va009039 0:65f1469d6bfb 2062 t16 = GET_ARG();
va009039 0:65f1469d6bfb 2063
va009039 0:65f1469d6bfb 2064 /*
va009039 0:65f1469d6bfb 2065 * The current frame's globals become the function object's
va009039 0:65f1469d6bfb 2066 * globals. The current frame is the container object
va009039 0:65f1469d6bfb 2067 * of this new function object
va009039 0:65f1469d6bfb 2068 */
va009039 0:65f1469d6bfb 2069 retval = func_new(TOS, (pPmObj_t)PM_FP->fo_globals, &pobj2);
va009039 0:65f1469d6bfb 2070 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 2071
va009039 0:65f1469d6bfb 2072 /* Put any default args in a tuple */
va009039 0:65f1469d6bfb 2073 if (t16 > 0)
va009039 0:65f1469d6bfb 2074 {
va009039 0:65f1469d6bfb 2075
va009039 0:65f1469d6bfb 2076 #ifdef HAVE_DEFAULTARGS
va009039 0:65f1469d6bfb 2077 heap_gcPushTempRoot(pobj2, &objid);
va009039 0:65f1469d6bfb 2078 retval = tuple_new(t16, &pobj3);
va009039 0:65f1469d6bfb 2079 heap_gcPopTempRoot(objid);
va009039 0:65f1469d6bfb 2080 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 2081 PM_SP--;
va009039 0:65f1469d6bfb 2082 while (--t16 >= 0)
va009039 0:65f1469d6bfb 2083 {
va009039 0:65f1469d6bfb 2084 ((pPmTuple_t)pobj3)->val[t16] = PM_POP();
va009039 0:65f1469d6bfb 2085 }
va009039 0:65f1469d6bfb 2086
va009039 0:65f1469d6bfb 2087 /* Set func's default args */
va009039 0:65f1469d6bfb 2088 ((pPmFunc_t)pobj2)->f_defaultargs = (pPmTuple_t)pobj3;
va009039 0:65f1469d6bfb 2089 #else
va009039 0:65f1469d6bfb 2090 /* Default arguments not configured in pmfeatures.h */
va009039 0:65f1469d6bfb 2091 PM_RAISE(retval, PM_RET_EX_SYS);
va009039 0:65f1469d6bfb 2092 break;
va009039 0:65f1469d6bfb 2093 #endif /* HAVE_DEFAULTARGS */
va009039 0:65f1469d6bfb 2094
va009039 0:65f1469d6bfb 2095 }
va009039 0:65f1469d6bfb 2096 else
va009039 0:65f1469d6bfb 2097 {
va009039 0:65f1469d6bfb 2098 PM_SP--;
va009039 0:65f1469d6bfb 2099 }
va009039 0:65f1469d6bfb 2100
va009039 0:65f1469d6bfb 2101 /* Push func obj */
va009039 0:65f1469d6bfb 2102 PM_PUSH(pobj2);
va009039 0:65f1469d6bfb 2103 continue;
va009039 0:65f1469d6bfb 2104
va009039 0:65f1469d6bfb 2105 #ifdef HAVE_CLOSURES
va009039 0:65f1469d6bfb 2106 case MAKE_CLOSURE:
va009039 0:65f1469d6bfb 2107 /* Get number of default args */
va009039 0:65f1469d6bfb 2108 t16 = GET_ARG();
va009039 0:65f1469d6bfb 2109 retval = func_new(TOS, (pPmObj_t)PM_FP->fo_globals, &pobj2);
va009039 0:65f1469d6bfb 2110 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 2111
va009039 0:65f1469d6bfb 2112 /* Set closure of the new function */
va009039 0:65f1469d6bfb 2113 ((pPmFunc_t)pobj2)->f_closure = (pPmTuple_t)TOS1;
va009039 0:65f1469d6bfb 2114 PM_SP -= 2;
va009039 0:65f1469d6bfb 2115
va009039 0:65f1469d6bfb 2116 /* Collect any default arguments into tuple */
va009039 0:65f1469d6bfb 2117 if (t16 > 0)
va009039 0:65f1469d6bfb 2118 {
va009039 0:65f1469d6bfb 2119 heap_gcPushTempRoot(pobj2, &objid);
va009039 0:65f1469d6bfb 2120 retval = tuple_new(t16, &pobj3);
va009039 0:65f1469d6bfb 2121 heap_gcPopTempRoot(objid);
va009039 0:65f1469d6bfb 2122 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 2123
va009039 0:65f1469d6bfb 2124 while (--t16 >= 0)
va009039 0:65f1469d6bfb 2125 {
va009039 0:65f1469d6bfb 2126 ((pPmTuple_t)pobj3)->val[t16] = PM_POP();
va009039 0:65f1469d6bfb 2127 }
va009039 0:65f1469d6bfb 2128 ((pPmFunc_t)pobj2)->f_defaultargs = (pPmTuple_t)pobj3;
va009039 0:65f1469d6bfb 2129 }
va009039 0:65f1469d6bfb 2130
va009039 0:65f1469d6bfb 2131 /* Push new func with closure */
va009039 0:65f1469d6bfb 2132 PM_PUSH(pobj2);
va009039 0:65f1469d6bfb 2133 continue;
va009039 0:65f1469d6bfb 2134
va009039 0:65f1469d6bfb 2135 case LOAD_CLOSURE:
va009039 0:65f1469d6bfb 2136 case LOAD_DEREF:
va009039 0:65f1469d6bfb 2137 /* Loads the i'th cell of free variable storage onto TOS */
va009039 0:65f1469d6bfb 2138 t16 = GET_ARG();
va009039 0:65f1469d6bfb 2139 pobj1 = PM_FP->fo_locals[PM_FP->fo_func->f_co->co_nlocals + t16];
va009039 0:65f1469d6bfb 2140 if (pobj1 == C_NULL)
va009039 0:65f1469d6bfb 2141 {
va009039 0:65f1469d6bfb 2142 PM_RAISE(retval, PM_RET_EX_SYS);
va009039 0:65f1469d6bfb 2143 break;
va009039 0:65f1469d6bfb 2144 }
va009039 0:65f1469d6bfb 2145 PM_PUSH(pobj1);
va009039 0:65f1469d6bfb 2146 continue;
va009039 0:65f1469d6bfb 2147
va009039 0:65f1469d6bfb 2148 case STORE_DEREF:
va009039 0:65f1469d6bfb 2149 /* Stores TOS into the i'th cell of free variable storage */
va009039 0:65f1469d6bfb 2150 t16 = GET_ARG();
va009039 0:65f1469d6bfb 2151 PM_FP->fo_locals[PM_FP->fo_func->f_co->co_nlocals + t16] = PM_POP();
va009039 0:65f1469d6bfb 2152 continue;
va009039 0:65f1469d6bfb 2153 #endif /* HAVE_CLOSURES */
va009039 0:65f1469d6bfb 2154
va009039 0:65f1469d6bfb 2155
va009039 0:65f1469d6bfb 2156 default:
va009039 0:65f1469d6bfb 2157 /* SystemError, unknown or unimplemented opcode */
va009039 0:65f1469d6bfb 2158 PM_RAISE(retval, PM_RET_EX_SYS);
va009039 0:65f1469d6bfb 2159 break;
va009039 0:65f1469d6bfb 2160 }
va009039 0:65f1469d6bfb 2161
va009039 0:65f1469d6bfb 2162 #ifdef HAVE_GENERATORS
va009039 0:65f1469d6bfb 2163 /* If got a StopIteration exception, check for a B_LOOP block */
va009039 0:65f1469d6bfb 2164 if (retval == PM_RET_EX_STOP)
va009039 0:65f1469d6bfb 2165 {
va009039 0:65f1469d6bfb 2166 pobj1 = (pPmObj_t)PM_FP;
va009039 0:65f1469d6bfb 2167 while ((retval == PM_RET_EX_STOP) && (pobj1 != C_NULL))
va009039 0:65f1469d6bfb 2168 {
va009039 0:65f1469d6bfb 2169 pobj2 = (pPmObj_t)((pPmFrame_t)pobj1)->fo_blockstack;
va009039 0:65f1469d6bfb 2170 while ((retval == PM_RET_EX_STOP) && (pobj2 != C_NULL))
va009039 0:65f1469d6bfb 2171 {
va009039 0:65f1469d6bfb 2172 if (((pPmBlock_t)pobj2)->b_type == B_LOOP)
va009039 0:65f1469d6bfb 2173 {
va009039 0:65f1469d6bfb 2174 /* Resume execution where the block handler says */
va009039 0:65f1469d6bfb 2175 /* Set PM_FP first, so PM_SP and PM_IP are set in the frame */
va009039 0:65f1469d6bfb 2176 PM_FP = (pPmFrame_t)pobj1;
va009039 0:65f1469d6bfb 2177 PM_SP = ((pPmBlock_t)pobj2)->b_sp;
va009039 0:65f1469d6bfb 2178 PM_IP = ((pPmBlock_t)pobj2)->b_handler;
va009039 0:65f1469d6bfb 2179 ((pPmFrame_t)pobj1)->fo_blockstack =
va009039 0:65f1469d6bfb 2180 ((pPmFrame_t)pobj1)->fo_blockstack->next;
va009039 0:65f1469d6bfb 2181 retval = PM_RET_OK;
va009039 0:65f1469d6bfb 2182 break;
va009039 0:65f1469d6bfb 2183 }
va009039 0:65f1469d6bfb 2184
va009039 0:65f1469d6bfb 2185 pobj2 = (pPmObj_t)((pPmBlock_t)pobj2)->next;
va009039 0:65f1469d6bfb 2186 }
va009039 0:65f1469d6bfb 2187 pobj1 = (pPmObj_t)((pPmFrame_t)pobj1)->fo_back;
va009039 0:65f1469d6bfb 2188 }
va009039 0:65f1469d6bfb 2189 if (retval == PM_RET_OK)
va009039 0:65f1469d6bfb 2190 {
va009039 0:65f1469d6bfb 2191 continue;
va009039 0:65f1469d6bfb 2192 }
va009039 0:65f1469d6bfb 2193 }
va009039 0:65f1469d6bfb 2194 #endif /* HAVE_GENERATORS */
va009039 0:65f1469d6bfb 2195
va009039 0:65f1469d6bfb 2196 /*
va009039 0:65f1469d6bfb 2197 * If execution reaches this point, it is because
va009039 0:65f1469d6bfb 2198 * a return value (from above) is not OK or we should exit the thread
va009039 0:65f1469d6bfb 2199 * (return of the function). In any case, remove the
va009039 0:65f1469d6bfb 2200 * current thread and reschedule.
va009039 0:65f1469d6bfb 2201 */
va009039 0:65f1469d6bfb 2202 PM_REPORT_IF_ERROR(retval);
va009039 0:65f1469d6bfb 2203
va009039 0:65f1469d6bfb 2204 /* If this is the last thread, return the error code */
va009039 0:65f1469d6bfb 2205 if ((gVmGlobal.threadList->length <= 1) && (retval != PM_RET_OK))
va009039 0:65f1469d6bfb 2206 {
va009039 0:65f1469d6bfb 2207 break;
va009039 0:65f1469d6bfb 2208 }
va009039 0:65f1469d6bfb 2209
va009039 0:65f1469d6bfb 2210 retval = list_remove((pPmObj_t)gVmGlobal.threadList,
va009039 0:65f1469d6bfb 2211 (pPmObj_t)gVmGlobal.pthread);
va009039 0:65f1469d6bfb 2212 gVmGlobal.pthread = C_NULL;
va009039 0:65f1469d6bfb 2213 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 2214
va009039 0:65f1469d6bfb 2215 retval = interp_reschedule();
va009039 0:65f1469d6bfb 2216 PM_BREAK_IF_ERROR(retval);
va009039 0:65f1469d6bfb 2217 }
va009039 0:65f1469d6bfb 2218
va009039 0:65f1469d6bfb 2219 return retval;
va009039 0:65f1469d6bfb 2220 }
va009039 0:65f1469d6bfb 2221
va009039 0:65f1469d6bfb 2222
va009039 0:65f1469d6bfb 2223 PmReturn_t
va009039 0:65f1469d6bfb 2224 interp_reschedule(void)
va009039 0:65f1469d6bfb 2225 {
va009039 0:65f1469d6bfb 2226 PmReturn_t retval = PM_RET_OK;
va009039 0:65f1469d6bfb 2227 static uint8_t threadIndex = (uint8_t)0;
va009039 0:65f1469d6bfb 2228 pPmObj_t pobj;
va009039 0:65f1469d6bfb 2229
va009039 0:65f1469d6bfb 2230 /* If there are no threads in the runnable list, null the active thread */
va009039 0:65f1469d6bfb 2231 if (gVmGlobal.threadList->length == 0)
va009039 0:65f1469d6bfb 2232 {
va009039 0:65f1469d6bfb 2233 gVmGlobal.pthread = C_NULL;
va009039 0:65f1469d6bfb 2234 }
va009039 0:65f1469d6bfb 2235
va009039 0:65f1469d6bfb 2236 /* Otherwise, get the next thread in the list (round robin) */
va009039 0:65f1469d6bfb 2237 else
va009039 0:65f1469d6bfb 2238 {
va009039 0:65f1469d6bfb 2239 if (++threadIndex >= gVmGlobal.threadList->length)
va009039 0:65f1469d6bfb 2240 {
va009039 0:65f1469d6bfb 2241 threadIndex = (uint8_t)0;
va009039 0:65f1469d6bfb 2242 }
va009039 0:65f1469d6bfb 2243 retval = list_getItem((pPmObj_t)gVmGlobal.threadList, threadIndex,
va009039 0:65f1469d6bfb 2244 &pobj);
va009039 0:65f1469d6bfb 2245 gVmGlobal.pthread = (pPmThread_t)pobj;
va009039 0:65f1469d6bfb 2246 PM_RETURN_IF_ERROR(retval);
va009039 0:65f1469d6bfb 2247 }
va009039 0:65f1469d6bfb 2248
va009039 0:65f1469d6bfb 2249 /* Clear flag to indicate a reschedule has occurred */
va009039 0:65f1469d6bfb 2250 interp_setRescheduleFlag(0);
va009039 0:65f1469d6bfb 2251 return retval;
va009039 0:65f1469d6bfb 2252 }
va009039 0:65f1469d6bfb 2253
va009039 0:65f1469d6bfb 2254
va009039 0:65f1469d6bfb 2255 PmReturn_t
va009039 0:65f1469d6bfb 2256 interp_addThread(pPmFunc_t pfunc)
va009039 0:65f1469d6bfb 2257 {
va009039 0:65f1469d6bfb 2258 PmReturn_t retval;
va009039 0:65f1469d6bfb 2259 pPmObj_t pframe;
va009039 0:65f1469d6bfb 2260 pPmObj_t pthread;
va009039 0:65f1469d6bfb 2261 uint8_t objid1, objid2;
va009039 0:65f1469d6bfb 2262
va009039 0:65f1469d6bfb 2263 /* Create a frame for the func */
va009039 0:65f1469d6bfb 2264 retval = frame_new((pPmObj_t)pfunc, &pframe);
va009039 0:65f1469d6bfb 2265 PM_RETURN_IF_ERROR(retval);
va009039 0:65f1469d6bfb 2266
va009039 0:65f1469d6bfb 2267 /* Create a thread with this new frame */
va009039 0:65f1469d6bfb 2268 heap_gcPushTempRoot(pframe, &objid1);
va009039 0:65f1469d6bfb 2269 retval = thread_new(pframe, &pthread);
va009039 0:65f1469d6bfb 2270 if (retval != PM_RET_OK)
va009039 0:65f1469d6bfb 2271 {
va009039 0:65f1469d6bfb 2272 heap_gcPopTempRoot(objid1);
va009039 0:65f1469d6bfb 2273 return retval;
va009039 0:65f1469d6bfb 2274 }
va009039 0:65f1469d6bfb 2275
va009039 0:65f1469d6bfb 2276 /* Add thread to end of list */
va009039 0:65f1469d6bfb 2277 heap_gcPushTempRoot(pthread, &objid2);
va009039 0:65f1469d6bfb 2278 retval = list_append((pPmObj_t)gVmGlobal.threadList, pthread);
va009039 0:65f1469d6bfb 2279 heap_gcPopTempRoot(objid1);
va009039 0:65f1469d6bfb 2280 return retval;
va009039 0:65f1469d6bfb 2281 }
va009039 0:65f1469d6bfb 2282
va009039 0:65f1469d6bfb 2283
va009039 0:65f1469d6bfb 2284 void
va009039 0:65f1469d6bfb 2285 interp_setRescheduleFlag(uint8_t boolean)
va009039 0:65f1469d6bfb 2286 {
va009039 0:65f1469d6bfb 2287 gVmGlobal.reschedule = boolean;
va009039 0:65f1469d6bfb 2288 }