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