12 static int matchType(
const char * _method_name,
KrkClass * type,
KrkValue arg) {
15 _method_name, type ? type->
name->
chars :
"unknown type", arg);
40 const char * _method_name,
41 int argc,
const KrkValue argv[],
int hasKw,
42 const char * fmt,
const char ** names, va_list args) {
46 int acceptextrakws = 0;
48 const char * maybeColon = strchr(fmt,
':');
50 _method_name = maybeColon + 1;
67 if (*fmt ==
':')
break;
92 int * out_c = va_arg(args,
int *);
110 krk_runtimeError(
vm.exceptions->typeError,
"$ must be after | or * in format string");
113 if (iarg < argc)
break;
130 int wasPositional = 0;
139 }
else if ((required && !hasKw) || (hasKw && !
krk_tableGet_fast(AS_DICT(argv[argc]), AS_STRING(
krk_peek(0)), &arg) && required)) {
141 krk_runtimeError(
vm.exceptions->typeError,
"%s() missing required positional argument: '%S'",
142 _method_name, AS_STRING(
krk_peek(0)));
149 krk_runtimeError(
vm.exceptions->typeError,
"%s() got multiple values for argument '%S'",
150 _method_name, AS_STRING(
krk_peek(0)));
154 char argtype = *fmt++;
160 int * out = va_arg(args,
int*);
161 *out = arg != KWARGS_VAL(0);
171 if (!matchType(_method_name, type, arg))
goto _error;
186 if (arg != KWARGS_VAL(0)) {
189 }
else if (!IS_OBJECT(arg)) {
190 TYPE_ERROR(heap
object,arg);
193 *out = AS_OBJECT(arg);
210 if (arg != KWARGS_VAL(0)) {
224 char ** out = va_arg(args,
char **);
225 size_t * size = NULL;
228 size = va_arg(args,
size_t*);
230 if (arg != KWARGS_VAL(0)) {
231 if (arg == NONE_VAL()) {
234 }
else if (IS_STRING(arg)) {
235 *out = AS_CSTRING(arg);
236 if (size) *size = AS_STRING(arg)->length;
238 TYPE_ERROR(str or None,arg);
249 char ** out = va_arg(args,
char **);
250 size_t * size = NULL;
253 size = va_arg(args,
size_t*);
255 if (arg != KWARGS_VAL(0)) {
256 if (IS_STRING(arg)) {
257 *out = AS_CSTRING(arg);
258 if (size) *size = AS_STRING(arg)->length;
276 #define NUMERIC(c,type) case c: { type * out = va_arg(args, type*); if (arg != KWARGS_VAL(0)) { if (!krk_long_to_int(arg, sizeof(type), out)) goto _error; } break; }
277 NUMERIC(
'b',
unsigned char)
279 NUMERIC(
'H',
unsigned short)
281 NUMERIC(
'I',
unsigned int)
283 NUMERIC(
'k',
unsigned long)
284 NUMERIC(
'L',
long long)
285 NUMERIC(
'K',
unsigned long long)
294 int * out = va_arg(args,
int*);
295 if (arg != KWARGS_VAL(0)) {
296 if (!IS_STRING(arg) || AS_STRING(arg)->codesLength != 1) {
297 TYPE_ERROR(str of length 1,arg);
310 float * out = va_arg(args,
float*);
311 if (arg != KWARGS_VAL(0)) {
312 if (!IS_FLOATING(arg)) {
317 TYPE_ERROR(
float,arg);
322 *out = AS_FLOATING(arg);
331 double * out = va_arg(args,
double*);
332 if (arg != KWARGS_VAL(0)) {
333 if (!IS_FLOATING(arg)) {
338 TYPE_ERROR(
float,arg);
343 *out = AS_FLOATING(arg);
361 int * out = va_arg(args,
int*);
362 if (arg != KWARGS_VAL(0)) {
370 krk_runtimeError(
vm.exceptions->typeError,
"unrecognized directive '%c' in format string", argtype);
384 krk_runtimeError(
vm.exceptions->argumentError,
"%s() takes %s %d argument%s (%d given)",
385 _method_name, required ?
"exactly" :
"at most", oarg, oarg == 1 ?
"" :
"s", argc);
389 if (!acceptextrakws && hasKw && AS_DICT(argv[argc])->count) {
396 for (
size_t i = 0; i < AS_DICT(argv[argc])->capacity; ++i) {
398 if (IS_STRING(entry->key)) {
399 krk_runtimeError(
vm.exceptions->typeError,
"%s() got an unexpected keyword argument '%S'",
400 _method_name, AS_STRING(entry->key));
417 const char * _method_name,
418 int argc,
const KrkValue argv[],
int hasKw,
419 const char * format,
const char ** names, ...) {
421 va_start(args, names);
422 int result =
krk_parseVArgs(_method_name,argc,argv,hasKw,format,names,args);
KrkValue krk_runtimeError(KrkClass *type, const char *fmt,...)
Produce and raise an exception with a formatted message.
KrkString * name
Name of the class.
int krk_bindMethod(KrkClass *_class, KrkString *name)
Perform method binding on the stack.
The most basic object type.
uint32_t krk_unicodeCodepoint(KrkString *string, size_t index)
Obtain the codepoint at a given index in a string.
KrkString * krk_copyString(const char *chars, size_t length)
Obtain a string object representation of the given C string.
char * chars
UTF8 canonical data.
One (key,value) pair in a table.
int krk_tableDelete(KrkTable *table, KrkValue key)
Remove a key from a hash table.
int krk_tableGet_fast(KrkTable *table, struct KrkString *str, KrkValue *value)
Obtain the value associated with a string key in a table.
Stack reference or primative value.
int krk_isInstanceOf(KrkValue obj, const KrkClass *type)
Determine if a class is an instance or subclass of a given type.
KrkClass * krk_getType(KrkValue value)
Get the class representing a value.
int krk_isFalsey(KrkValue value)
Determine the truth of a value.
Utilities for creating native bindings.
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_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.
Core API for the bytecode virtual machine.
KrkValue krk_callStack(int argCount)
Call a callable on the stack with argCount arguments.
#define vm
Convenience macro for namespacing.
KrkValue krk_pop(void)
Pop the top of the stack.
threadLocal KrkThreadState krk_currentThread
Thread-local VM state.
void krk_push(KrkValue value)
Push a stack value.
KrkValue krk_peek(int distance)
Peek down from the top of the stack.