Rework KrkValue to use NaN-boxing
This commit is contained in:
parent
073a5828d0
commit
2ed8e65c89
@ -7,7 +7,7 @@ def processFile(sourcePath, pid, cmd):
|
||||
with fileio.open(sourcePath,'r') as f:
|
||||
for line in f.readlines():
|
||||
let callerFile, callerFunc, callerLine, calleeFile, calleeFunc, calleeLine, nsecs = line.split(' ')
|
||||
nsecs = int(nsecs)
|
||||
nsecs = int(nsecs[:-2])
|
||||
let data = funcs.get((callerFile,callerFunc),{})
|
||||
let call = data.get((callerLine,calleeFile,calleeFunc,calleeLine),(0,0))
|
||||
let out = (call[0] + 1, call[1] + nsecs)
|
||||
@ -37,7 +37,7 @@ def processFile(sourcePath, pid, cmd):
|
||||
let count, nsecs = v
|
||||
totalNsecs -= nsecs
|
||||
|
||||
out.write(f'{startLine} {totalNsecs}\n')
|
||||
out.write(f'{startLine} {totalNsecs}00\n')
|
||||
for k, v in value.items():
|
||||
if not k: continue
|
||||
let sourceLine, file, func, destLine = k
|
||||
@ -45,5 +45,5 @@ def processFile(sourcePath, pid, cmd):
|
||||
if file != sFile: out.write(f'cfi={file}\n')
|
||||
out.write(f'cfn={func}\n')
|
||||
out.write(f'calls={count} {destLine}\n')
|
||||
out.write(f'{sourceLine} {totalNsecs}\n')
|
||||
out.write(f'{sourceLine} {totalNsecs}00\n')
|
||||
out.write('\n')
|
||||
|
@ -8,20 +8,20 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#if defined(__EMSCRIPTEN__)
|
||||
typedef long long krk_integer_type;
|
||||
# define PRIkrk_int "%lld"
|
||||
# define PRIkrk_hex "%llx"
|
||||
# define parseStrInt strtoll
|
||||
typedef int krk_integer_type;
|
||||
# define PRIkrk_int "%d"
|
||||
# define PRIkrk_hex "%x"
|
||||
# define parseStrInt strtol
|
||||
#elif defined(_WIN32)
|
||||
typedef long long krk_integer_type;
|
||||
# define PRIkrk_int "%I64d"
|
||||
# define PRIkrk_hex "%I64x"
|
||||
# define parseStrInt strtoll
|
||||
typedef int krk_integer_type;
|
||||
# define PRIkrk_int "%I32d"
|
||||
# define PRIkrk_hex "%I32x"
|
||||
# define parseStrInt strtol
|
||||
# define ENABLE_THREADING
|
||||
# else
|
||||
typedef long krk_integer_type;
|
||||
# define PRIkrk_int "%ld"
|
||||
# define PRIkrk_hex "%lx"
|
||||
typedef int krk_integer_type;
|
||||
# define PRIkrk_int "%d"
|
||||
# define PRIkrk_hex "%x"
|
||||
# define parseStrInt strtol
|
||||
# define ENABLE_THREADING
|
||||
#endif
|
||||
|
@ -4,6 +4,7 @@
|
||||
* @brief Definitions for primitive stack references.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "kuroko.h"
|
||||
|
||||
/**
|
||||
@ -18,37 +19,26 @@ typedef struct KrkString KrkString;
|
||||
/**
|
||||
* @brief Tag enum for basic value types.
|
||||
*
|
||||
* Value types are tagged unions of a handful of small
|
||||
* types represented directly on the stack: Integers,
|
||||
* double-precision floating point values, booleans,
|
||||
* exception handler references, complex function argument
|
||||
* processing sentinels, object reference pointers, and None.
|
||||
* These are the values stored in the upper NaN bits of
|
||||
* the boxed NaN values.
|
||||
*/
|
||||
typedef enum {
|
||||
KRK_VAL_NONE,
|
||||
KRK_VAL_BOOLEAN,
|
||||
KRK_VAL_INTEGER,
|
||||
KRK_VAL_FLOATING,
|
||||
KRK_VAL_HANDLER,
|
||||
KRK_VAL_OBJECT,
|
||||
KRK_VAL_KWARGS,
|
||||
KRK_VAL_BOOLEAN = 0xFFFC,
|
||||
KRK_VAL_INTEGER = 0xFFFD,
|
||||
KRK_VAL_HANDLER = 0xFFFE,
|
||||
KRK_VAL_NONE = 0xFFFF,
|
||||
KRK_VAL_KWARGS = 0x7FFC,
|
||||
KRK_VAL_OBJECT = 0x7FFD,
|
||||
} KrkValueType;
|
||||
|
||||
/**
|
||||
* @brief Stack value representation of a 'with' or 'try' block.
|
||||
*
|
||||
* When a 'with' or 'try' block is entered, a handler value is
|
||||
* created on the stack representing the type (with, try) and the
|
||||
* jump target to leave the block (entering the 'except' block of
|
||||
* a 'try', if present, or calling the __exit__ method of an object
|
||||
* __enter__'d by a 'with' block). When the relevant conditions are
|
||||
* triggered in the VM, the stack will be scanned from top to bottom
|
||||
* to look for these values.
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned short type;
|
||||
unsigned short target;
|
||||
} KrkJumpTarget;
|
||||
#define KRK_VAL_MASK_BOOLEAN ((uint64_t)0xFFFC000000000000) /* 1..1100 */
|
||||
#define KRK_VAL_MASK_INTEGER ((uint64_t)0xFFFD000000000000) /* 1..1101 */
|
||||
#define KRK_VAL_MASK_HANDLER ((uint64_t)0xFFFE000000000000) /* 1..1110 */
|
||||
#define KRK_VAL_MASK_NONE ((uint64_t)0xFFFF000000000000) /* 1..1111 */
|
||||
#define KRK_VAL_MASK_KWARGS ((uint64_t)0x7FFC000000000000) /* 0..1100 */
|
||||
#define KRK_VAL_MASK_OBJECT ((uint64_t)0x7FFD000000000000) /* 0..1101 */
|
||||
#define KRK_VAL_MASK_NAN ((uint64_t)0x7FFC000000000000)
|
||||
#define KRK_VAL_MASK_LOW ((uint64_t)0x0000FFFFFFFFFFFF)
|
||||
|
||||
/**
|
||||
* @brief Stack reference or primative value.
|
||||
@ -59,19 +49,11 @@ typedef struct {
|
||||
* direct copying rather than as pointers, avoiding the need to track
|
||||
* memory used by them.
|
||||
*
|
||||
* Each value is a tagged union with a type (see the enum KrkValueType)
|
||||
* and its contents.
|
||||
* Implemented through basic NaN-boxing where the top sixteen bits are
|
||||
* used as a tag (@ref KrkValueType) and the lower 32 or 48 bits contain
|
||||
* the various primitive types.
|
||||
*/
|
||||
typedef struct {
|
||||
KrkValueType type;
|
||||
union {
|
||||
char boolean;
|
||||
krk_integer_type integer;
|
||||
double floating;
|
||||
KrkJumpTarget handler;
|
||||
KrkObj * object;
|
||||
} as;
|
||||
} KrkValue;
|
||||
typedef uint64_t KrkValue;
|
||||
|
||||
/**
|
||||
* @brief Flexible vector of stack references.
|
||||
@ -183,30 +165,51 @@ extern int krk_valuesEqual(KrkValue a, KrkValue b);
|
||||
*/
|
||||
extern int krk_valuesSame(KrkValue a, KrkValue b);
|
||||
|
||||
#define BOOLEAN_VAL(value) ((KrkValue){KRK_VAL_BOOLEAN, {.integer = value}})
|
||||
#define NONE_VAL(value) ((KrkValue){KRK_VAL_NONE, {.integer = 0}})
|
||||
#define INTEGER_VAL(value) ((KrkValue){KRK_VAL_INTEGER, {.integer = value}})
|
||||
#define FLOATING_VAL(value) ((KrkValue){KRK_VAL_FLOATING,{.floating = value}})
|
||||
#define HANDLER_VAL(ty,ta) ((KrkValue){KRK_VAL_HANDLER, {.handler = (KrkJumpTarget){.type = ty, .target = ta}}})
|
||||
#define OBJECT_VAL(value) ((KrkValue){KRK_VAL_OBJECT, {.object = (KrkObj*)value}})
|
||||
#define KWARGS_VAL(value) ((KrkValue){KRK_VAL_KWARGS, {.integer = value}})
|
||||
#define NONE_VAL(value) ((KrkValue)(KRK_VAL_MASK_LOW | KRK_VAL_MASK_NONE))
|
||||
#define BOOLEAN_VAL(value) ((KrkValue)((uint32_t)(value) | KRK_VAL_MASK_BOOLEAN))
|
||||
#define INTEGER_VAL(value) ((KrkValue)((uint32_t)(value) | KRK_VAL_MASK_INTEGER))
|
||||
#define KWARGS_VAL(value) ((KrkValue)((uint32_t)(value) | KRK_VAL_MASK_KWARGS))
|
||||
#define OBJECT_VAL(value) ((KrkValue)(((uintptr_t)(value) & KRK_VAL_MASK_LOW) | KRK_VAL_MASK_OBJECT))
|
||||
#define HANDLER_VAL(ty,ta) ((KrkValue)((uint32_t)((((uint16_t)ty) << 16) | ((uint16_t)ta)) | KRK_VAL_MASK_HANDLER))
|
||||
#define FLOATING_VAL(value) (krk_dbl_as_val(value))
|
||||
|
||||
#define AS_BOOLEAN(value) ((value).as.integer)
|
||||
#define AS_INTEGER(value) ((value).as.integer)
|
||||
#define AS_FLOATING(value) ((value).as.floating)
|
||||
#define AS_HANDLER(value) ((value).as.handler)
|
||||
#define AS_OBJECT(value) ((value).as.object)
|
||||
#define KRK_VAL_TYPE(value) ((value) >> 48)
|
||||
|
||||
#define IS_BOOLEAN(value) ((value).type == KRK_VAL_BOOLEAN)
|
||||
#define IS_NONE(value) ((value).type == KRK_VAL_NONE)
|
||||
#define IS_INTEGER(value) (((value).type == KRK_VAL_INTEGER) || ((value.type) == KRK_VAL_BOOLEAN))
|
||||
#define IS_FLOATING(value) ((value).type == KRK_VAL_FLOATING)
|
||||
#define IS_HANDLER(value) ((value).type == KRK_VAL_HANDLER)
|
||||
#define IS_OBJECT(value) ((value).type == KRK_VAL_OBJECT)
|
||||
#define IS_KWARGS(value) ((value).type == KRK_VAL_KWARGS)
|
||||
#define AS_BOOLEAN(value) ((krk_integer_type)((value) & KRK_VAL_MASK_LOW))
|
||||
#define AS_INTEGER(value) ((krk_integer_type)((value) & KRK_VAL_MASK_LOW))
|
||||
#define AS_HANDLER(value) ((uint32_t)((value) & KRK_VAL_MASK_LOW))
|
||||
#define AS_OBJECT(value) ((KrkObj*)(uintptr_t)((value) & KRK_VAL_MASK_LOW))
|
||||
#define AS_FLOATING(value) (krk_val_as_dbl(value))
|
||||
|
||||
#define IS_TRY_HANDLER(value) (IS_HANDLER(value) && AS_HANDLER(value).type == OP_PUSH_TRY)
|
||||
#define IS_WITH_HANDLER(value) (IS_HANDLER(value) && AS_HANDLER(value).type == OP_PUSH_WITH)
|
||||
#define IS_RAISE_HANDLER(value) (IS_HANDLER(value) && AS_HANDLER(value).type == OP_RAISE)
|
||||
#define IS_EXCEPT_HANDLER(value) (IS_HANDLER(value) && AS_HANDLER(value).type == OP_FILTER_EXCEPT)
|
||||
static inline double krk_val_as_dbl(KrkValue val) {
|
||||
double out;
|
||||
memcpy(&out,&val,sizeof(KrkValue));
|
||||
return out;
|
||||
}
|
||||
|
||||
static inline KrkValue krk_dbl_as_val(double dbl) {
|
||||
KrkValue out;
|
||||
memcpy(&out,&dbl,sizeof(KrkValue));
|
||||
return out;
|
||||
}
|
||||
|
||||
#define IS_INTEGER(value) (((value) & KRK_VAL_MASK_HANDLER) == KRK_VAL_MASK_BOOLEAN)
|
||||
#define IS_BOOLEAN(value) (((value) & KRK_VAL_MASK_NONE) == KRK_VAL_MASK_BOOLEAN)
|
||||
#define IS_NONE(value) (((value) & KRK_VAL_MASK_NONE) == KRK_VAL_MASK_NONE)
|
||||
#define IS_HANDLER(value) (((value) & KRK_VAL_MASK_NONE) == KRK_VAL_MASK_HANDLER)
|
||||
#define IS_OBJECT(value) (((value) & KRK_VAL_MASK_NONE) == KRK_VAL_MASK_OBJECT)
|
||||
#define IS_KWARGS(value) (((value) & KRK_VAL_MASK_NONE) == KRK_VAL_MASK_KWARGS)
|
||||
#define IS_FLOATING(value) (((value) & KRK_VAL_MASK_NAN) != KRK_VAL_MASK_NAN)
|
||||
|
||||
#define AS_HANDLER_TYPE(value) (AS_HANDLER(value) >> 16)
|
||||
#define AS_HANDLER_TARGET(value) (AS_HANDLER(value) & 0xFFFF)
|
||||
#define IS_TRY_HANDLER(value) (IS_HANDLER(value) && AS_HANDLER_TYPE(value) == OP_PUSH_TRY)
|
||||
#define IS_WITH_HANDLER(value) (IS_HANDLER(value) && AS_HANDLER_TYPE(value) == OP_PUSH_WITH)
|
||||
#define IS_RAISE_HANDLER(value) (IS_HANDLER(value) && AS_HANDLER_TYPE(value) == OP_RAISE)
|
||||
#define IS_EXCEPT_HANDLER(value) (IS_HANDLER(value) && AS_HANDLER_TYPE(value) == OP_FILTER_EXCEPT)
|
||||
|
||||
#define KWARGS_SINGLE (INT32_MAX)
|
||||
#define KWARGS_LIST (INT32_MAX-1)
|
||||
#define KWARGS_DICT (INT32_MAX-2)
|
||||
#define KWARGS_NIL (INT32_MAX-3)
|
||||
#define KWARGS_UNSET (0)
|
||||
|
@ -18,7 +18,7 @@
|
||||
}
|
||||
|
||||
#define FORCE_FLOAT(arg) \
|
||||
if (!IS_FLOATING(arg)) { switch (arg.type) { \
|
||||
if (!IS_FLOATING(arg)) { switch (KRK_VAL_TYPE(arg)) { \
|
||||
case KRK_VAL_INTEGER: arg = FLOATING_VAL(AS_INTEGER(arg)); break; \
|
||||
case KRK_VAL_BOOLEAN: arg = FLOATING_VAL(AS_BOOLEAN(arg)); break; \
|
||||
default: { \
|
||||
|
@ -16,7 +16,7 @@ static KrkValue _tuple_init(int argc, KrkValue argv[], int hasKw) {
|
||||
/* Convert this to a call to tupleOf(*arg) */
|
||||
KrkValue tupleOf;
|
||||
krk_tableGet(&vm.builtins->fields, OBJECT_VAL(S("tupleOf")), &tupleOf);
|
||||
krk_push(KWARGS_VAL(LONG_MAX-1));
|
||||
krk_push(KWARGS_VAL(KWARGS_LIST));
|
||||
krk_push(argv[1]);
|
||||
krk_push(KWARGS_VAL(1));
|
||||
krk_push(krk_callSimple(tupleOf, 3, 0));
|
||||
|
@ -22,13 +22,14 @@ void krk_freeTable(KrkTable * table) {
|
||||
}
|
||||
|
||||
inline uint32_t krk_hashValue(KrkValue value) {
|
||||
switch (value.type) {
|
||||
switch (KRK_VAL_TYPE(value)) {
|
||||
case KRK_VAL_INTEGER: return (uint32_t)(AS_INTEGER(value));
|
||||
case KRK_VAL_FLOATING: return (uint32_t)(AS_FLOATING(value) * 1000); /* arbitrary; what's a good way to hash floats? */
|
||||
case KRK_VAL_BOOLEAN: return (uint32_t)(AS_BOOLEAN(value));
|
||||
case KRK_VAL_NONE: return 0;
|
||||
case KRK_VAL_OBJECT: return (uint32_t)(AS_OBJECT(value))->hash;
|
||||
default: return 0;
|
||||
default:
|
||||
if (IS_FLOATING(value)) return (uint32_t)(AS_FLOATING(value) * 1000); /* arbitrary; what's a good way to hash floats? */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
72
src/value.c
72
src/value.c
@ -48,38 +48,39 @@ void krk_printValue(FILE * f, KrkValue printable) {
|
||||
|
||||
void krk_printValueSafe(FILE * f, KrkValue printable) {
|
||||
if (!IS_OBJECT(printable)) {
|
||||
switch (printable.type) {
|
||||
switch (KRK_VAL_TYPE(printable)) {
|
||||
case KRK_VAL_INTEGER: fprintf(f, PRIkrk_int, AS_INTEGER(printable)); break;
|
||||
case KRK_VAL_BOOLEAN: fprintf(f, "%s", AS_BOOLEAN(printable) ? "True" : "False"); break;
|
||||
case KRK_VAL_FLOATING: fprintf(f, "%.16g", AS_FLOATING(printable)); break;
|
||||
case KRK_VAL_NONE: fprintf(f, "None"); break;
|
||||
case KRK_VAL_HANDLER:
|
||||
switch (AS_HANDLER(printable).type) {
|
||||
case OP_PUSH_TRY: fprintf(f, "{try->%d}", (int)AS_HANDLER(printable).target); break;
|
||||
case OP_PUSH_WITH: fprintf(f, "{with->%d}", (int)AS_HANDLER(printable).target); break;
|
||||
case OP_RAISE: fprintf(f, "{raise<-%d}", (int)AS_HANDLER(printable).target); break;
|
||||
case OP_FILTER_EXCEPT: fprintf(f, "{except<-%d}", (int)AS_HANDLER(printable).target); break;
|
||||
case OP_BEGIN_FINALLY: fprintf(f, "{finally<-%d}", (int)AS_HANDLER(printable).target); break;
|
||||
case OP_RETURN: fprintf(f, "{return<-%d}", (int)AS_HANDLER(printable).target); break;
|
||||
switch (AS_HANDLER_TYPE(printable)) {
|
||||
case OP_PUSH_TRY: fprintf(f, "{try->%d}", (int)AS_HANDLER_TARGET(printable)); break;
|
||||
case OP_PUSH_WITH: fprintf(f, "{with->%d}", (int)AS_HANDLER_TARGET(printable)); break;
|
||||
case OP_RAISE: fprintf(f, "{raise<-%d}", (int)AS_HANDLER_TARGET(printable)); break;
|
||||
case OP_FILTER_EXCEPT: fprintf(f, "{except<-%d}", (int)AS_HANDLER_TARGET(printable)); break;
|
||||
case OP_BEGIN_FINALLY: fprintf(f, "{finally<-%d}", (int)AS_HANDLER_TARGET(printable)); break;
|
||||
case OP_RETURN: fprintf(f, "{return<-%d}", (int)AS_HANDLER_TARGET(printable)); break;
|
||||
}
|
||||
break;
|
||||
case KRK_VAL_KWARGS: {
|
||||
if (AS_INTEGER(printable) == LONG_MAX) {
|
||||
if (AS_INTEGER(printable) == KWARGS_SINGLE) {
|
||||
fprintf(f, "{unpack single}");
|
||||
} else if (AS_INTEGER(printable) == LONG_MAX-1) {
|
||||
} else if (AS_INTEGER(printable) == KWARGS_LIST) {
|
||||
fprintf(f, "{unpack list}");
|
||||
} else if (AS_INTEGER(printable) == LONG_MAX-2) {
|
||||
} else if (AS_INTEGER(printable) == KWARGS_DICT) {
|
||||
fprintf(f, "{unpack dict}");
|
||||
} else if (AS_INTEGER(printable) == LONG_MAX-3) {
|
||||
} else if (AS_INTEGER(printable) == KWARGS_NIL) {
|
||||
fprintf(f, "{unpack nil}");
|
||||
} else if (AS_INTEGER(printable) == 0) {
|
||||
} else if (AS_INTEGER(printable) == KWARGS_UNSET) {
|
||||
fprintf(f, "{unset default}");
|
||||
} else {
|
||||
fprintf(f, "{sentinel=" PRIkrk_int "}",AS_INTEGER(printable));
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
default:
|
||||
if (IS_FLOATING(printable)) fprintf(f, "%.16g", AS_FLOATING(printable));
|
||||
break;
|
||||
}
|
||||
} else if (IS_STRING(printable)) {
|
||||
fprintf(f, "'");
|
||||
@ -137,7 +138,7 @@ void krk_printValueSafe(FILE * f, KrkValue printable) {
|
||||
}
|
||||
|
||||
int krk_valuesSame(KrkValue a, KrkValue b) {
|
||||
if (a.type != b.type) return 0;
|
||||
if (KRK_VAL_TYPE(a) != KRK_VAL_TYPE(b)) return 0;
|
||||
if (IS_OBJECT(a)) return AS_OBJECT(a) == AS_OBJECT(b);
|
||||
return krk_valuesEqual(a,b);
|
||||
}
|
||||
@ -145,13 +146,12 @@ int krk_valuesSame(KrkValue a, KrkValue b) {
|
||||
__attribute__((hot))
|
||||
inline
|
||||
int krk_valuesEqual(KrkValue a, KrkValue b) {
|
||||
if (a.type == b.type) {
|
||||
switch (a.type) {
|
||||
if (KRK_VAL_TYPE(a) == KRK_VAL_TYPE(b)) {
|
||||
switch (KRK_VAL_TYPE(a)) {
|
||||
case KRK_VAL_BOOLEAN: return AS_BOOLEAN(a) == AS_BOOLEAN(b);
|
||||
case KRK_VAL_NONE: return 1; /* None always equals None */
|
||||
case KRK_VAL_KWARGS: /* Equal if same number of args; may be useful for comparing sentinels (0) to arg lists. */
|
||||
case KRK_VAL_INTEGER: return AS_INTEGER(a) == AS_INTEGER(b);
|
||||
case KRK_VAL_FLOATING: return AS_FLOATING(a) == AS_FLOATING(b);
|
||||
case KRK_VAL_HANDLER: krk_runtimeError(vm.exceptions->valueError,"Invalid value"); return 0;
|
||||
case KRK_VAL_OBJECT: {
|
||||
if (AS_OBJECT(a) == AS_OBJECT(b)) return 1;
|
||||
@ -159,33 +159,29 @@ int krk_valuesEqual(KrkValue a, KrkValue b) {
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
if (IS_FLOATING(a) && IS_FLOATING(b)) return AS_FLOATING(a) == AS_FLOATING(b);
|
||||
|
||||
if (IS_KWARGS(a) || IS_KWARGS(b)) return 0;
|
||||
|
||||
if (!IS_OBJECT(a) && !IS_OBJECT(b)) {
|
||||
switch (a.type) {
|
||||
switch (KRK_VAL_TYPE(a)) {
|
||||
case KRK_VAL_INTEGER: {
|
||||
switch (b.type) {
|
||||
case KRK_VAL_BOOLEAN: return AS_INTEGER(a) == AS_BOOLEAN(b);
|
||||
case KRK_VAL_FLOATING: return (double)AS_INTEGER(a) == AS_FLOATING(b);
|
||||
default: return 0;
|
||||
}
|
||||
} break;
|
||||
case KRK_VAL_FLOATING: {
|
||||
switch (b.type) {
|
||||
case KRK_VAL_BOOLEAN: return AS_FLOATING(a) == (double)AS_BOOLEAN(b);
|
||||
case KRK_VAL_INTEGER: return AS_FLOATING(a) == (double)AS_INTEGER(b);
|
||||
default: return 0;
|
||||
}
|
||||
if (IS_BOOLEAN(b)) return AS_INTEGER(a) == AS_BOOLEAN(b);
|
||||
else if (IS_FLOATING(b)) return (double)AS_INTEGER(a) == AS_FLOATING(b);
|
||||
return 0;
|
||||
} break;
|
||||
case KRK_VAL_BOOLEAN: {
|
||||
switch (b.type) {
|
||||
case KRK_VAL_INTEGER: return AS_BOOLEAN(a) == AS_INTEGER(b);
|
||||
case KRK_VAL_FLOATING: return (double)AS_BOOLEAN(a) == AS_FLOATING(b);
|
||||
default: return 0;
|
||||
}
|
||||
if (IS_INTEGER(b)) return AS_INTEGER(a) == AS_BOOLEAN(b);
|
||||
else if (IS_FLOATING(b)) return (double)AS_INTEGER(a) == AS_FLOATING(b);
|
||||
return 0;
|
||||
} break;
|
||||
default: return 0;
|
||||
default:
|
||||
if (IS_FLOATING(a)) {
|
||||
if (IS_BOOLEAN(b)) return AS_FLOATING(a) == (double)AS_BOOLEAN(b);
|
||||
else if (IS_INTEGER(b)) return AS_FLOATING(a) == (double)AS_INTEGER(b);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
55
src/vm.c
55
src/vm.c
@ -448,11 +448,9 @@ void krk_finalizeClass(KrkClass * _class) {
|
||||
* Internal version of type().
|
||||
*/
|
||||
inline KrkClass * krk_getType(KrkValue of) {
|
||||
switch (of.type) {
|
||||
switch (KRK_VAL_TYPE(of)) {
|
||||
case KRK_VAL_INTEGER:
|
||||
return vm.baseClasses->intClass;
|
||||
case KRK_VAL_FLOATING:
|
||||
return vm.baseClasses->floatClass;
|
||||
case KRK_VAL_BOOLEAN:
|
||||
return vm.baseClasses->boolClass;
|
||||
case KRK_VAL_NONE:
|
||||
@ -480,6 +478,7 @@ inline KrkClass * krk_getType(KrkValue of) {
|
||||
return vm.baseClasses->objectClass;
|
||||
} break;
|
||||
default:
|
||||
if (IS_FLOATING(of)) return vm.baseClasses->floatClass;
|
||||
return vm.baseClasses->objectClass;
|
||||
}
|
||||
}
|
||||
@ -557,9 +556,9 @@ int krk_processComplexArguments(int argCount, KrkValueArray * positionals, KrkTa
|
||||
KrkValue key = startOfExtras[i*2];
|
||||
KrkValue value = startOfExtras[i*2 + 1];
|
||||
if (IS_KWARGS(key)) {
|
||||
if (AS_INTEGER(key) == LONG_MAX-1) { /* unpack list */
|
||||
if (AS_INTEGER(key) == KWARGS_LIST) { /* unpack list */
|
||||
unpackIterableFast(value);
|
||||
} else if (AS_INTEGER(key) == LONG_MAX-2) { /* unpack dict */
|
||||
} else if (AS_INTEGER(key) == KWARGS_DICT) { /* unpack dict */
|
||||
if (!IS_INSTANCE(value)) {
|
||||
krk_runtimeError(vm.exceptions->typeError, "**expression value is not a dict.");
|
||||
return 0;
|
||||
@ -577,7 +576,7 @@ int krk_processComplexArguments(int argCount, KrkValueArray * positionals, KrkTa
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (AS_INTEGER(key) == LONG_MAX) { /* single value */
|
||||
} else if (AS_INTEGER(key) == KWARGS_SINGLE) { /* single value */
|
||||
krk_writeValueArray(positionals, value);
|
||||
}
|
||||
} else if (IS_STRING(key)) {
|
||||
@ -1002,19 +1001,21 @@ void krk_attachNamedObject(KrkTable * table, const char name[], KrkObj * obj) {
|
||||
* going to take the else branch.
|
||||
*/
|
||||
int krk_isFalsey(KrkValue value) {
|
||||
switch (value.type) {
|
||||
switch (KRK_VAL_TYPE(value)) {
|
||||
case KRK_VAL_NONE: return 1;
|
||||
case KRK_VAL_BOOLEAN: return !AS_BOOLEAN(value);
|
||||
case KRK_VAL_INTEGER: return !AS_INTEGER(value);
|
||||
case KRK_VAL_FLOATING: return !AS_FLOATING(value);
|
||||
case KRK_VAL_OBJECT: {
|
||||
switch (AS_OBJECT(value)->type) {
|
||||
case KRK_OBJ_STRING: return !AS_STRING(value)->codesLength;
|
||||
case KRK_OBJ_TUPLE: return !AS_TUPLE(value)->values.count;
|
||||
default: break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
default:
|
||||
if (IS_FLOATING(value)) return !AS_FLOATING(value);
|
||||
break;
|
||||
}
|
||||
KrkClass * type = krk_getType(value);
|
||||
|
||||
@ -2016,7 +2017,7 @@ _resumeHook: (void)0;
|
||||
KrkValue contextManager = krk_peek(2);
|
||||
KrkClass * type = krk_getType(contextManager);
|
||||
krk_push(contextManager);
|
||||
if (AS_HANDLER(handler).type == OP_RAISE) {
|
||||
if (AS_HANDLER_TYPE(handler) == OP_RAISE) {
|
||||
krk_push(OBJECT_VAL(krk_getType(exceptionObject)));
|
||||
krk_push(exceptionObject);
|
||||
KrkValue tracebackEntries = NONE_VAL();
|
||||
@ -2038,7 +2039,7 @@ _resumeHook: (void)0;
|
||||
krk_callSimple(OBJECT_VAL(type->_exit), 4, 0);
|
||||
if (krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION) goto _finishException;
|
||||
}
|
||||
if (AS_HANDLER(handler).type != OP_RETURN) break;
|
||||
if (AS_HANDLER_TYPE(handler) != OP_RETURN) break;
|
||||
krk_pop(); /* handler */
|
||||
} /* fallthrough */
|
||||
case OP_RETURN: {
|
||||
@ -2055,8 +2056,8 @@ _finishReturn: (void)0;
|
||||
; stackOffset--);
|
||||
if (stackOffset >= (int)frame->slots) {
|
||||
krk_currentThread.stackTop = &krk_currentThread.stack[stackOffset + 1];
|
||||
frame->ip = frame->closure->function->chunk.code + AS_HANDLER(krk_peek(0)).target;
|
||||
AS_HANDLER(krk_currentThread.stackTop[-1]).type = OP_RETURN;
|
||||
frame->ip = frame->closure->function->chunk.code + AS_HANDLER_TARGET(krk_peek(0));
|
||||
krk_currentThread.stackTop[-1] = HANDLER_VAL(OP_RETURN,AS_HANDLER_TARGET(krk_peek(0)));
|
||||
krk_currentThread.stackTop[-2] = result;
|
||||
break;
|
||||
}
|
||||
@ -2248,9 +2249,9 @@ _finishReturn: (void)0;
|
||||
break;
|
||||
case OP_FILTER_EXCEPT: {
|
||||
int isMatch = 0;
|
||||
if (AS_HANDLER(krk_peek(1)).type == OP_RETURN) {
|
||||
if (AS_HANDLER_TYPE(krk_peek(1)) == OP_RETURN) {
|
||||
isMatch = 0;
|
||||
} else if (AS_HANDLER(krk_peek(1)).type == OP_END_FINALLY) {
|
||||
} else if (AS_HANDLER_TYPE(krk_peek(1)) == OP_END_FINALLY) {
|
||||
isMatch = 0;
|
||||
} else if (IS_CLASS(krk_peek(0)) && krk_isInstanceOf(krk_peek(2), AS_CLASS(krk_peek(0)))) {
|
||||
isMatch = 1;
|
||||
@ -2265,7 +2266,7 @@ _finishReturn: (void)0;
|
||||
isMatch = !IS_NONE(krk_peek(2));
|
||||
}
|
||||
if (isMatch) {
|
||||
AS_HANDLER(krk_currentThread.stackTop[-2]).type = OP_FILTER_EXCEPT;
|
||||
krk_currentThread.stackTop[-2] = HANDLER_VAL(OP_FILTER_EXCEPT,AS_HANDLER_TARGET(krk_peek(1)));
|
||||
}
|
||||
krk_pop();
|
||||
krk_push(BOOLEAN_VAL(isMatch));
|
||||
@ -2273,10 +2274,10 @@ _finishReturn: (void)0;
|
||||
}
|
||||
case OP_BEGIN_FINALLY: {
|
||||
if (IS_HANDLER(krk_peek(0))) {
|
||||
if (AS_HANDLER(krk_peek(0)).type == OP_PUSH_TRY) {
|
||||
AS_HANDLER(krk_currentThread.stackTop[-1]).type = OP_BEGIN_FINALLY;
|
||||
} else if (AS_HANDLER(krk_peek(0)).type == OP_FILTER_EXCEPT) {
|
||||
AS_HANDLER(krk_currentThread.stackTop[-1]).type = OP_BEGIN_FINALLY;
|
||||
if (AS_HANDLER_TYPE(krk_peek(0)) == OP_PUSH_TRY) {
|
||||
krk_currentThread.stackTop[-1] = HANDLER_VAL(OP_BEGIN_FINALLY,AS_HANDLER_TARGET(krk_peek(0)));
|
||||
} else if (AS_HANDLER_TYPE(krk_peek(0)) == OP_FILTER_EXCEPT) {
|
||||
krk_currentThread.stackTop[-1] = HANDLER_VAL(OP_BEGIN_FINALLY,AS_HANDLER_TARGET(krk_peek(0)));
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -2284,12 +2285,12 @@ _finishReturn: (void)0;
|
||||
case OP_END_FINALLY: {
|
||||
KrkValue handler = krk_peek(0);
|
||||
if (IS_HANDLER(handler)) {
|
||||
if (AS_HANDLER(handler).type == OP_RAISE || AS_HANDLER(handler).type == OP_END_FINALLY) {
|
||||
if (AS_HANDLER_TYPE(handler) == OP_RAISE || AS_HANDLER_TYPE(handler) == OP_END_FINALLY) {
|
||||
krk_pop(); /* handler */
|
||||
krk_currentThread.currentException = krk_pop();
|
||||
krk_currentThread.flags |= KRK_THREAD_HAS_EXCEPTION;
|
||||
goto _finishException;
|
||||
} else if (AS_HANDLER(handler).type == OP_RETURN) {
|
||||
} else if (AS_HANDLER_TYPE(handler) == OP_RETURN) {
|
||||
krk_push(krk_peek(1));
|
||||
goto _finishReturn;
|
||||
}
|
||||
@ -2486,7 +2487,7 @@ _finishReturn: (void)0;
|
||||
case OP_EXPAND_ARGS_LONG:
|
||||
case OP_EXPAND_ARGS: {
|
||||
int type = OPERAND;
|
||||
krk_push(KWARGS_VAL(LONG_MAX-type));
|
||||
krk_push(KWARGS_VAL(KWARGS_SINGLE-type));
|
||||
break;
|
||||
}
|
||||
case OP_CLOSURE_LONG:
|
||||
@ -2747,12 +2748,12 @@ _finishReturn: (void)0;
|
||||
_finishException:
|
||||
if (!handleException()) {
|
||||
frame = &krk_currentThread.frames[krk_currentThread.frameCount - 1];
|
||||
frame->ip = frame->closure->function->chunk.code + AS_HANDLER(krk_peek(0)).target;
|
||||
frame->ip = frame->closure->function->chunk.code + AS_HANDLER_TARGET(krk_peek(0));
|
||||
/* Stick the exception into the exception slot */
|
||||
if (AS_HANDLER(krk_currentThread.stackTop[-1]).type == OP_FILTER_EXCEPT) {
|
||||
AS_HANDLER(krk_currentThread.stackTop[-1]).type = OP_END_FINALLY;
|
||||
if (AS_HANDLER_TYPE(krk_currentThread.stackTop[-1])== OP_FILTER_EXCEPT) {
|
||||
krk_currentThread.stackTop[-1] = HANDLER_VAL(OP_END_FINALLY,AS_HANDLER_TARGET(krk_peek(0)));
|
||||
} else {
|
||||
AS_HANDLER(krk_currentThread.stackTop[-1]).type = OP_RAISE;
|
||||
krk_currentThread.stackTop[-1] = HANDLER_VAL(OP_RAISE,AS_HANDLER_TARGET(krk_peek(0)));
|
||||
}
|
||||
krk_currentThread.stackTop[-2] = krk_currentThread.currentException;
|
||||
krk_currentThread.currentException = NONE_VAL();
|
||||
|
@ -33,6 +33,6 @@ def __main__():
|
||||
ordering[m3] = px
|
||||
m0 = ordering[m0]
|
||||
|
||||
print(ordering[1]*ordering[ordering[1]])
|
||||
print(str(float(ordering[1])*ordering[ordering[1]]).replace('.0',''))
|
||||
|
||||
__main__()
|
||||
|
@ -41,5 +41,5 @@ class Baz(object):
|
||||
|
||||
let b = Baz()
|
||||
print(b.bar)
|
||||
b.bar = 0xDEADBEEF
|
||||
b.bar = 0xCAFE
|
||||
print(b.bar)
|
||||
|
@ -8,6 +8,6 @@ Called as a setter: [102]
|
||||
<class '__main__.Bar'> test
|
||||
I am a Python-style @property!
|
||||
42
|
||||
I am a Python-style @property's setter called with 3735928559
|
||||
I am a Python-style @property's setter called with 51966
|
||||
I am a Python-style @property!
|
||||
3735928559
|
||||
51966
|
||||
|
@ -303,7 +303,7 @@ static int doSecondPass(FILE * out) {
|
||||
|
||||
for (size_t i = 0; i < func->chunk.constants.count; ++i) {
|
||||
KrkValue * val = &func->chunk.constants.values[i];
|
||||
switch (val->type) {
|
||||
switch (KRK_VAL_TYPE(*val)) {
|
||||
case KRK_VAL_OBJECT:
|
||||
switch (AS_OBJECT(*val)->type) {
|
||||
case KRK_OBJ_STRING:
|
||||
@ -329,10 +329,11 @@ static int doSecondPass(FILE * out) {
|
||||
case KRK_VAL_INTEGER:
|
||||
WRITE_INTEGER(AS_INTEGER(*val));
|
||||
break;
|
||||
case KRK_VAL_FLOATING:
|
||||
default:
|
||||
if (IS_FLOATING(*val)) {
|
||||
WRITE_FLOATING(AS_FLOATING(*val));
|
||||
break;
|
||||
default:
|
||||
}
|
||||
fprintf(stderr,
|
||||
"Invalid value found in constants table,"
|
||||
"this marashal format can not store '%s'\n",
|
||||
|
Loading…
Reference in New Issue
Block a user