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.
68bool 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.
72bool 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.
76bool 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.
80bool 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.
84bool 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`.
90uint32_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.
95bool 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.
106uint32_t calculateRange(WrenVM* vm, ObjRange* range, uint32_t* length,
107 int* step);
108
109#endif
110