util.h File Reference

Utilities for creating native bindings. More...

#include "object.h"
#include "vm.h"
#include "memory.h"
Include dependency graph for util.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  StringBuilder
 Inline flexible string array. More...
 

Macros

#define S(c)   (krk_copyString(c,sizeof(c)-1))
 
#define likely(cond)   __builtin_expect((cond), 1)
 
#define unlikely(cond)   __builtin_expect((cond), 0)
 
#define __has_attribute(attr)   0
 
#define _protected
 
#define _noexport   __attribute__((visibility("hidden")))
 
#define _unused
 
#define _hot
 
#define _cold
 
#define _nonnull
 
#define ADD_BASE_CLASS(obj, name, baseClass)   krk_makeClass(vm.builtins, &obj, name, baseClass)
 
#define ATTRIBUTE_NOT_ASSIGNABLE()
 
#define METHOD_TAKES_NONE()
 
#define METHOD_TAKES_EXACTLY(n)
 
#define METHOD_TAKES_AT_LEAST(n)
 
#define METHOD_TAKES_AT_MOST(n)
 
#define FUNCTION_TAKES_NONE()
 
#define FUNCTION_TAKES_EXACTLY(n)
 
#define FUNCTION_TAKES_AT_LEAST(n)
 
#define FUNCTION_TAKES_AT_MOST(n)
 
#define TYPE_ERROR(expected, value)
 
#define NOT_ENOUGH_ARGS(name)   krk_runtimeError(vm.exceptions->argumentError, "Expected more args.")
 
#define CHECK_ARG(i, type, ctype, name)
 
#define FUNC_NAME(klass, name)   _ ## klass ## _ ## name
 
#define FUNC_SIG(klass, name)   _noexport KrkValue FUNC_NAME(klass,name) (int argc, const KrkValue argv[], int hasKw)
 
#define MAKE_CLASS(klass)   do { krk_makeClass(module,&klass,#klass,vm.baseClasses->objectClass); klass ->allocSize = sizeof(struct klass); } while (0)
 
#define BIND_METHOD(klass, method)   krk_defineNative(&klass->methods, #method, _ ## klass ## _ ## method)
 
#define BIND_PROP(klass, method)   krk_defineNativeProperty(&klass->methods, #method, _ ## klass ## _ ## method)
 
#define BIND_FUNC(module, func)   krk_defineNative(&module->fields, #func, _krk_ ## func)
 
#define BIND_STATICMETHOD(klass, method)   krk_defineNativeStaticMethod(&klass->methods, #method, _ ## klass ## _ ## method)
 
#define BIND_CLASSMETHOD(klass, method)   krk_defineNativeClassMethod(&klass->methods, #method, _ ## klass ## _ ## method)
 
#define KRK_Method_internal_name(klass, name)    _krk_method_ ## klass ## _ ## name
 
#define KRK_Method_internal_sig(klass, name)    static inline KrkValue KRK_Method_internal_name(klass,name) (const char * _method_name, CURRENT_CTYPE CURRENT_NAME, int argc, const KrkValue argv[], int hasKw)
 
#define KRK_Method(klass, name)
 
#define KRK_Function_internal_name(name)    _krk_function_ ## name
 
#define KRK_Function_internal_sig(name)    static inline KrkValue KRK_Function_internal_name(name) (const char * _method_name, int argc, const KrkValue argv[], int hasKw)
 
#define KRK_Function(name)
 
#define KRK_StaticMethod_internal_sig(klass, name)    static inline KrkValue KRK_Method_internal_name(klass, name) (const char * _method_name, int argc, const KrkValue argv[], int hasKw)
 
#define KRK_StaticMethod(klass, name)
 
#define pushStringBuilder   krk_pushStringBuilder
 
#define pushStringBuilderStr   krk_pushStringBuilderStr
 
#define finishStringBuilder   krk_finishStringBuilder
 
#define finishStringBuilderBytes   krk_finishStringBuilderBytes
 
#define discardStringBuilder   krk_discardStringBuilder
 
#define IS_int(o)   (IS_INTEGER(o))
 
