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