util.h
Go to the documentation of this file.
1 #pragma once
10 #include "object.h"
11 #include "vm.h"
12 #include "memory.h"
13 
14 /* Quick macro for turning string constants into KrkString*s */
15 #define S(c) (krk_copyString(c,sizeof(c)-1))
16 
17 #define likely(cond) __builtin_expect((cond), 1)
18 #define unlikely(cond) __builtin_expect((cond), 0)
19 
20 #if !defined(__has_attribute)
21 # define __has_attribute(attr) 0
22 #endif
23 
24 #if __has_attribute(protected)
25 # define _protected __attribute__((protected))
26 #else
27 # define _protected
28 #endif
29 
30 #if !defined(_WIN32) && !defined(EFI_PLATFORM)
31 #define _noexport __attribute__((visibility("hidden")))
32 #else
33 #define _noexport
34 #endif
35 
36 #define ADD_BASE_CLASS(obj, name, baseClass) krk_makeClass(vm.builtins, &obj, name, baseClass)
37 
38 #define ATTRIBUTE_NOT_ASSIGNABLE() do { if (unlikely(argc != 1)) return krk_runtimeError(vm.exceptions->attributeError, "'%T' object has no attribute '%s'", \
39  argv[0], _method_name); } while (0)
40 
41 #define METHOD_TAKES_NONE() do { if (unlikely(argc != 1)) return krk_runtimeError(vm.exceptions->argumentError, "%s() takes no arguments (%d given)", \
42  _method_name, (argc-1)); } while (0)
43 
44 #define METHOD_TAKES_EXACTLY(n) do { if (unlikely(argc != (n+1))) return krk_runtimeError(vm.exceptions->argumentError, "%s() takes %s %d argument%s (%d given)", \
45  _method_name, "exactly", n, (n != 1) ? "s" : "", (argc-1)); } while (0)
46 
47 #define METHOD_TAKES_AT_LEAST(n) do { if (unlikely(argc < (n+1))) return krk_runtimeError(vm.exceptions->argumentError, "%s() takes %s %d argument%s (%d given)", \
48  _method_name, "at least", n, (n != 1) ? "s" : "", (argc-1)); } while (0)
49 
50 #define METHOD_TAKES_AT_MOST(n) do { if (unlikely(argc > (n+1))) return krk_runtimeError(vm.exceptions->argumentError, "%s() takes %s %d argument%s (%d given)", \
51  _method_name, "at most", n, (n != 1) ? "s" : "", (argc-1)); } while (0)
52 
53 #define FUNCTION_TAKES_NONE() do { if (unlikely(argc != 0)) return krk_runtimeError(vm.exceptions->argumentError, "%s() takes no arguments (%d given)", \
54  _method_name, (argc)); } while (0)
55 
56 #define FUNCTION_TAKES_EXACTLY(n) do { if (unlikely(argc != n)) return krk_runtimeError(vm.exceptions->argumentError, "%s() takes %s %d argument%s (%d given)", \
57  _method_name, "exactly", n, (n != 1) ? "s" : "", (argc)); } while (0)
58 
59 #define FUNCTION_TAKES_AT_LEAST(n) do { if (unlikely(argc < n)) return krk_runtimeError(vm.exceptions->argumentError, "%s() takes %s %d argument%s (%d given)", \
60  _method_name, "at least", n, (n != 1) ? "s" : "", (argc)); } while (0)
61 
62 #define FUNCTION_TAKES_AT_MOST(n) do { if (unlikely(argc > n)) return krk_runtimeError(vm.exceptions->argumentError, "%s() takes %s %d argument%s (%d given)", \
63  _method_name, "at most", n, (n != 1) ? "s" : "", (argc)); } while (0)
64 
65 #define TYPE_ERROR(expected,value) krk_runtimeError(vm.exceptions->typeError, "%s() expects %s, not '%T'", \
66  /* Function name */ _method_name, /* expected type */ #expected, value)
67 
68 #define NOT_ENOUGH_ARGS(name) krk_runtimeError(vm.exceptions->argumentError, "Expected more args.")
69 
70 #define CHECK_ARG(i, type, ctype, name) \
71  if (unlikely(argc < (i+1))) return NOT_ENOUGH_ARGS(name); \
72  if (unlikely(!IS_ ## type (argv[i]))) return TYPE_ERROR(type,argv[i]); \
73  ctype name __attribute__((unused)) = AS_ ## type (argv[i])
74 
75 #define FUNC_NAME(klass, name) _ ## klass ## _ ## name
76 #define FUNC_SIG(klass, name) _noexport KrkValue FUNC_NAME(klass,name) (int argc, const KrkValue argv[], int hasKw)
77 
78 /* These forms are deprecated. */
79 #define KRK_METHOD(klass, name, ...) FUNC_SIG(klass, name) { \
80  static __attribute__ ((unused)) const char* _method_name = # name; \
81  CHECK_ARG(0,klass,CURRENT_CTYPE,CURRENT_NAME); \
82  __VA_ARGS__ \
83  return NONE_VAL(); }
84 
85 #define KRK_FUNC(name,...) static KrkValue _krk_ ## name (int argc, const KrkValue argv[], int hasKw) { \
86  static __attribute__ ((unused)) const char* _method_name = # name; \
87  __VA_ARGS__ \
88  return NONE_VAL(); }
89 
90 /* This assumes you have a KrkInstance called `module` in the current scope. */
91 #define MAKE_CLASS(klass) do { krk_makeClass(module,&klass,#klass,vm.baseClasses->objectClass); klass ->allocSize = sizeof(struct klass); } while (0)
92 #define BIND_METHOD(klass,method) krk_defineNative(&klass->methods, #method, _ ## klass ## _ ## method)
93 #define BIND_PROP(klass,method) krk_defineNativeProperty(&klass->methods, #method, _ ## klass ## _ ## method)
94 #define BIND_FUNC(module,func) krk_defineNative(&module->fields, #func, _krk_ ## func)
95 
96 static inline KrkNative * krk_defineNativeStaticMethod(KrkTable * table, const char * name, NativeFn function) {
97  KrkNative * out = krk_defineNative(table,name,function);
98  out->obj.flags |= KRK_OBJ_FLAGS_FUNCTION_IS_STATIC_METHOD;
99  return out;
100 }
101 #define BIND_STATICMETHOD(klass,method) krk_defineNativeStaticMethod(&klass->methods, #method, _ ## klass ## _ ## method)
102 
103 static inline KrkNative * krk_defineNativeClassMethod(KrkTable * table, const char * name, NativeFn function) {
104  KrkNative * out = krk_defineNative(table,name,function);
105  out->obj.flags |= KRK_OBJ_FLAGS_FUNCTION_IS_CLASS_METHOD;
106  return out;
107 }
108 #define BIND_CLASSMETHOD(klass,method) krk_defineNativeClassMethod(&klass->methods, #method, _ ## klass ## _ ## method)
109 
110 #define KRK_Method_internal_name(klass, name) \
111  _krk_method_ ## klass ## _ ## name
112 #define KRK_Method_internal_sig(klass, name) \
113  static inline KrkValue KRK_Method_internal_name(klass,name) (const char * _method_name, CURRENT_CTYPE CURRENT_NAME, int argc, const KrkValue argv[], int hasKw)
114 
115 #define KRK_Method(klass, name) \
116  KRK_Method_internal_sig(klass, name); \
117  FUNC_SIG(klass, name) { \
118  static const char * _method_name = # name; \
119  CHECK_ARG(0,klass,CURRENT_CTYPE,CURRENT_NAME); \
120  return KRK_Method_internal_name(klass,name)(_method_name, CURRENT_NAME, argc, argv, hasKw); \
121  } \
122  KRK_Method_internal_sig(klass,name)
123 
124 #define KRK_Function_internal_name(name) \
125  _krk_function_ ## name
126 #define KRK_Function_internal_sig(name) \
127  static inline KrkValue KRK_Function_internal_name(name) (const char * _method_name, int argc, const KrkValue argv[], int hasKw)
128 
129 #define KRK_Function(name) \
130  KRK_Function_internal_sig(name); \
131  static KrkValue _krk_ ## name (int argc, const KrkValue argv[], int hasKw) { \
132  static const char* _method_name = # name; \
133  return KRK_Function_internal_name(name)(_method_name,argc,argv,hasKw); \
134  } \
135  KRK_Function_internal_sig(name)
136 
137 #define KRK_StaticMethod_internal_sig(klass, name) \
138  static inline KrkValue KRK_Method_internal_name(klass, name) (const char * _method_name, int argc, const KrkValue argv[], int hasKw)
139 #define KRK_StaticMethod(klass, name) \
140  KRK_StaticMethod_internal_sig(klass, name); \
141  FUNC_SIG(klass, name) { \
142  static const char * _method_name = # name; \
143  return KRK_Method_internal_name(klass,name)(_method_name,argc,argv,hasKw); \
144  } \
145  KRK_StaticMethod_internal_sig(klass,name)
146 
151  size_t capacity;
152  size_t length;
153  char * bytes;
154 };
155 
162 void krk_pushStringBuilder(struct StringBuilder * sb, char c);
163 #define pushStringBuilder krk_pushStringBuilder
164 
172 void krk_pushStringBuilderStr(struct StringBuilder * sb, const char *str, size_t len);
173 #define pushStringBuilderStr krk_pushStringBuilderStr
174 
186 #define finishStringBuilder krk_finishStringBuilder
187 
198 #define finishStringBuilderBytes krk_finishStringBuilderBytes
199 
211 #define discardStringBuilder krk_discardStringBuilder
212 
213 #define IS_int(o) (IS_INTEGER(o))
214 #define AS_int(o) (AS_INTEGER(o))
215 
216 #define IS_bool(o) (IS_BOOLEAN(o))
217 #define AS_bool(o) (AS_BOOLEAN(o))
218 
219 #define IS_float(o) (IS_FLOATING(o))
220 #define AS_float(o) (AS_FLOATING(o))
221 
222 #define IS_list(o) ((IS_INSTANCE(o) && AS_INSTANCE(o)->_class == vm.baseClasses->listClass) || krk_isInstanceOf(o,vm.baseClasses->listClass))
223 #define AS_list(o) (KrkList*)AS_OBJECT(o)
224 
225 #define IS_tuple(o) IS_TUPLE(o)
226 #define AS_tuple(o) AS_TUPLE(o)
227 
228 #define IS_bytes(o) IS_BYTES(o)
229 #define AS_bytes(o) AS_BYTES(o)
230 
231 #define IS_class(o) IS_CLASS(o)
232 #define AS_class(o) AS_CLASS(o)
233 
234 #define IS_str(o) (IS_STRING(o)||krk_isInstanceOf(o,vm.baseClasses->strClass))
235 #define AS_str(o) (KrkString*)AS_OBJECT(o)
236 
237 #define IS_striterator(o) (krk_isInstanceOf(o,vm.baseClasses->striteratorClass))
238 #define AS_striterator(o) (AS_INSTANCE(o))
239 
240 #define IS_dict(o) ((IS_INSTANCE(o) && AS_INSTANCE(o)->_class == vm.baseClasses->dictClass) || krk_isInstanceOf(o,vm.baseClasses->dictClass))
241 #define AS_dict(o) (KrkDict*)AS_OBJECT(o)
242 
243 #define IS_dictitems(o) krk_isInstanceOf(o,vm.baseClasses->dictitemsClass)
244 #define AS_dictitems(o) ((struct DictItems*)AS_OBJECT(o))
245 
246 #define IS_dictkeys(o) krk_isInstanceOf(o,vm.baseClasses->dictkeysClass)
247 #define AS_dictkeys(o) ((struct DictKeys*)AS_OBJECT(o))
248 
249 #define IS_dictvalues(o) krk_isInstanceOf(o,vm.baseClasses->dictvaluesClass)
250 #define AS_dictvalues(o) ((struct DictValues*)AS_OBJECT(o))
251 
252 #define IS_bytearray(o) (krk_isInstanceOf(o,vm.baseClasses->bytearrayClass))
253 #define AS_bytearray(o) ((struct ByteArray*)AS_INSTANCE(o))
254 
255 #define IS_slice(o) krk_isInstanceOf(o,vm.baseClasses->sliceClass)
256 #define AS_slice(o) ((struct KrkSlice*)AS_INSTANCE(o))
257 
258 extern KrkValue krk_dict_nth_key_fast(size_t capacity, KrkTableEntry * entries, size_t index);
259 extern KrkValue FUNC_NAME(str,__getitem__)(int,const KrkValue*,int);
260 extern KrkValue FUNC_NAME(str,split)(int,const KrkValue*,int);
261 extern KrkValue FUNC_NAME(str,format)(int,const KrkValue*,int);
262 #define krk_string_get FUNC_NAME(str,__getitem__)
263 #define krk_string_split FUNC_NAME(str,split)
264 #define krk_string_format FUNC_NAME(str,format)
265 
266 static inline void _setDoc_class(KrkClass * thing, const char * text, size_t size) {
267  krk_attachNamedObject(&thing->methods, "__doc__", (KrkObj*)krk_copyString(text, size));
268 }
269 static inline void _setDoc_instance(KrkInstance * thing, const char * text, size_t size) {
270  krk_attachNamedObject(&thing->fields, "__doc__", (KrkObj*)krk_copyString(text, size));
271 }
272 static inline void _setDoc_native(KrkNative * thing, const char * text, size_t size) {
273  (void)size;
274  thing->doc = text;
275 }
276 
289 #ifdef KRK_NO_DOCUMENTATION
290 # define KRK_DOC(thing, text) (thing);
291 #else
292 # define KRK_DOC(thing, text) \
293  _Generic(&((thing)[0]), \
294  KrkClass*: _setDoc_class, \
295  KrkInstance*: _setDoc_instance, \
296  KrkNative*: _setDoc_native \
297  )(thing,text,sizeof(text)-1)
298 #endif
299 
300 #define BUILTIN_FUNCTION(name, func, docStr) KRK_DOC(krk_defineNative(&vm.builtins->fields, name, func), docStr)
301 
302 extern int krk_extractSlicer(const char * _method_name, KrkValue slicerVal, krk_integer_type count, krk_integer_type *start, krk_integer_type *end, krk_integer_type *step);
303 #define KRK_SLICER(arg,count) \
304  krk_integer_type start; \
305  krk_integer_type end; \
306  krk_integer_type step; \
307  if (krk_extractSlicer(_method_name, arg, count, &start, &end, &step))
308 
320 extern int krk_unpackIterable(KrkValue iterable, void * context, int callback(void *, const KrkValue *, size_t));
321 
322 
323 #define KRK_BASE_CLASS(cls) (vm.baseClasses->cls ## Class)
324 #define KRK_EXC(exc) (vm.exceptions->exc)
325 
326 
327 extern int krk_parseVArgs(
328  const char * _method_name,
329  int argc, const KrkValue argv[], int hasKw,
330  const char * fmt, const char ** names, va_list args);
331 
332 extern int krk_parseArgs_impl(
333  const char * _method_name,
334  int argc, const KrkValue argv[], int hasKw,
335  const char * format, const char ** names, ...);
336 
348 #define krk_parseArgs(f,n,...) krk_parseArgs_impl(_method_name,argc,argv,hasKw,f,n,__VA_ARGS__)
349 
350 
351 extern int krk_pushStringBuilderFormatV(struct StringBuilder * sb, const char * fmt, va_list args);
352 extern int krk_pushStringBuilderFormat(struct StringBuilder * sb, const char * fmt, ...);
353 extern KrkValue krk_stringFromFormat(const char * fmt, ...);
354 extern int krk_long_to_int(KrkValue val, char size, void * out);
355 extern int krk_isSubClass(const KrkClass * cls, const KrkClass * base);
Functions for dealing with garbage collection and memory allocation.
Struct definitions for core object types.
Type object.
Definition: object.h:189
KrkTable methods
General attributes table.
Definition: object.h:192
An object of a class.
Definition: object.h:255
KrkTable fields
Attributes table.
Definition: object.h:258
Managed binding to a C function.
Definition: object.h:283
const char * doc
Docstring to supply from __doc__.
Definition: object.h:287
KrkObj obj
Base.
Definition: object.h:284
The most basic object type.
Definition: object.h:41
uint16_t flags
General object flags, mostly related to garbage collection.
Definition: object.h:43
KrkString * krk_copyString(const char *chars, size_t length)
Obtain a string object representation of the given C string.
Definition: object.c:221
One (key,value) pair in a table.
Definition: table.h:20
Simple hash table of arbitrary keys to values.
Definition: table.h:28
void krk_attachNamedObject(KrkTable *table, const char name[], KrkObj *obj)
Attach an object to an attribute table.
Definition: vm.c:839
KrkNative * krk_defineNative(KrkTable *table, const char *name, NativeFn function)
Attach a native C function to an attribute table.
Definition: vm.c:194
Stack reference or primative value.
Inline flexible string array.
Definition: util.h:150
void krk_pushStringBuilderStr(struct StringBuilder *sb, const char *str, size_t len)
Append a string to the end of a string builder.
Definition: obj_str.c:1059
KrkValue krk_finishStringBuilderBytes(struct StringBuilder *sb)
Finalize a string builder in a bytes object.
Definition: obj_str.c:1085
int krk_long_to_int(KrkValue val, char size, void *out)
Convert an int or long to a C integer.
Definition: obj_long.c:1963
KrkValue krk_discardStringBuilder(struct StringBuilder *sb)
Discard the contents of a string builder.
Definition: obj_str.c:1091
int krk_unpackIterable(KrkValue iterable, void *context, int callback(void *, const KrkValue *, size_t))
Unpack an iterable.
Definition: builtins.c:380
KrkValue krk_finishStringBuilder(struct StringBuilder *sb)
Finalize a string builder into a string object.
Definition: obj_str.c:1079
int krk_parseArgs_impl(const char *_method_name, int argc, const KrkValue argv[], int hasKw, const char *format, const char **names,...)
Variable argument version of krk_parseVArgs.
Definition: parseargs.c:416
void krk_pushStringBuilder(struct StringBuilder *sb, char c)
Add a character to the end of a string builder.
Definition: obj_str.c:1050
int krk_parseVArgs(const char *_method_name, int argc, const KrkValue argv[], int hasKw, const char *fmt, const char **names, va_list args)
Validate and parse arguments to a function similar to how managed function arguments are handled.
Definition: parseargs.c:39
Core API for the bytecode virtual machine.