#define AS_int(o)   (AS_INTEGER(o))
 
#define IS_bool(o)   (IS_BOOLEAN(o))
 
#define AS_bool(o)   (AS_BOOLEAN(o))
 
#define IS_float(o)   (IS_FLOATING(o))
 
#define AS_float(o)   (AS_FLOATING(o))
 
#define IS_list(o)   ((IS_INSTANCE(o) && AS_INSTANCE(o)->_class == vm.baseClasses->listClass) || krk_isInstanceOf(o,vm.baseClasses->listClass))
 
#define AS_list(o)   (KrkList*)AS_OBJECT(o)
 
#define IS_tuple(o)   IS_TUPLE(o)
 
#define AS_tuple(o)   AS_TUPLE(o)
 
#define IS_bytes(o)   IS_BYTES(o)
 
#define AS_bytes(o)   AS_BYTES(o)
 
#define IS_class(o)   IS_CLASS(o)
 
#define AS_class(o)   AS_CLASS(o)
 
#define IS_str(o)   (IS_STRING(o)||krk_isInstanceOf(o,vm.baseClasses->strClass))
 
#define AS_str(o)   (KrkString*)AS_OBJECT(o)
 
#define IS_striterator(o)   (krk_isInstanceOf(o,vm.baseClasses->striteratorClass))
 
#define AS_striterator(o)   (AS_INSTANCE(o))
 
#define IS_dict(o)   ((IS_INSTANCE(o) && AS_INSTANCE(o)->_class == vm.baseClasses->dictClass) || krk_isInstanceOf(o,vm.baseClasses->dictClass))
 
#define AS_dict(o)   (KrkDict*)AS_OBJECT(o)
 
#define IS_dictitems(o)   krk_isInstanceOf(o,vm.baseClasses->dictitemsClass)
 
#define AS_dictitems(o)   ((struct DictItems*)AS_OBJECT(o))
 
#define IS_dictkeys(o)   krk_isInstanceOf(o,vm.baseClasses->dictkeysClass)
 
#define AS_dictkeys(o)   ((struct DictKeys*)AS_OBJECT(o))
 
#define IS_dictvalues(o)   krk_isInstanceOf(o,vm.baseClasses->dictvaluesClass)
 
#define AS_dictvalues(o)   ((struct DictValues*)AS_OBJECT(o))
 
#define IS_bytearray(o)   (krk_isInstanceOf(o,vm.baseClasses->bytearrayClass))
 
#define AS_bytearray(o)   ((struct ByteArray*)AS_INSTANCE(o))
 
#define IS_slice(o)   krk_isInstanceOf(o,vm.baseClasses->sliceClass)
 
#define AS_slice(o)   ((struct KrkSlice*)AS_INSTANCE(o))
 
#define krk_string_get   FUNC_NAME(str,__getitem__)
 
#define krk_string_split   FUNC_NAME(str,split)
 
#define krk_string_format   FUNC_NAME(str,format)
 
#define KRK_DOC(thing, text)
 Attach documentation to a thing of various types. More...
 
#define BUILTIN_FUNCTION(name, func, docStr)   KRK_DOC(krk_defineNative(&vm.builtins->fields, name, func), docStr)
 
#define KRK_SLICER(arg, count)
 
#define KRK_BASE_CLASS(cls)   (vm.baseClasses->cls ## Class)
 
#define KRK_EXC(exc)   (vm.exceptions->exc)
 
#define krk_parseArgs(f, n, ...)   krk_parseArgs_impl(_method_name,argc,argv,hasKw,f,n,__VA_ARGS__)
 Parse arguments to a function while accepting keyword arguments. More...
 
#define KRK_Module_internal_name(name)    _krk_module_onload_ ## name
 
#define KRK_Module_internal_sig(name)    static inline void KRK_Module_internal_name(name) (KrkInstance * module, KrkString * runAs)
 
#define KRK_Module(name)
 

Functions

void krk_pushStringBuilder (struct StringBuilder *sb, char c)
 Add a character to the end of a string builder. More...
 
void krk_pushStringBuilderStr (struct StringBuilder *sb, const char *str, size_t len)
 Append a string to the end of a string builder. More...
 
