fork download
  1. #include <assert.h>
  2. #include <inttypes.h> // PRIx64
  3. #include <stdbool.h>
  4. #include <stdio.h>
  5. #include <stdlib.h> // malloc
  6. #include <stdint.h>
  7. #include <string.h>
  8.  
  9. // value.h
  10. typedef uint64_t Value;
  11.  
  12. #define SIGN_BIT ((uint64_t)0x8000000000000000)
  13. #define QNAN ((uint64_t)0x7ffc000000000000)
  14.  
  15. #define TAG_NIL 1 // 01.
  16. #define TAG_FALSE 2 // 10.
  17. #define TAG_TRUE 3 // 11.
  18.  
  19. #define BOOL_VAL(b) ((b) ? TRUE_VAL : FALSE_VAL)
  20. #define FALSE_VAL ((Value)(uint64_t)(QNAN | TAG_FALSE))
  21. #define TRUE_VAL ((Value)(uint64_t)(QNAN | TAG_TRUE))
  22. #define NIL_VAL ((Value)(uint64_t)(QNAN | TAG_NIL))
  23. #define NUMBER_VAL(num) numToValue(num)
  24. #define OBJ_VAL(obj) (Value)(SIGN_BIT | QNAN | (uint64_t)(uintptr_t)(obj))
  25.  
  26. #define IS_BOOL(value) (((value) | 1) == TRUE_VAL)
  27. #define IS_NIL(value) ((value) == NIL_VAL)
  28. #define IS_NUMBER(value) (((value) & QNAN) != QNAN)
  29. #define IS_OBJ(value) (((value) & (QNAN | SIGN_BIT)) == (QNAN | SIGN_BIT))
  30.  
  31. #define AS_BOOL(value) ((value) == TRUE_VAL)
  32. #define AS_NUMBER(value) valueToNum(value)
  33. #define AS_OBJ(value) ((Obj*)(uintptr_t)((value) & ~(SIGN_BIT | QNAN)))
  34.  
  35. static inline double valueToNum(Value value) {
  36. double num;
  37. memcpy(&num, &value, sizeof(Value));
  38. return num;
  39. }
  40.  
  41. static inline Value numToValue(double num) {
  42. Value value;
  43. memcpy(&value, &num, sizeof(double));
  44. return value;
  45. }
  46.  
  47. typedef struct Obj Obj;
  48. typedef struct ObjString ObjString;
  49.  
  50. // object.h
  51. #define OBJ_TYPE(value) (AS_OBJ(value)->type)
  52. #define IS_STRING(value) isObjType(value, OBJ_STRING)
  53. #define AS_STRING(value) ((ObjString*)AS_OBJ(value))
  54. #define AS_CSTRING(value) (((ObjString*)AS_OBJ(value))->chars)
  55.  
  56. typedef enum {
  57. // 他にも色々あるが、省略
  58. OBJ_STRING,
  59. } ObjType;
  60.  
  61. struct Obj {
  62. ObjType type;
  63. // bool isMarked;
  64. // struct Obj* next;
  65. };
  66.  
  67. struct ObjString {
  68. Obj obj;
  69. int length;
  70. char* chars;
  71. // uint32_t hash;
  72. };
  73.  
  74. #define ALLOCATE(type, count) \
  75.   (type*)reallocate(NULL, 0, sizeof(type) * (count))
  76.  
  77. #define reallocate(ptr, oldSize, newSize) realloc(ptr, newSize)
  78.  
  79. #define ALLOCATE_OBJ(type, objectType) \
  80.   (type*)allocateObject(sizeof(type), objectType)
  81.  
  82. static Obj* allocateObject(size_t size, ObjType type) {
  83. Obj* object = (Obj*)reallocate(NULL, 0, size);
  84. object->type = type;
  85. // object->isMarked = false;
  86.  
  87. // object->next = vm.objects;
  88. // vm.objects = object;
  89.  
  90. return object;
  91. }
  92.  
  93. static ObjString* allocateString(char* chars, int length /*, uint32_t hash*/) {
  94. ObjString* string = ALLOCATE_OBJ(ObjString, OBJ_STRING);
  95. string->length = length;
  96. string->chars = chars;
  97. // string->hash = hash;
  98.  
  99. // push(OBJ_VAL(string));
  100. // tableSet(&vm.strings, string, NIL_VAL);
  101. // pop();
  102.  
  103. return string;
  104. }
  105.  
  106. ObjString* copyString(const char* chars, int length) {
  107. // uint32_t hash = hashString(chars, length);
  108. // ObjString* interned = tableFindString(&vm.strings, chars, length,
  109. // hash);
  110. // if (interned != NULL) return interned;
  111.  
  112. char* heapChars = ALLOCATE(char, length + 1);
  113. memcpy(heapChars, chars, length);
  114. heapChars[length] = '\0';
  115. return allocateString(heapChars, length /*, hash*/);
  116. }
  117.  
  118. void printObject(Value value) {
  119. switch (OBJ_TYPE(value)) {
  120. case OBJ_STRING:
  121. printf("\"%s\"", AS_CSTRING(value));
  122. break;
  123. default: assert(false); break;
  124. }
  125. }
  126.  
  127. void printValue(Value value) {
  128. printf("%016" PRIx64 ": ", value);
  129.  
  130. if (IS_BOOL(value)) {
  131. printf(AS_BOOL(value) ? "true" : "false");
  132. } else if (IS_NIL(value)) {
  133. printf("nil");
  134. } else if (IS_NUMBER(value)) {
  135. printf("%g", AS_NUMBER(value));
  136. } else if (IS_OBJ(value)) {
  137. printObject(value);
  138. } else {
  139. assert(!"illegal value");
  140. }
  141. }
  142.  
  143. int main(void) {
  144. char s[] = "Hello, world!";
  145. Value str = OBJ_VAL(copyString(s, strlen(s)));
  146.  
  147. Value values[] = {
  148. NIL_VAL,
  149. FALSE_VAL,
  150. TRUE_VAL,
  151. NUMBER_VAL(1.234),
  152. NUMBER_VAL(-0.789e5),
  153. NUMBER_VAL(0.0),
  154. NUMBER_VAL(1.0 / 0.0),
  155. NUMBER_VAL(-1.0 / 0.0),
  156. NUMBER_VAL(0.0 / 0.0),
  157. str,
  158. };
  159.  
  160. for (size_t i = 0; i < sizeof(values) / sizeof(*values); ++i) {
  161. printValue(values[i]);
  162. printf("\n");
  163. }
  164.  
  165. return 0;
  166. }
  167.  
Success #stdin #stdout 0.01s 5360KB
stdin
Standard input is empty
stdout
7ffc000000000001: nil
7ffc000000000002: false
7ffc000000000003: true
3ff3be76c8b43958: 1.234
c0f3434000000000: -78900
0000000000000000: 0
7ff0000000000000: inf
fff0000000000000: -inf
7ff8000000000000: nan
fffc0000010d0280: "Hello, world!"