Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of pymite by
vm/int.c@0:65f1469d6bfb, 2013-03-02 (annotated)
- Committer:
- va009039
- Date:
- Sat Mar 02 11:54:20 2013 +0000
- Revision:
- 0:65f1469d6bfb
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__ 0x08 |
| va009039 | 0:65f1469d6bfb | 11 | |
| va009039 | 0:65f1469d6bfb | 12 | |
| va009039 | 0:65f1469d6bfb | 13 | /** |
| va009039 | 0:65f1469d6bfb | 14 | * \file |
| va009039 | 0:65f1469d6bfb | 15 | * \brief Integer Object Type |
| va009039 | 0:65f1469d6bfb | 16 | * |
| va009039 | 0:65f1469d6bfb | 17 | * Integer object type operations. |
| va009039 | 0:65f1469d6bfb | 18 | */ |
| va009039 | 0:65f1469d6bfb | 19 | |
| va009039 | 0:65f1469d6bfb | 20 | #include <limits.h> |
| va009039 | 0:65f1469d6bfb | 21 | |
| va009039 | 0:65f1469d6bfb | 22 | #include "pm.h" |
| va009039 | 0:65f1469d6bfb | 23 | |
| va009039 | 0:65f1469d6bfb | 24 | |
| va009039 | 0:65f1469d6bfb | 25 | PmReturn_t |
| va009039 | 0:65f1469d6bfb | 26 | int_dup(pPmObj_t pint, pPmObj_t *r_pint) |
| va009039 | 0:65f1469d6bfb | 27 | { |
| va009039 | 0:65f1469d6bfb | 28 | PmReturn_t retval = PM_RET_OK; |
| va009039 | 0:65f1469d6bfb | 29 | |
| va009039 | 0:65f1469d6bfb | 30 | /* Allocate new int */ |
| va009039 | 0:65f1469d6bfb | 31 | retval = heap_getChunk(sizeof(PmInt_t), (uint8_t **)r_pint); |
| va009039 | 0:65f1469d6bfb | 32 | PM_RETURN_IF_ERROR(retval); |
| va009039 | 0:65f1469d6bfb | 33 | |
| va009039 | 0:65f1469d6bfb | 34 | /* Copy value */ |
| va009039 | 0:65f1469d6bfb | 35 | OBJ_SET_TYPE(*r_pint, OBJ_TYPE_INT); |
| va009039 | 0:65f1469d6bfb | 36 | ((pPmInt_t)*r_pint)->val = ((pPmInt_t)pint)->val; |
| va009039 | 0:65f1469d6bfb | 37 | return retval; |
| va009039 | 0:65f1469d6bfb | 38 | } |
| va009039 | 0:65f1469d6bfb | 39 | |
| va009039 | 0:65f1469d6bfb | 40 | |
| va009039 | 0:65f1469d6bfb | 41 | PmReturn_t |
| va009039 | 0:65f1469d6bfb | 42 | int_new(int32_t n, pPmObj_t *r_pint) |
| va009039 | 0:65f1469d6bfb | 43 | { |
| va009039 | 0:65f1469d6bfb | 44 | PmReturn_t retval = PM_RET_OK; |
| va009039 | 0:65f1469d6bfb | 45 | |
| va009039 | 0:65f1469d6bfb | 46 | /* If n is 0,1,-1, return static int objects from global struct */ |
| va009039 | 0:65f1469d6bfb | 47 | if (n == 0) |
| va009039 | 0:65f1469d6bfb | 48 | { |
| va009039 | 0:65f1469d6bfb | 49 | *r_pint = PM_ZERO; |
| va009039 | 0:65f1469d6bfb | 50 | return PM_RET_OK; |
| va009039 | 0:65f1469d6bfb | 51 | } |
| va009039 | 0:65f1469d6bfb | 52 | if (n == 1) |
| va009039 | 0:65f1469d6bfb | 53 | { |
| va009039 | 0:65f1469d6bfb | 54 | *r_pint = PM_ONE; |
| va009039 | 0:65f1469d6bfb | 55 | return PM_RET_OK; |
| va009039 | 0:65f1469d6bfb | 56 | } |
| va009039 | 0:65f1469d6bfb | 57 | if (n == -1) |
| va009039 | 0:65f1469d6bfb | 58 | { |
| va009039 | 0:65f1469d6bfb | 59 | *r_pint = PM_NEGONE; |
| va009039 | 0:65f1469d6bfb | 60 | return PM_RET_OK; |
| va009039 | 0:65f1469d6bfb | 61 | } |
| va009039 | 0:65f1469d6bfb | 62 | |
| va009039 | 0:65f1469d6bfb | 63 | /* Else create and return new int obj */ |
| va009039 | 0:65f1469d6bfb | 64 | retval = heap_getChunk(sizeof(PmInt_t), (uint8_t **)r_pint); |
| va009039 | 0:65f1469d6bfb | 65 | PM_RETURN_IF_ERROR(retval); |
| va009039 | 0:65f1469d6bfb | 66 | OBJ_SET_TYPE(*r_pint, OBJ_TYPE_INT); |
| va009039 | 0:65f1469d6bfb | 67 | ((pPmInt_t)*r_pint)->val = n; |
| va009039 | 0:65f1469d6bfb | 68 | return retval; |
| va009039 | 0:65f1469d6bfb | 69 | } |
| va009039 | 0:65f1469d6bfb | 70 | |
| va009039 | 0:65f1469d6bfb | 71 | |
| va009039 | 0:65f1469d6bfb | 72 | PmReturn_t |
| va009039 | 0:65f1469d6bfb | 73 | int_positive(pPmObj_t pobj, pPmObj_t *r_pint) |
| va009039 | 0:65f1469d6bfb | 74 | { |
| va009039 | 0:65f1469d6bfb | 75 | PmReturn_t retval; |
| va009039 | 0:65f1469d6bfb | 76 | |
| va009039 | 0:65f1469d6bfb | 77 | /* Raise TypeError if obj is not an int */ |
| va009039 | 0:65f1469d6bfb | 78 | if (OBJ_GET_TYPE(pobj) != OBJ_TYPE_INT) |
| va009039 | 0:65f1469d6bfb | 79 | { |
| va009039 | 0:65f1469d6bfb | 80 | PM_RAISE(retval, PM_RET_EX_TYPE); |
| va009039 | 0:65f1469d6bfb | 81 | return retval; |
| va009039 | 0:65f1469d6bfb | 82 | } |
| va009039 | 0:65f1469d6bfb | 83 | |
| va009039 | 0:65f1469d6bfb | 84 | /* Create new int obj */ |
| va009039 | 0:65f1469d6bfb | 85 | return int_new(((pPmInt_t)pobj)->val, r_pint); |
| va009039 | 0:65f1469d6bfb | 86 | } |
| va009039 | 0:65f1469d6bfb | 87 | |
| va009039 | 0:65f1469d6bfb | 88 | |
| va009039 | 0:65f1469d6bfb | 89 | PmReturn_t |
| va009039 | 0:65f1469d6bfb | 90 | int_negative(pPmObj_t pobj, pPmObj_t *r_pint) |
| va009039 | 0:65f1469d6bfb | 91 | { |
| va009039 | 0:65f1469d6bfb | 92 | PmReturn_t retval; |
| va009039 | 0:65f1469d6bfb | 93 | |
| va009039 | 0:65f1469d6bfb | 94 | /* Raise TypeError if obj is not an int */ |
| va009039 | 0:65f1469d6bfb | 95 | if (OBJ_GET_TYPE(pobj) != OBJ_TYPE_INT) |
| va009039 | 0:65f1469d6bfb | 96 | { |
| va009039 | 0:65f1469d6bfb | 97 | PM_RAISE(retval, PM_RET_EX_TYPE); |
| va009039 | 0:65f1469d6bfb | 98 | return retval; |
| va009039 | 0:65f1469d6bfb | 99 | } |
| va009039 | 0:65f1469d6bfb | 100 | |
| va009039 | 0:65f1469d6bfb | 101 | /* Create new int obj */ |
| va009039 | 0:65f1469d6bfb | 102 | return int_new(-((pPmInt_t)pobj)->val, r_pint); |
| va009039 | 0:65f1469d6bfb | 103 | } |
| va009039 | 0:65f1469d6bfb | 104 | |
| va009039 | 0:65f1469d6bfb | 105 | |
| va009039 | 0:65f1469d6bfb | 106 | PmReturn_t |
| va009039 | 0:65f1469d6bfb | 107 | int_bitInvert(pPmObj_t pobj, pPmObj_t *r_pint) |
| va009039 | 0:65f1469d6bfb | 108 | { |
| va009039 | 0:65f1469d6bfb | 109 | PmReturn_t retval; |
| va009039 | 0:65f1469d6bfb | 110 | |
| va009039 | 0:65f1469d6bfb | 111 | /* Raise TypeError if obj is not an int */ |
| va009039 | 0:65f1469d6bfb | 112 | if (OBJ_GET_TYPE(pobj) != OBJ_TYPE_INT) |
| va009039 | 0:65f1469d6bfb | 113 | { |
| va009039 | 0:65f1469d6bfb | 114 | PM_RAISE(retval, PM_RET_EX_TYPE); |
| va009039 | 0:65f1469d6bfb | 115 | return retval; |
| va009039 | 0:65f1469d6bfb | 116 | } |
| va009039 | 0:65f1469d6bfb | 117 | |
| va009039 | 0:65f1469d6bfb | 118 | /* Create new int obj */ |
| va009039 | 0:65f1469d6bfb | 119 | return int_new(~((pPmInt_t)pobj)->val, r_pint); |
| va009039 | 0:65f1469d6bfb | 120 | } |
| va009039 | 0:65f1469d6bfb | 121 | |
| va009039 | 0:65f1469d6bfb | 122 | |
| va009039 | 0:65f1469d6bfb | 123 | PmReturn_t |
| va009039 | 0:65f1469d6bfb | 124 | int_print(pPmObj_t pint) |
| va009039 | 0:65f1469d6bfb | 125 | { |
| va009039 | 0:65f1469d6bfb | 126 | PmReturn_t retval = PM_RET_OK; |
| va009039 | 0:65f1469d6bfb | 127 | uint8_t buf[12]; |
| va009039 | 0:65f1469d6bfb | 128 | |
| va009039 | 0:65f1469d6bfb | 129 | C_ASSERT(pint != C_NULL); |
| va009039 | 0:65f1469d6bfb | 130 | |
| va009039 | 0:65f1469d6bfb | 131 | /* Raise TypeError if obj is not an int */ |
| va009039 | 0:65f1469d6bfb | 132 | if (OBJ_GET_TYPE(pint) != OBJ_TYPE_INT) |
| va009039 | 0:65f1469d6bfb | 133 | { |
| va009039 | 0:65f1469d6bfb | 134 | PM_RAISE(retval, PM_RET_EX_TYPE); |
| va009039 | 0:65f1469d6bfb | 135 | return retval; |
| va009039 | 0:65f1469d6bfb | 136 | } |
| va009039 | 0:65f1469d6bfb | 137 | |
| va009039 | 0:65f1469d6bfb | 138 | retval = sli_ltoa10(((pPmInt_t)pint)->val, buf, sizeof(buf)); |
| va009039 | 0:65f1469d6bfb | 139 | PM_RETURN_IF_ERROR(retval); |
| va009039 | 0:65f1469d6bfb | 140 | sli_puts(buf); |
| va009039 | 0:65f1469d6bfb | 141 | |
| va009039 | 0:65f1469d6bfb | 142 | return retval; |
| va009039 | 0:65f1469d6bfb | 143 | } |
| va009039 | 0:65f1469d6bfb | 144 | |
| va009039 | 0:65f1469d6bfb | 145 | |
| va009039 | 0:65f1469d6bfb | 146 | PmReturn_t |
| va009039 | 0:65f1469d6bfb | 147 | int_printHex(pPmObj_t pint) |
| va009039 | 0:65f1469d6bfb | 148 | { |
| va009039 | 0:65f1469d6bfb | 149 | uint8_t buf[9]; |
| va009039 | 0:65f1469d6bfb | 150 | PmReturn_t retval = PM_RET_OK; |
| va009039 | 0:65f1469d6bfb | 151 | |
| va009039 | 0:65f1469d6bfb | 152 | C_ASSERT(OBJ_GET_TYPE(pint) == OBJ_TYPE_INT); |
| va009039 | 0:65f1469d6bfb | 153 | |
| va009039 | 0:65f1469d6bfb | 154 | /* Print the integer object */ |
| va009039 | 0:65f1469d6bfb | 155 | retval = sli_ltoa16(((pPmInt_t)pint)->val, buf, sizeof(buf), 1); |
| va009039 | 0:65f1469d6bfb | 156 | sli_puts(buf); |
| va009039 | 0:65f1469d6bfb | 157 | return retval; |
| va009039 | 0:65f1469d6bfb | 158 | } |
| va009039 | 0:65f1469d6bfb | 159 | |
| va009039 | 0:65f1469d6bfb | 160 | |
| va009039 | 0:65f1469d6bfb | 161 | PmReturn_t |
| va009039 | 0:65f1469d6bfb | 162 | int_pow(pPmObj_t px, pPmObj_t py, pPmObj_t *r_pn) |
| va009039 | 0:65f1469d6bfb | 163 | { |
| va009039 | 0:65f1469d6bfb | 164 | int32_t x; |
| va009039 | 0:65f1469d6bfb | 165 | int32_t y; |
| va009039 | 0:65f1469d6bfb | 166 | int32_t n; |
| va009039 | 0:65f1469d6bfb | 167 | PmReturn_t retval; |
| va009039 | 0:65f1469d6bfb | 168 | |
| va009039 | 0:65f1469d6bfb | 169 | /* Raise TypeError if args aren't ints */ |
| va009039 | 0:65f1469d6bfb | 170 | if ((OBJ_GET_TYPE(px) != OBJ_TYPE_INT) |
| va009039 | 0:65f1469d6bfb | 171 | || (OBJ_GET_TYPE(py) != OBJ_TYPE_INT)) |
| va009039 | 0:65f1469d6bfb | 172 | { |
| va009039 | 0:65f1469d6bfb | 173 | PM_RAISE(retval, PM_RET_EX_TYPE); |
| va009039 | 0:65f1469d6bfb | 174 | return retval; |
| va009039 | 0:65f1469d6bfb | 175 | } |
| va009039 | 0:65f1469d6bfb | 176 | |
| va009039 | 0:65f1469d6bfb | 177 | x = ((pPmInt_t)px)->val; |
| va009039 | 0:65f1469d6bfb | 178 | y = ((pPmInt_t)py)->val; |
| va009039 | 0:65f1469d6bfb | 179 | |
| va009039 | 0:65f1469d6bfb | 180 | /* Raise Value error if exponent is negative */ |
| va009039 | 0:65f1469d6bfb | 181 | if (y < 0) |
| va009039 | 0:65f1469d6bfb | 182 | { |
| va009039 | 0:65f1469d6bfb | 183 | PM_RAISE(retval, PM_RET_EX_VAL); |
| va009039 | 0:65f1469d6bfb | 184 | return retval; |
| va009039 | 0:65f1469d6bfb | 185 | } |
| va009039 | 0:65f1469d6bfb | 186 | |
| va009039 | 0:65f1469d6bfb | 187 | /* Calculate x raised to y */ |
| va009039 | 0:65f1469d6bfb | 188 | n = 1; |
| va009039 | 0:65f1469d6bfb | 189 | while (y > 0) |
| va009039 | 0:65f1469d6bfb | 190 | { |
| va009039 | 0:65f1469d6bfb | 191 | n = n * x; |
| va009039 | 0:65f1469d6bfb | 192 | y--; |
| va009039 | 0:65f1469d6bfb | 193 | } |
| va009039 | 0:65f1469d6bfb | 194 | retval = int_new(n, r_pn); |
| va009039 | 0:65f1469d6bfb | 195 | |
| va009039 | 0:65f1469d6bfb | 196 | return retval; |
| va009039 | 0:65f1469d6bfb | 197 | } |
| va009039 | 0:65f1469d6bfb | 198 | |
| va009039 | 0:65f1469d6bfb | 199 | |
| va009039 | 0:65f1469d6bfb | 200 | PmReturn_t |
| va009039 | 0:65f1469d6bfb | 201 | int_divmod(pPmObj_t px, pPmObj_t py, uint8_t op, pPmObj_t *r_pxopy) |
| va009039 | 0:65f1469d6bfb | 202 | { |
| va009039 | 0:65f1469d6bfb | 203 | int32_t x; |
| va009039 | 0:65f1469d6bfb | 204 | int32_t y; |
| va009039 | 0:65f1469d6bfb | 205 | int32_t xdivy; |
| va009039 | 0:65f1469d6bfb | 206 | int32_t xmody; |
| va009039 | 0:65f1469d6bfb | 207 | int32_t xopy; |
| va009039 | 0:65f1469d6bfb | 208 | PmReturn_t retval = PM_RET_OK; |
| va009039 | 0:65f1469d6bfb | 209 | |
| va009039 | 0:65f1469d6bfb | 210 | /* Raise TypeError if args aren't ints */ |
| va009039 | 0:65f1469d6bfb | 211 | if ((OBJ_GET_TYPE(px) != OBJ_TYPE_INT) |
| va009039 | 0:65f1469d6bfb | 212 | || (OBJ_GET_TYPE(py) != OBJ_TYPE_INT)) |
| va009039 | 0:65f1469d6bfb | 213 | { |
| va009039 | 0:65f1469d6bfb | 214 | PM_RAISE(retval, PM_RET_EX_TYPE); |
| va009039 | 0:65f1469d6bfb | 215 | return retval; |
| va009039 | 0:65f1469d6bfb | 216 | } |
| va009039 | 0:65f1469d6bfb | 217 | |
| va009039 | 0:65f1469d6bfb | 218 | x = ((pPmInt_t)px)->val; |
| va009039 | 0:65f1469d6bfb | 219 | y = ((pPmInt_t)py)->val; |
| va009039 | 0:65f1469d6bfb | 220 | |
| va009039 | 0:65f1469d6bfb | 221 | /* Raise ZeroDivisionError if denominator is zero */ |
| va009039 | 0:65f1469d6bfb | 222 | if (y == 0) |
| va009039 | 0:65f1469d6bfb | 223 | { |
| va009039 | 0:65f1469d6bfb | 224 | PM_RAISE(retval, PM_RET_EX_ZDIV); |
| va009039 | 0:65f1469d6bfb | 225 | return retval; |
| va009039 | 0:65f1469d6bfb | 226 | } |
| va009039 | 0:65f1469d6bfb | 227 | |
| va009039 | 0:65f1469d6bfb | 228 | /* Issue #167: Make overflow silent until exceptions can be caught */ |
| va009039 | 0:65f1469d6bfb | 229 | /* (-sys.maxint-1)/-1 is the only overflow case. */ |
| va009039 | 0:65f1469d6bfb | 230 | /* TODO: enable the overflow for Issue #169 */ |
| va009039 | 0:65f1469d6bfb | 231 | /* |
| va009039 | 0:65f1469d6bfb | 232 | if ((y == -1) && (op == '/') && (x < 0) |
| va009039 | 0:65f1469d6bfb | 233 | && ((uint32_t)x == (0 - (uint32_t)x))) |
| va009039 | 0:65f1469d6bfb | 234 | { |
| va009039 | 0:65f1469d6bfb | 235 | PM_RAISE(retval, PM_RET_EX_OFLOW); |
| va009039 | 0:65f1469d6bfb | 236 | return retval; |
| va009039 | 0:65f1469d6bfb | 237 | } |
| va009039 | 0:65f1469d6bfb | 238 | */ |
| va009039 | 0:65f1469d6bfb | 239 | |
| va009039 | 0:65f1469d6bfb | 240 | /* Shortcut when denominator is one or negative one */ |
| va009039 | 0:65f1469d6bfb | 241 | if (y == 1) |
| va009039 | 0:65f1469d6bfb | 242 | { |
| va009039 | 0:65f1469d6bfb | 243 | xdivy = x; |
| va009039 | 0:65f1469d6bfb | 244 | xmody = 0; |
| va009039 | 0:65f1469d6bfb | 245 | } |
| va009039 | 0:65f1469d6bfb | 246 | else if (y == -1) |
| va009039 | 0:65f1469d6bfb | 247 | { |
| va009039 | 0:65f1469d6bfb | 248 | xdivy = -x; |
| va009039 | 0:65f1469d6bfb | 249 | xmody = 0; |
| va009039 | 0:65f1469d6bfb | 250 | } |
| va009039 | 0:65f1469d6bfb | 251 | |
| va009039 | 0:65f1469d6bfb | 252 | else |
| va009039 | 0:65f1469d6bfb | 253 | { |
| va009039 | 0:65f1469d6bfb | 254 | xdivy = x / y; |
| va009039 | 0:65f1469d6bfb | 255 | xmody = x - xdivy * y; |
| va009039 | 0:65f1469d6bfb | 256 | |
| va009039 | 0:65f1469d6bfb | 257 | /* |
| va009039 | 0:65f1469d6bfb | 258 | * If the remainder is non-0 and the signs of x and y differ, |
| va009039 | 0:65f1469d6bfb | 259 | * C89 doesn't define whether xdivy is now the floor or the |
| va009039 | 0:65f1469d6bfb | 260 | * ceiling of the infinitely precise quotient. We want the floor, |
| va009039 | 0:65f1469d6bfb | 261 | * and we have it iff the remainder's sign matches y's. |
| va009039 | 0:65f1469d6bfb | 262 | */ |
| va009039 | 0:65f1469d6bfb | 263 | if ((xmody != 0) && ((y ^ xmody) < 0)) |
| va009039 | 0:65f1469d6bfb | 264 | { |
| va009039 | 0:65f1469d6bfb | 265 | xmody += y; |
| va009039 | 0:65f1469d6bfb | 266 | --xdivy; |
| va009039 | 0:65f1469d6bfb | 267 | C_ASSERT(xmody && ((y ^ xmody) >= 0)); |
| va009039 | 0:65f1469d6bfb | 268 | } |
| va009039 | 0:65f1469d6bfb | 269 | } |
| va009039 | 0:65f1469d6bfb | 270 | xopy = (op == '/') ? xdivy : xmody; |
| va009039 | 0:65f1469d6bfb | 271 | return int_new(xopy, r_pxopy); |
| va009039 | 0:65f1469d6bfb | 272 | } |