KrkValue krk_finishStringBuilder (struct StringBuilder *sb)
 Finalize a string builder into a string object. More...
 
KrkValue krk_finishStringBuilderBytes (struct StringBuilder *sb)
 Finalize a string builder in a bytes object. More...
 
KrkValue krk_discardStringBuilder (struct StringBuilder *sb)
 Discard the contents of a string builder. More...
 
KrkValue krk_dict_nth_key_fast (size_t capacity, KrkTableEntry *entries, size_t index)
 
KrkValue FUNC_NAME (str, __getitem__)(int
 
KrkValue FUNC_NAME (str, split)(int
 
KrkValue FUNC_NAME (str, format)(int
 
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)
 
int krk_unpackIterable (KrkValue iterable, void *context, int callback(void *, const KrkValue *, size_t))
 Unpack an iterable. More...
 
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. More...
 
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.
 
int krk_pushStringBuilderFormatV (struct StringBuilder *sb, const char *fmt, va_list args)
 
int krk_pushStringBuilderFormat (struct StringBuilder *sb, const char *fmt,...)
 
KrkValue krk_stringFromFormat (const char *fmt,...)
 
int krk_long_to_int (KrkValue val, char size, void *out)
 Convert an int or long to a C integer. More...
 
int krk_isSubClass (const KrkClass *cls, const KrkClass *base)
 

Variables

KrkValue const KrkValue int
 

Detailed Description

Utilities for creating native bindings.

This is intended for use in C extensions to provide a uniform interface for defining extension methods and ensuring they have consistent argument and keyword argument usage.

Definition in file util.h.

Macro Definition Documentation

◆ ATTRIBUTE_NOT_ASSIGNABLE

#define ATTRIBUTE_NOT_ASSIGNABLE ( )
Value:
do { if (unlikely(argc != 1)) return krk_runtimeError(vm.exceptions->attributeError, "'%T' object has no attribute '%s'", \
argv[0], _method_name); } while (0)
KrkValue krk_runtimeError(KrkClass *type, const char *fmt,...)
Produce and raise an exception with a formatted message.
Definition: exceptions.c:460
#define vm
Convenience macro for namespacing.
Definition: vm.h:257

Definition at line 62 of file util.h.

◆ CHECK_ARG

#define CHECK_ARG (   i,
  type,
  ctype,
  name 
)
Value:
if (unlikely(argc < (i+1))) return NOT_ENOUGH_ARGS(name); \
if (unlikely(!IS_ ## type (argv[i]))) return TYPE_ERROR(type,argv[i]); \
ctype name _unused = AS_ ## type (argv[i])

Definition at line 94 of file util.h.

◆ FUNCTION_TAKES_AT_LEAST

#define FUNCTION_TAKES_AT_LEAST (   n)
Value:
do { if (unlikely(argc < n)) return krk_runtimeError(vm.exceptions->argumentError, "%s() takes %s %d argument%s (%d given)", \
_method_name, "at least", n, (n != 1) ? "s" : "", (argc)); } while (0)

Definition at line 83 of file util.h.

◆ FUNCTION_TAKES_AT_MOST

#define FUNCTION_TAKES_AT_MOST (   n)
Value:
do { if (unlikely(argc > n)) return krk_runtimeError(vm.exceptions->argumentError, "%s() takes %s %d argument%s (%d given)", \
_method_name, "at most", n, (n != 1) ? "s" : "", (argc)); } while (0)

Definition at line 86 of file util.h.

◆ FUNCTION_TAKES_EXACTLY

#define FUNCTION_TAKES_EXACTLY (   n)
Value:
do { if (unlikely(argc != n)) return krk_runtimeError(vm.exceptions->argumentError, "%s() takes %s %d argument%s (%d given)", \
_method_name, "exactly", n, (n != 1) ? "s" : "", (argc)); } while (0)

Definition at line 80 of file util.h.

◆ FUNCTION_TAKES_NONE

#define FUNCTION_TAKES_NONE ( )
Value:
do { if (unlikely(argc != 0)) return krk_runtimeError(vm.exceptions->argumentError, "%s() takes no arguments (%d given)", \
_method_name, (argc)); } while (0)

Definition at line 77 of file util.h.

◆ KRK_DOC

#define KRK_DOC (   thing,
  text 
)
Value:
_Generic(&((thing)[0]), \
KrkClass*: _setDoc_class, \
KrkInstance*: _setDoc_instance, \
KrkNative*: _setDoc_native \
)(thing,text,sizeof(text)-1)
Type object.
Definition: object.h:215
An object of a class.
Definition: object.h:281
Managed binding to a C function.
Definition: object.h:309

Attach documentation to a thing of various types.

Classes store their docstrings directly, rather than in their attribute tables. Instances use the attribute table and store strings with the name __doc__. Native functions store direct C string pointers for documentation.

This macro provides a generic interface for applying documentation strings to any of the above types, and handles not attaching documentation when built with KRK_NO_DOCUMENTATION.

Definition at line 304 of file util.h.

◆ KRK_Function

#define KRK_Function (   name)
Value:
KRK_Function_internal_sig(name); \
static KrkValue _krk_ ## name (int argc, const KrkValue argv[], int hasKw) { \
static const char* _method_name = # name; \
return KRK_Function_internal_name(name)(_method_name,argc,argv,hasKw); \
} \
KRK_Function_internal_sig(name)
Stack reference or primative value.

Definition at line 141 of file util.h.

◆ KRK_Method

#define KRK_Method (   klass,
  name 
)
Value:
KRK_Method_internal_sig(klass, name); \
FUNC_SIG(klass, name) { \
static const char * _method_name = # name; \
CHECK_ARG(0,klass,CURRENT_CTYPE,CURRENT_NAME); \
return KRK_Method_internal_name(klass,name)(_method_name, CURRENT_NAME, argc, argv, hasKw); \
} \
KRK_Method_internal_sig(klass,name)

