Esempio n. 1
0
int spn_values_comparable(const SpnValue *lhs, const SpnValue *rhs)
{
	if (isnum(lhs) && isnum(rhs)) {
		return 1;
	}

	if (isobject(lhs) && isobject(rhs)) {
		SpnObject *obl = objvalue(lhs), *obr = objvalue(rhs);
		if (!class_equal(obl->isa, obr->isa)) {
			return 0;
		}

		return obl->isa->compare != NULL;
	}

	return 0;
}
Esempio n. 2
0
void spn_value_print(const SpnValue *val)
{
	switch (valtype(val)) {
	case SPN_TTAG_NIL: {
		fputs("nil", stdout);
		break;
	}
	case SPN_TTAG_BOOL: {
		fputs(boolvalue(val) ? "true" : "false", stdout);
		break;
	}
	case SPN_TTAG_NUMBER: {
		if (isfloat(val)) {
			printf("%.*g", DBL_DIG, floatvalue(val));
		} else {
			printf("%ld", intvalue(val));
		}

		break;
	}
	case SPN_TTAG_STRING: {
		SpnString *s = stringvalue(val);
		fputs(s->cstr, stdout);
		break;
	}
	case SPN_TTAG_ARRAY: {
		SpnArray *array = objvalue(val);
		print_array(array, 0);
		break;
	}
	case SPN_TTAG_HASHMAP: {
		SpnHashMap *hashmap = objvalue(val);
		print_hashmap(hashmap, 0);
		break;
	}
	case SPN_TTAG_FUNC: {
		SpnFunction *func = funcvalue(val);
		void *p;

		if (func->native) {
			p = (void *)(ptrdiff_t)(func->repr.fn);
		} else {
			p = func->repr.bc;
		}

		printf("<function %p>", p);
		break;
	}
	case SPN_TTAG_USERINFO: {
		void *ptr = isobject(val) ? objvalue(val) : ptrvalue(val);
		printf("<userinfo %p>", ptr);
		break;
	}
	default:
		SHANT_BE_REACHED();
		break;
	}
}
Esempio n. 3
0
void spn_value_release(const SpnValue *val)
{
	if (isobject(val)) {
		assert(isstring(val) || isarray(val)
		   || ishashmap(val) || isfunc(val)
		   || isuserinfo(val));

		spn_object_release(objvalue(val));
	}
}
Esempio n. 4
0
int spn_value_equal(const SpnValue *lhs, const SpnValue *rhs)
{
	/* first, make sure that we compare values of the same type
	 * (values of different types cannot possibly be equal)
	 */
	if (valtype(lhs) != valtype(rhs)) {
		return 0;
	}

	switch (valtype(lhs)) {
	case SPN_TTAG_NIL:    { return 1; /* nil can only be nil */ }
	case SPN_TTAG_BOOL:   { return boolvalue(lhs) == boolvalue(rhs); }
	case SPN_TTAG_NUMBER: { return numeric_equal(lhs, rhs); }

	case SPN_TTAG_STRING:
	case SPN_TTAG_ARRAY:
	case SPN_TTAG_HASHMAP:
	case SPN_TTAG_FUNC: {
		return spn_object_equal(objvalue(lhs), objvalue(rhs));
	}

	case SPN_TTAG_USERINFO: {
		/* an object can not equal a non-object */
		if (isobject(lhs) != isobject(rhs)) {
			return 0;
		}

		if (isobject(lhs)) {
			return spn_object_equal(objvalue(lhs), objvalue(rhs));
		} else {
			return ptrvalue(lhs) == ptrvalue(rhs);
		}
	}
	default:
		SHANT_BE_REACHED();
	}

	return 0;
}
Esempio n. 5
0
unsigned long spn_hash_value(const SpnValue *key)
{
	switch (valtype(key)) {
	case SPN_TTAG_NIL:	{ return 0; }
	case SPN_TTAG_BOOL:	{ return boolvalue(key); /* 0 or 1 */ }
	case SPN_TTAG_NUMBER: {
		if (isfloat(key)) {
			double f = floatvalue(key);

			/* only test for integer if it fits into one (anti-UB) */
			if (LONG_MIN <= f && f <= LONG_MAX) {
				long i = f; /* truncate */

				if (f == i) {
					/* it's really an integer.
					 * This takes care of the +/- 0 problem too
					 * (since 0 itself is an integer)
					 */
					return i;
				}
			} else {
				return spn_hash_bytes(&f, sizeof f);
			}
		}

		/* the hash value of an integer is itself */
		return intvalue(key);
	}
	case SPN_TTAG_STRING:
	case SPN_TTAG_ARRAY:
	case SPN_TTAG_HASHMAP:
	case SPN_TTAG_FUNC: {
		SpnObject *obj = objvalue(key);
		unsigned long (*hashfn)(void *) = obj->isa->hashfn;
		return hashfn ? hashfn(obj) : (unsigned long)(obj);
	}
	case SPN_TTAG_USERINFO: {
		if (isobject(key)) {
			SpnObject *obj = objvalue(key);
			unsigned long (*hashfn)(void *) = obj->isa->hashfn;
			return hashfn ? hashfn(obj) : (unsigned long)(obj);
		}

		return (unsigned long)(ptrvalue(key));
	}
	default:
		SHANT_BE_REACHED();
	}

	return 0;
}
Esempio n. 6
0
unsigned long spn_hash_value(const SpnValue *key)
{
	switch (valtype(key)) {
	case SPN_TTAG_NIL:	{ return 0; }
	case SPN_TTAG_BOOL:	{ return boolvalue(key); /* 0 or 1 */ }
	case SPN_TTAG_NUMBER: {
		if (isfloat(key)) {
			double f = floatvalue(key);
			long i = f; /* truncate */

			if (f == i) {
				return i; /* it's really an integer */
			} else {
				return spn_hash_bytes(&f, sizeof f);
			}
		}

		/* the hash value of an integer is itself */
		return intvalue(key);
	}
	case SPN_TTAG_STRING:
	case SPN_TTAG_ARRAY:
	case SPN_TTAG_HASHMAP:
	case SPN_TTAG_FUNC: {
		SpnObject *obj = objvalue(key);
		unsigned long (*hashfn)(void *) = obj->isa->hashfn;
		return hashfn ? hashfn(obj) : (unsigned long)(obj);
	}
	case SPN_TTAG_USERINFO: {
		if (isobject(key)) {
			SpnObject *obj = objvalue(key);
			unsigned long (*hashfn)(void *) = obj->isa->hashfn;
			return hashfn ? hashfn(obj) : (unsigned long)(obj);
		}

		return (unsigned long)(ptrvalue(key));
	}
	default:
		SHANT_BE_REACHED();
	}

	return 0;
}