| 1 | #ifndef wren_primitive_h | 
|---|
| 2 | #define wren_primitive_h | 
|---|
| 3 |  | 
|---|
| 4 | #include "wren_vm.h" | 
|---|
| 5 |  | 
|---|
| 6 | // Binds a primitive method named [name] (in Wren) implemented using C function | 
|---|
| 7 | // [fn] to `ObjClass` [cls]. | 
|---|
| 8 | #define PRIMITIVE(cls, name, function)                                         \ | 
|---|
| 9 | do                                                                         \ | 
|---|
| 10 | {                                                                          \ | 
|---|
| 11 | int symbol = wrenSymbolTableEnsure(vm,                                   \ | 
|---|
| 12 | &vm->methodNames, name, strlen(name));                               \ | 
|---|
| 13 | Method method;                                                           \ | 
|---|
| 14 | method.type = METHOD_PRIMITIVE;                                          \ | 
|---|
| 15 | method.as.primitive = prim_##function;                                   \ | 
|---|
| 16 | wrenBindMethod(vm, cls, symbol, method);                                 \ | 
|---|
| 17 | } while (false) | 
|---|
| 18 |  | 
|---|
| 19 | // Binds a primitive method named [name] (in Wren) implemented using C function | 
|---|
| 20 | // [fn] to `ObjClass` [cls], but as a FN call. | 
|---|
| 21 | #define FUNCTION_CALL(cls, name, function)                                     \ | 
|---|
| 22 | do                                                                         \ | 
|---|
| 23 | {                                                                          \ | 
|---|
| 24 | int symbol = wrenSymbolTableEnsure(vm,                                   \ | 
|---|
| 25 | &vm->methodNames, name, strlen(name));                               \ | 
|---|
| 26 | Method method;                                                           \ | 
|---|
| 27 | method.type = METHOD_FUNCTION_CALL;                                      \ | 
|---|
| 28 | method.as.primitive = prim_##function;                                   \ | 
|---|
| 29 | wrenBindMethod(vm, cls, symbol, method);                                 \ | 
|---|
| 30 | } while (false) | 
|---|
| 31 |  | 
|---|
| 32 | // Defines a primitive method whose C function name is [name]. This abstracts | 
|---|
| 33 | // the actual type signature of a primitive function and makes it clear which C | 
|---|
| 34 | // functions are invoked as primitives. | 
|---|
| 35 | #define DEF_PRIMITIVE(name)                                                    \ | 
|---|
| 36 | static bool prim_##name(WrenVM* vm, Value* args) | 
|---|
| 37 |  | 
|---|
| 38 | #define RETURN_VAL(value)                                                      \ | 
|---|
| 39 | do                                                                         \ | 
|---|
| 40 | {                                                                          \ | 
|---|
| 41 | args[0] = value;                                                         \ | 
|---|
| 42 | return true;                                                             \ | 
|---|
| 43 | } while (false) | 
|---|
| 44 |  | 
|---|
| 45 | #define RETURN_OBJ(obj)     RETURN_VAL(OBJ_VAL(obj)) | 
|---|
| 46 | #define RETURN_BOOL(value)  RETURN_VAL(BOOL_VAL(value)) | 
|---|
| 47 | #define RETURN_FALSE        RETURN_VAL(FALSE_VAL) | 
|---|
| 48 | #define RETURN_NULL         RETURN_VAL(NULL_VAL) | 
|---|
| 49 | #define RETURN_NUM(value)   RETURN_VAL(NUM_VAL(value)) | 
|---|
| 50 | #define RETURN_TRUE         RETURN_VAL(TRUE_VAL) | 
|---|
| 51 |  | 
|---|
| 52 | #define RETURN_ERROR(msg)                                                      \ | 
|---|
| 53 | do                                                                         \ | 
|---|
| 54 | {                                                                          \ | 
|---|
| 55 | vm->fiber->error = wrenNewStringLength(vm, msg, sizeof(msg) - 1);        \ | 
|---|
| 56 | return false;                                                            \ | 
|---|
| 57 | } while (false) | 
|---|
| 58 |  | 
|---|
| 59 | #define RETURN_ERROR_FMT(...)                                                  \ | 
|---|
| 60 | do                                                                         \ | 
|---|
| 61 | {                                                                          \ | 
|---|
| 62 | vm->fiber->error = wrenStringFormat(vm, __VA_ARGS__);                    \ | 
|---|
| 63 | return false;                                                            \ | 
|---|
| 64 | } while (false) | 
|---|
| 65 |  | 
|---|
| 66 | // Validates that the given [arg] is a function. Returns true if it is. If not, | 
|---|
| 67 | // reports an error and returns false. | 
|---|
| 68 | bool validateFn(WrenVM* vm, Value arg, const char* argName); | 
|---|
| 69 |  | 
|---|
| 70 | // Validates that the given [arg] is a Num. Returns true if it is. If not, | 
|---|
| 71 | // reports an error and returns false. | 
|---|
| 72 | bool validateNum(WrenVM* vm, Value arg, const char* argName); | 
|---|
| 73 |  | 
|---|
| 74 | // Validates that [value] is an integer. Returns true if it is. If not, reports | 
|---|
| 75 | // an error and returns false. | 
|---|
| 76 | bool validateIntValue(WrenVM* vm, double value, const char* argName); | 
|---|
| 77 |  | 
|---|
| 78 | // Validates that the given [arg] is an integer. Returns true if it is. If not, | 
|---|
| 79 | // reports an error and returns false. | 
|---|
| 80 | bool validateInt(WrenVM* vm, Value arg, const char* argName); | 
|---|
| 81 |  | 
|---|
| 82 | // Validates that [arg] is a valid object for use as a map key. Returns true if | 
|---|
| 83 | // it is. If not, reports an error and returns false. | 
|---|
| 84 | bool validateKey(WrenVM * vm, Value arg); | 
|---|
| 85 |  | 
|---|
| 86 | // Validates that the argument at [argIndex] is an integer within `[0, count)`. | 
|---|
| 87 | // Also allows negative indices which map backwards from the end. Returns the | 
|---|
| 88 | // valid positive index value. If invalid, reports an error and returns | 
|---|
| 89 | // `UINT32_MAX`. | 
|---|
| 90 | uint32_t validateIndex(WrenVM* vm, Value arg, uint32_t count, | 
|---|
| 91 | const char* argName); | 
|---|
| 92 |  | 
|---|
| 93 | // Validates that the given [arg] is a String. Returns true if it is. If not, | 
|---|
| 94 | // reports an error and returns false. | 
|---|
| 95 | bool validateString(WrenVM* vm, Value arg, const char* argName); | 
|---|
| 96 |  | 
|---|
| 97 | // Given a [range] and the [length] of the object being operated on, determines | 
|---|
| 98 | // the series of elements that should be chosen from the underlying object. | 
|---|
| 99 | // Handles ranges that count backwards from the end as well as negative ranges. | 
|---|
| 100 | // | 
|---|
| 101 | // Returns the index from which the range should start or `UINT32_MAX` if the | 
|---|
| 102 | // range is invalid. After calling, [length] will be updated with the number of | 
|---|
| 103 | // elements in the resulting sequence. [step] will be direction that the range | 
|---|
| 104 | // is going: `1` if the range is increasing from the start index or `-1` if the | 
|---|
| 105 | // range is decreasing. | 
|---|
| 106 | uint32_t calculateRange(WrenVM* vm, ObjRange* range, uint32_t* length, | 
|---|
| 107 | int* step); | 
|---|
| 108 |  | 
|---|
| 109 | #endif | 
|---|
| 110 |  | 
|---|