Definition at line 127 of file util.h.

◆ KRK_Module

#define KRK_Module (   name)
Value:
KRK_Module_internal_sig(name); \
KrkValue krk_module_onload_ ## name (KrkString * runAs) { \
KrkInstance * module = krk_newInstance(KRK_BASE_CLASS(module)); \
krk_push(OBJECT_VAL(module)); \
krk_attachNamedObject(&module->fields, "__name__", (KrkObj*)runAs); \
KRK_Module_internal_name(name)(module, runAs); \
return krk_pop(); \
} \
KRK_Module_internal_sig(name)
KrkInstance * krk_newInstance(KrkClass *_class)
Create a new instance of the given class.
Definition: object.c:343
The most basic object type.
Definition: object.h:41
Immutable sequence of Unicode codepoints.
Definition: object.h:93
KrkValue krk_pop(void)
Pop the top of the stack.
Definition: vm.c:131

Definition at line 373 of file util.h.

◆ krk_parseArgs

#define krk_parseArgs (   f,
  n,
  ... 
)    krk_parseArgs_impl(_method_name,argc,argv,hasKw,f,n,__VA_ARGS__)

Parse arguments to a function while accepting keyword arguments.

Convenience macro for krk_parseArgs_impl to avoid needing to pass all of the implicit arguments normally provided to a KRK_Function or KRK_Method.

Parameters
fFormat string.
nNames array.
Returns
1 on success, 0 on failure with an exception set.

Definition at line 360 of file util.h.

◆ KRK_SLICER

#define KRK_SLICER (   arg,
  count 
)
Value:
krk_integer_type start; \
krk_integer_type end; \
krk_integer_type step; \
if (krk_extractSlicer(_method_name, arg, count, &start, &end, &step))

Definition at line 315 of file util.h.

◆ KRK_StaticMethod

#define KRK_StaticMethod (   klass,
  name 
)
Value:
KRK_StaticMethod_internal_sig(klass, name); \
FUNC_SIG(klass, name) { \
static const char * _method_name = # name; \
return KRK_Method_internal_name(klass,name)(_method_name,argc,argv,hasKw); \
} \
KRK_StaticMethod_internal_sig(klass,name)

