Exemple #1
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;
	}
}
Exemple #2
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;
}
Exemple #3
0
/* helper function for emitting meaningful error messages */
static void format_errmsg(char **msg, enum format_error_kind kind, int argidx, ...)
{
	va_list args;

	if (msg == NULL) {
		return;
	}

	va_start(args, argidx);

	switch (kind) {
	case TYPE_MISMATCH: {
		int expect = va_arg(args, int);
		int actual = va_arg(args, int);

		const void *argv[3];
		argv[0] = &argidx;
		argv[1] = spn_type_name(expect);
		argv[2] = spn_type_name(actual);

		*msg = spn_string_format_cstr("type mismatch in argument %i: expected %s, got %s", NULL, argv);
		break;
	}
	case EXPECT_INTEGER: {
		const void *argv[1];
		argv[0] = &argidx;
		*msg = spn_string_format_cstr("type mismatch in argument %i: expected integer, got floating-point", NULL, argv);
		break;
	}
	case INVALID_SPECIFIER: {
		long ch = va_arg(args, int); /* `char' is promoted to `int' */

		const void *argv[2];
		argv[0] = &ch;
		argv[1] = &argidx;
		*msg = spn_string_format_cstr("invalid format specifier `%%%c' at index %i", NULL, argv);
		break;
	}
	case OUT_OF_ARGUMENTS: {
		const void *argv[1];
		argv[0] = &argidx;
		*msg = spn_string_format_cstr("too few arguments (%i)", NULL, argv);
		break;
	}
	default:
		SHANT_BE_REACHED();
	}

	va_end(args);
}
Exemple #4
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;
}
Exemple #5
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;
}