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 #if __has_attribute(unused)
37 # define _unused __attribute__((unused))
38 #else
39 # define _unused
40 #endif
41 
42 #if __has_attribute(hot)
43 # define _hot __attribute__((hot))
44 #else
45 # define _hot
46 #endif
47 
48 #if __has_attribute(cold)
49 # define _cold __attribute__((cold))
50 #else
51 # define _cold
52 #endif
53 
54 #if __has_attribute(nonnull)
55 # define _nonnull __attribute__((nonnull))
56 #else
57 # define _nonnull
58 #endif
59 
60 #define ADD_BASE_CLASS(obj, name, baseClass) krk_makeClass(vm.builtins, &obj, name, baseClass)
61 
62 #define ATTRIBUTE_NOT_ASSIGNABLE() do { if (unlikely(argc != 1)) return krk_runtimeError(vm.exceptions->attributeError, "'%T' object has no attribute '%s'", \
63  argv[0], _method_name); } while (0)
64 
65 #define METHOD_TAKES_NONE() do { if (unlikely(argc != 1)) return krk_runtimeError(vm.exceptions->argumentError, "%s() takes no arguments (%d given)", \
66  _method_name, (argc-1)); } while (0)
67 
68 #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)", \
69  _method_name, "exactly", n, (n != 1) ? "s" : "", (argc-1)); } while (0)
70 
71 #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)", \
72  _method_name, "at least", n, (n != 1) ? "s" : "", (argc-1)); } while (0)
73 
74 #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)", \
75  _method_name, "at most", n, (n != 1) ? "s" : "", (argc-1)); } while (0)
76 
77 #define FUNCTION_TAKES_NONE() do { if (unlikely(argc != 0)) return krk_runtimeError(vm.exceptions->argumentError, "%s() takes no arguments (%d given)", \
78  _method_name, (argc)); } while (0)
79 
80 #define FUNCTION_TAKES_EXACTLY(n) do { if (unlikely(argc != n)) return krk_runtimeError(vm.exceptions->argumentError, "%s() takes %s %d argument%s (%d given)", \
81  _method_name, "exactly", n, (n != 1) ? "s" : "", (argc)); } while (0)
82 
83 #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)", \
84  _method_name, "at least", n, (n != 1) ? "s" : "", (argc)); } while (0)
85 
86 #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)", \
87  _method_name, "at most", n, (n != 1) ? "s" : "", (argc)); } while (0)
88 
89 #define TYPE_ERROR(expected,value) krk_runtimeError(vm.exceptions->typeError, "%s() expects %s, not '%T'", \
90  /* Function name */ _method_name, /* expected type */ #expected, value)
91 
92 #define NOT_ENOUGH_ARGS(name) krk_runtimeError(vm.exceptions->argumentError, "Expected more args.")
93 
94 #define CHECK_ARG(i, type, ctype, name) \
95  if (unlikely(argc < (i+1))) return NOT_ENOUGH_ARGS(name); \
96  if (unlikely(!IS_ ## type (argv[i]))) return TYPE_ERROR(type,argv[i]); \
97  ctype name _unused = AS_ ## type (argv[i])
98 
99 #define FUNC_NAME(klass, name) _ ## klass ## _ ## name
100 #define FUNC_SIG(klass, name) _noexport KrkValue FUNC_NAME(klass,name) (int argc, const KrkValue argv[], int hasKw)
101 
102 /* This assumes you have a KrkInstance called `module` in the current scope. */
103 #define MAKE_CLASS(klass) do { krk_makeClass(module,&klass,#klass,vm.baseClasses->objectClass); klass ->allocSize = sizeof(struct klass); } while (0)
104 #define BIND_METHOD(klass,method) krk_defineNative(&klass->methods, #method, _ ## klass ## _ ## method)
105 #define BIND_PROP(klass,method) krk_defineNativeProperty(&klass->methods, #method, _ ## klass ## _ ## method)
106 #define BIND_FUNC(module,func) krk_defineNative(&module->fields, #func, _krk_ ## func)
107 
108 static inline KrkNative * krk_defineNativeStaticMethod(KrkTable * table, const char * name, NativeFn function) {
109  KrkNative * out = krk_defineNative(table,name,function);
110  out->obj.flags |= KRK_OBJ_FLAGS_FUNCTION_IS_STATIC_METHOD;
111  return out;
112 }
113 #define BIND_STATICMETHOD(klass,method) krk_defineNativeStaticMethod(&klass->methods, #method, _ ## klass ## _ ## method)
114 
115 static inline KrkNative * krk_defineNativeClassMethod(KrkTable * table, const char * name, NativeFn function) {
116  KrkNative * out = krk_defineNative(table,name,function);
117  out->obj.flags |= KRK_OBJ_FLAGS_FUNCTION_IS_CLASS_METHOD;
118  return out;
119 }
120 #define BIND_CLASSMETHOD(klass,method) krk_defineNativeClassMethod(&klass->methods, #method, _ ## klass ## _ ## method)
121 
122 #define KRK_Method_internal_name(klass, name) \
123  _krk_method_ ## klass ## _ ## name
124 #define KRK_Method_internal_sig(klass, name) \
125  static inline KrkValue KRK_Method_internal_name(klass,name) (const char * _method_name, CURRENT_CTYPE CURRENT_NAME, int argc, const KrkValue argv[], int hasKw)
126 
127 #define KRK_Method(klass, name) \
128  KRK_Method_internal_sig(klass, name); \
129  FUNC_SIG(klass, name) { \
130  static const char * _method_name = # name; \
131  CHECK_ARG(0,klass,CURRENT_CTYPE,CURRENT_NAME); \
132  return KRK_Method_internal_name(klass,name)(_method_name, CURRENT_NAME, argc, argv, hasKw); \
133  } \
134  KRK_Method_internal_sig(klass,name)
135 
136 #define KRK_Function_internal_name(name) \
137  _krk_function_ ## name
138 #define KRK_Function_internal_sig(name) \
139  static inline KrkValue KRK_Function_internal_name(name) (const char * _method_name, int argc, const KrkValue argv[], int hasKw)
140 
141 #define KRK_Function(name) \
142  KRK_Function_internal_sig(name); \
143  static KrkValue _krk_ ## name (int argc, const KrkValue argv[], int hasKw) { \
144  static const char* _method_name = # name; \
145  return KRK_Function_internal_name(name)(_method_name,argc,argv,hasKw); \
146  } \
147  KRK_Function_internal_sig(name)
148 
149 #define KRK_StaticMethod_internal_sig(klass, name) \
150  static inline KrkValue KRK_Method_internal_name(klass, name) (const char * _method_name, int argc, const KrkValue argv[], int hasKw)
151 #define KRK_StaticMethod(klass, name) \
152  KRK_StaticMethod_internal_sig(klass, name); \
153  FUNC_SIG(klass, name) { \
154  static const char * _method_name = # name; \
155  return KRK_Method_internal_name(klass,name)(_method_name,argc,argv,hasKw); \
156  } \
157  KRK_StaticMethod_internal_sig(klass,name)
158 
163  size_t capacity;
164  size_t length;
165  char * bytes;
166 };
167 
174 void krk_pushStringBuilder(struct StringBuilder * sb, char c);
175 #define pushStringBuilder krk_pushStringBuilder
176 
184 void krk_pushStringBuilderStr(struct StringBuilder * sb, const char *str, size_t len);
185 #define pushStringBuilderStr krk_pushStringBuilderStr
186 
198 #define finishStringBuilder krk_finishStringBuilder
199 
210 #define finishStringBuilderBytes krk_finishStringBuilderBytes
211 
223 #define discardStringBuilder krk_discardStringBuilder
224 
225 #define IS_int(o) (IS_INTEGER(o))
226 #define AS_int(o) (AS_INTEGER(o))
227 
228 #define IS_bool(o) (IS_BOOLEAN(o))
229 #define AS_bool(o) (AS_BOOLEAN(o))
230 
231 #define IS_float(o) (IS_FLOATING(o))
232 #define AS_float(o) (AS_FLOATING(o))
233 
234 #define IS_list(o) ((IS_INSTANCE(o) && AS_INSTANCE(o)->_class == vm.baseClasses->listClass) || krk_isInstanceOf(o,vm.baseClasses->listClass))
235 #define AS_list(o) (KrkList*)AS_OBJECT(o)
236 
237 #define IS_tuple(o) IS_TUPLE(o)
238 #define AS_tuple(o) AS_TUPLE(o)
239 
240 #define IS_bytes(o) IS_BYTES(o)
241 #define AS_bytes(o) AS_BYTES(o)
242 
243 #define IS_class(o) IS_CLASS(o)
244 #define AS_class(o) AS_CLASS(o)
245 
246 #define IS_str(o) (IS_STRING(o)||krk_isInstanceOf(o,vm.baseClasses->strClass))
247 #define AS_str(o) (KrkString*)AS_OBJECT(o)
248 
249 #define IS_striterator(o) (krk_isInstanceOf(o,vm.baseClasses->striteratorClass))
250 #define AS_striterator(o) (AS_INSTANCE(o))
251 
252 #define IS_dict(o) ((IS_INSTANCE(o) && AS_INSTANCE(o)->_class == vm.baseClasses->dictClass) || krk_isInstanceOf(o,vm.baseClasses->dictClass))
253 #define AS_dict(o) (KrkDict*)AS_OBJECT(o)
254 
255 #define IS_dictitems(o) krk_isInstanceOf(o,vm.baseClasses->dictitemsClass)
256 #define AS_dictitems(o) ((struct DictItems*)AS_OBJECT(o))
257 
258 #define IS_dictkeys(o) krk_isInstanceOf(o,vm.baseClasses->dictkeysClass)
259 #define AS_dictkeys(o) ((struct DictKeys*)AS_OBJECT(o))
260 
261 #define IS_dictvalues(o) krk_isInstanceOf(o,vm.baseClasses->dictvaluesClass)
262 #define AS_dictvalues(o) ((struct DictValues*)AS_OBJECT(o))
263 
264 #define IS_bytearray(o) (krk_isInstanceOf(o,vm.baseClasses->bytearrayClass))
265 #define AS_bytearray(o) ((struct ByteArray*)AS_INSTANCE(o))
266 
267 #define IS_slice(o) krk_isInstanceOf(o,vm.baseClasses->sliceClass)
268 #define AS_slice(o) ((struct KrkSlice*)AS_INSTANCE(o))
269 
270 extern KrkValue krk_dict_nth_key_fast(size_t capacity, KrkTableEntry * entries, size_t index);
271 extern KrkValue FUNC_NAME(str,__getitem__)(int,const KrkValue*,int);
272 extern KrkValue FUNC_NAME(str,split)(int,const KrkValue*,int);
273 extern KrkValue FUNC_NAME(str,format)(int,const KrkValue*,int);
274 #define krk_string_get FUNC_NAME(str,__getitem__)
275 #define krk_string_split FUNC_NAME(str,split)
276 #define krk_string_format FUNC_NAME(str,format)
277 
278 static inline void _setDoc_class(KrkClass * thing, const char * text, size_t size) {
279  krk_attachNamedObject(&thing->methods, "__doc__", (KrkObj*)krk_copyString(text, size));
280 }
281 static inline void _setDoc_instance(KrkInstance * thing, const char * text, size_t size) {
282  krk_attachNamedObject(&thing->fields, "__doc__", (KrkObj*)krk_copyString(text, size));
283 }
284 static inline void _setDoc_native(KrkNative * thing, const char * text, size_t size) {
285  (void)size;
286  thing->doc = text;
287 }
288 
301 #ifdef KRK_NO_DOCUMENTATION
302 # define KRK_DOC(thing, text) (thing);
303 #else
304 # define KRK_DOC(thing, text) \
305  _Generic(&((thing)[0]), \
306  KrkClass*: _setDoc_class, \
307  KrkInstance*: _setDoc_instance, \
308  KrkNative*: _setDoc_native \
309  )(thing,text,sizeof(text)-1)
310 #endif
311 
312 #define BUILTIN_FUNCTION(name, func, docStr) KRK_DOC(krk_defineNative(&vm.builtins->fields, name, func), docStr)
313 
314 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);
315 #define KRK_SLICER(arg,count) \
316  krk_integer_type start; \
317  krk_integer_type end; \
318  krk_integer_type step; \
319  if (krk_extractSlicer(_method_name, arg, count, &start, &end, &step))
320 
332 extern int krk_unpackIterable(KrkValue iterable, void * context, int callback(void *, const KrkValue *, size_t));
333 
334 
335 #define KRK_BASE_CLASS(cls) (vm.baseClasses->cls ## Class)
336 #define KRK_EXC(exc) (vm.exceptions->exc)
337 
338 
339 extern int krk_parseVArgs(
340  const char * _method_name,
341  int argc, const KrkValue argv[], int hasKw,
342  const char * fmt, const char ** names, va_list args);
343 
344 extern int krk_parseArgs_impl(
345  const char * _method_name,
346  int argc, const KrkValue argv[], int hasKw,
347  const char * format, const char ** names, ...);
348 
360 #define krk_parseArgs(f,n,...) krk_parseArgs_impl(_method_name,argc,argv,hasKw,f,n,__VA_ARGS__)
361 
362 
363 extern int krk_pushStringBuilderFormatV(struct StringBuilder * sb, const char * fmt, va_list args);
364 extern int krk_pushStringBuilderFormat(struct StringBuilder * sb, const char * fmt, ...);
365 extern KrkValue krk_stringFromFormat(const char * fmt, ...);
366 extern int krk_long_to_int(KrkValue val, char size, void * out);
367 extern int krk_isSubClass(const KrkClass * cls, const KrkClass * base);
368 
369 #define KRK_Module_internal_name(name) \
370  _krk_module_onload_ ## name
371 #define KRK_Module_internal_sig(name) \
372  static inline void KRK_Module_internal_name(name) (KrkInstance * module, KrkString * runAs)
373 #define KRK_Module(name) \
374  KRK_Module_internal_sig(name); \
375  KrkValue krk_module_onload_ ## name (KrkString * runAs) { \
376  KrkInstance * module = krk_newInstance(KRK_BASE_CLASS(module)); \
377  krk_push(OBJECT_VAL(module)); \
378  krk_attachNamedObject(&module->fields, "__name__", (KrkObj*)runAs); \
379  KRK_Module_internal_name(name)(module, runAs); \
380  return krk_pop(); \
381  } \
382  KRK_Module_internal_sig(name)
Functions for dealing with garbage collection and memory allocation.
Struct definitions for core object types.
Type object.
Definition: object.h:215
KrkTable methods
General attributes table.
Definition: object.h:218
An object of a class.
Definition: object.h:281
KrkTable fields
Attributes table.
Definition: object.h:284
Managed binding to a C function.
Definition: object.h:309
const char * doc
Docstring to supply from __doc__.
Definition: object.h:313
KrkObj obj
Base.
Definition: object.h:310
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:224
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:808
KrkNative * krk_defineNative(KrkTable *table, const char *name, NativeFn function)
Attach a native C function to an attribute table.
Definition: vm.c:155
Stack reference or primative value.
Inline flexible string array.
Definition: util.h:162
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:1091
KrkValue krk_finishStringBuilderBytes(struct StringBuilder *sb)
Finalize a string builder in a bytes object.
Definition: obj_str.c:1117
int krk_long_to_int(KrkValue val, char size, void *out)
Convert an int or long to a C integer.
Definition: obj_long.c:3084
KrkValue krk_discardStringBuilder(struct StringBuilder *sb)
Discard the contents of a string builder.
Definition: obj_str.c:1123
int krk_unpackIterable(KrkValue iterable, void *context, int callback(void *, const KrkValue *, size_t))
Unpack an iterable.
Definition: builtins.c:387
KrkValue krk_finishStringBuilder(struct StringBuilder *sb)
Finalize a string builder into a string object.
Definition: obj_str.c:1111
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:456
void krk_pushStringBuilder(struct StringBuilder *sb, char c)
Add a character to the end of a string builder.
Definition: obj_str.c:1082
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:85
Core API for the bytecode virtual machine.