Definition at line 151 of file util.h.

◆ METHOD_TAKES_AT_LEAST

#define METHOD_TAKES_AT_LEAST (   n)
Value:
do { if (unlikely(argc < (n+1))) return krk_runtimeError(vm.exceptions->argumentError, "%s() takes %s %d argument%s (%d given)", \
_method_name, "at least", n, (n != 1) ? "s" : "", (argc-1)); } while (0)

Definition at line 71 of file util.h.

◆ METHOD_TAKES_AT_MOST

#define METHOD_TAKES_AT_MOST (   n)
Value:
do { if (unlikely(argc > (n+1))) return krk_runtimeError(vm.exceptions->argumentError, "%s() takes %s %d argument%s (%d given)", \
_method_name, "at most", n, (n != 1) ? "s" : "", (argc-1)); } while (0)

Definition at line 74 of file util.h.

◆ METHOD_TAKES_EXACTLY

#define METHOD_TAKES_EXACTLY (   n)
Value:
do { if (unlikely(argc != (n+1))) return krk_runtimeError(vm.exceptions->argumentError, "%s() takes %s %d argument%s (%d given)", \
_method_name, "exactly", n, (n != 1) ? "s" : "", (argc-1)); } while (0)

Definition at line 68 of file util.h.

◆ METHOD_TAKES_NONE

#define METHOD_TAKES_NONE ( )
Value:
do { if (unlikely(argc != 1)) return krk_runtimeError(vm.exceptions->argumentError, "%s() takes no arguments (%d given)", \
_method_name, (argc-1)); } while (0)

Definition at line 65 of file util.h.

◆ TYPE_ERROR

