127 lines
2.6 KiB
C
127 lines
2.6 KiB
C
#pragma once
|
|
|
|
#include<stdbool.h>
|
|
#include<stdint.h>
|
|
#include<stddef.h>
|
|
#include<ctype.h>
|
|
#include<stdlib.h>
|
|
#include<stdio.h>
|
|
#include<string.h>
|
|
#include<math.h>
|
|
#include<assert.h>
|
|
|
|
#include"str.h"
|
|
|
|
#define LTAG_MASK 0xFFFF000000000000ULL
|
|
#define LTAG_NAN 0xFFF8000000000001ULL
|
|
#define LTAG_NIL 0xFFF8000000000002ULL
|
|
#define LTAG_FALSE 0xFFF8000000000003ULL
|
|
#define LTAG_TRUE 0xFFF8000000000004ULL
|
|
#define LTAG_I32 0xFFF9000000000000ULL
|
|
#define LTAG_TABLE 0xFFFA000000000000ULL
|
|
#define LTAG_USERDATA 0xFFFB000000000000ULL
|
|
#define LTAG_FUNCTION 0xFFFC000000000000ULL
|
|
#define LTAG_FLOAT 0xFFFD000000000000ULL
|
|
#define LTAG_STRING 0xFFFE000000000000ULL
|
|
|
|
typedef enum {
|
|
LT_NIL,
|
|
LT_STRING,
|
|
LT_NUMBER,
|
|
LT_INTEGER,
|
|
LT_TABLE,
|
|
LT_USERDATA,
|
|
LT_BOOLEAN,
|
|
LT_FUNCTION,
|
|
} LType;
|
|
|
|
typedef union {
|
|
double f;
|
|
uint64_t u;
|
|
} LValue;
|
|
|
|
static inline uint64_t lhash64(uint64_t val) {
|
|
val ^= (val >> 33);
|
|
val *= 0xff51afd7ed558ccdUL;
|
|
val ^= (val >> 33);
|
|
val *= 0xc4ceb9fe1a85ec53UL;
|
|
val ^= (val >> 33);
|
|
return val;
|
|
}
|
|
|
|
static inline LValue lvalue_from_double(double f) {
|
|
LValue v;
|
|
|
|
if(isnan(f)) {
|
|
// Normalize
|
|
v.u = LTAG_NAN;
|
|
} else {
|
|
v.f = f;
|
|
}
|
|
|
|
return (LValue) {.f = f};
|
|
}
|
|
|
|
static inline LValue lvalue_from_int32(int32_t i) {
|
|
return (LValue) {.u = LTAG_I32 | (uint32_t) i};
|
|
}
|
|
|
|
static inline LValue lvalue_from_bool(bool b) {
|
|
return (LValue) {.u = b ? LTAG_TRUE : LTAG_FALSE};
|
|
}
|
|
|
|
static inline LValue lvalue_from_nil() {
|
|
return (LValue) {.u = LTAG_NIL};
|
|
}
|
|
|
|
struct LTable;
|
|
static inline LValue lvalue_from_table(struct LTable *tbl) {
|
|
return (LValue) {.u = LTAG_TABLE | (uintptr_t) tbl};
|
|
}
|
|
|
|
struct LString;
|
|
static inline LValue lvalue_from_string(struct LString *str) {
|
|
return (LValue) {.u = LTAG_STRING | (uintptr_t) str};
|
|
}
|
|
|
|
struct LFunc;
|
|
static inline LValue lvalue_from_func(struct LFunc *f) {
|
|
return (LValue) {.u = LTAG_FUNCTION | (uintptr_t) f};
|
|
}
|
|
|
|
static inline int32_t lvalue_to_int32(LValue v) {
|
|
return v.u & ~LTAG_MASK;
|
|
}
|
|
|
|
static inline uint64_t lvalue_tag(LValue v) {
|
|
return v.u & LTAG_MASK;
|
|
}
|
|
|
|
static inline LValue lvalue_raw(uint64_t tag, uint64_t rawval) {
|
|
assert(rawval == (rawval & ~LTAG_MASK));
|
|
return (LValue) {.u = tag | rawval};
|
|
}
|
|
|
|
static inline uint64_t lvalue_hash(LValue lv) {
|
|
if(lvalue_tag(lv) == LTAG_STRING) {
|
|
LString *str = (LString*) (lv.u & ~LTAG_MASK);
|
|
|
|
uint64_t h = 0;
|
|
|
|
for(size_t i = 0; i < (str->length & ~7); i += 8) {
|
|
h = lhash64(h ^ *(uint64_t*) &str->data[i]);
|
|
}
|
|
|
|
uint64_t last = 0;
|
|
memcpy(&last, str->data + (str->length & ~7), str->length - (str->length & ~7));
|
|
|
|
h = lhash64(h ^ last);
|
|
|
|
return h;
|
|
}
|
|
|
|
return lhash64(lv.u);
|
|
}
|
|
|
|
bool lvalue_eq(LValue, LValue);
|