#define TYPE_ERROR (   expected,
  value 
)
Value:
krk_runtimeError(vm.exceptions->typeError, "%s() expects %s, not '%T'", \
/* Function name */ _method_name, /* expected type */ #expected, value)

Definition at line 89 of file util.h.

Function Documentation

◆ krk_discardStringBuilder()

KrkValue krk_discardStringBuilder ( struct StringBuilder sb)

Discard the contents of a string builder.

Frees the resources allocated for the string builder without converting it to a string or bytes object. Call this when an error has been encountered and the contents of a string builder are no longer needed.

Parameters
sbString builder to discard.
Returns
None, as a convenience.

Definition at line 1123 of file obj_str.c.

◆ krk_finishStringBuilder()

KrkValue krk_finishStringBuilder ( struct StringBuilder sb)

Finalize a string builder into a string object.

Creates a string object from the contents of the string builder and frees the space allocated for the builder, returning a value representing the newly created string object.

Parameters
sbString builder to finalize.
Returns
A value representing a string object.

Definition at line 1111 of file obj_str.c.

◆ krk_finishStringBuilderBytes()

KrkValue krk_finishStringBuilderBytes ( struct StringBuilder sb)

Finalize a string builder in a bytes object.

Converts the contents of a string builder into a bytes object and frees the space allocated for the builder.

Parameters
sbString builder to finalize.
Returns
A value representing a bytes object.

Definition at line 1117 of file obj_str.c.

◆ krk_long_to_int()

int krk_long_to_int ( KrkValue  val,
char  size,
void *  out 
)

Convert an int or long to a C integer.

No overflow checking is performed in any case.

Parameters
valint or long to convert.
sizeSize in bytes of desired C integer type.
outPointer to resulting int.

Definition at line 3084 of file obj_long.c.

◆ krk_parseVArgs()

int krk_parseVArgs ( const char *  orig_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.

This works like a fancy scanf. We accept the original argument specification (argc,argv,hasKw), a format string, an array of argument names, and then var args that are generally pointers to where to stick results.

Parameters
argcOriginal positional argument count.
argvOriginal argument list, argv[argc] should be a dict if hasKw is set.
hasKwWhether argv[argc] has a dict of keyword arguments.
fmtString describing formats of expected arguments.
namesArray of strings of parameter names.
argsvar args
Returns
1 on success, 0 on error.

< Index into positional input arguments

< Index into names array

< Parser state, whether required arguments are being collected

< Whether extra keyword args should produce an error (0) or not (1)

If the format string starts with . then argument processing skips the first argument on the assumption that this is a method and the first argument has already been handled by the method wrapper macros or directly by the function. This makes error messages a bit nicer, as argument counts will exclude the implicit self.

| begins optional arguments - eg. default args. Every format option after this point should be preset to usable default value, as it will not be touched if the argument is not found.

* works like args would in a Kuroko function signature, collecting all remaining positional arguments into a list. It does this be returning the count of remaining arguments (int) and the pointer to their start in the original argument list (KrkValue).

This also implicitly signals the end of required arguments and all later arguments are automatically optional, without needing to use |.

$ indicates the end of positional arguments. Everything after this point is only accepted as a keyword argument. $ must appear after one of | or *.

If any positional arguments remain when $ is encountred, a too-many arguments exception will be raised.

If ~ is encountered anywhere in the format string, then extraneous keyword arguments are left as-is and no exception is raised when they are found. As keyword arguments are deleted from the kwargs dict while processing other arguments, this means if hasKw is set then argv[argc] will be left with only the unhandled keyword arguments, same as for a **kwargs argument in a Kuroko function signature.

O Collect an object (with ! - of a given type) and place it in in the KrkObj** var arg. The object must be a heap object, so this can not be used to collect boxed value types like int or float - use V for those instead. As an exception to the heap object requirements, None is accepted and will result in NULL (but if a type is requested, the type check will fail before None can be evaluated).

V Accept any value (with ! - of a given type) and place a value reference in the KrkValue* var arg. This works with boxed value types as well, so it is safe for use with int and float and so on. The type check is equivalent to instanceof. As a special case - as with O - the type may be NULL in which case type checking is guaranteed to fail but parsing will not. The resulting error message is less informative in this case.

z Collect one string or None and place a pointer to it in a const char **. If # is specified, the size of the string is also placed in a following size_t* var arg. If the argument is None the result is NULL and the size is set to 0.

s Same as z but does not accept None.

Integer conversions.

TODO Currently no overflow checking is done for any case, but we should do it for at least the signed values to align with the CPython API this is all based on... The distinct signed vs. unsigned variants are intended both for future compatibility and to make intent clear, but have no functional difference at this point.

C Accept a string of length one and convert it to a C int in a similar manner to ord.

f Accept a Kuroko float as C float.

d Accept a Kuroko float as C double.

p Accept any value and examine its truthiness, returning an int. Python's docs call this "predicate", if you were wondering where the p came from. If bool conversion raises an exception, arg parsing ends with failure and that exception remains set.

If we got through the format string and there are still positional arguments, we got more than we expected and should raise an exception.

If we don't accept extra keyword arguments and there's still anything left in the dict, raise an exception about unexpected keyword arguments. The remaining key (or keys) should be a string, so we should find at least one thing to complain about by name...

Definition at line 85 of file parseargs.c.

◆ krk_pushStringBuilder()

void krk_pushStringBuilder ( struct StringBuilder sb,
char  c 
)

Add a character to the end of a string builder.

Parameters
sbString builder to append to.
cCharacter to append.

Definition at line 1082 of file obj_str.c.

◆ krk_pushStringBuilderStr()

void krk_pushStringBuilderStr ( struct StringBuilder sb,
const char *  str,
size_t  len 
)

Append a string to the end of a string builder.

Parameters
sbString builder to append to.
strC string to add.
lenLength of the C string.

Definition at line 1091 of file obj_str.c.

◆ krk_unpackIterable()

int krk_unpackIterable ( KrkValue  iterable,
void *  context,
int   callbackvoid *, const KrkValue *, size_t 
)

Unpack an iterable.

Unpacks an iterable value, passing a series of arrays of values to a callback, callback.

If iterable is a list or tuple, callback will be called once with the total size of the container. Otherwise, callback will be called many times with a count of 1, until the iterable is exhausted.

If iterable is not iterable, an exception is set and 1 is returned. If callback returns non-zero, unpacking stops and 1 is returned, with no additional exception.

Definition at line 387 of file builtins.c.