builtins.c
1 #include <string.h>
2 #include <kuroko/vm.h>
3 #include <kuroko/value.h>
4 #include <kuroko/memory.h>
5 #include <kuroko/util.h>
6 #include <kuroko/debug.h>
7 
8 #include "private.h"
9 
10 FUNC_SIG(list,__init__);
11 FUNC_SIG(list,sort);
12 
13 KrkValue krk_dirObject(int argc, const KrkValue argv[], int hasKw) {
14  if (argc != 1)
15  return krk_runtimeError(vm.exceptions->argumentError, "%s() takes %s %d argument%s (%d given)",
16  "dir", "exactly", 1, "", argc);
17 
18  /* Create a new list instance */
19  KrkValue myList = krk_list_of(0,NULL,0);
20  krk_push(myList);
21 
22  if (IS_INSTANCE(argv[0])) {
23  /* Obtain self-reference */
24  KrkInstance * self = AS_INSTANCE(argv[0]);
25  for (size_t i = 0; i < self->fields.capacity; ++i) {
26  if (!IS_KWARGS(self->fields.entries[i].key)) {
27  krk_writeValueArray(AS_LIST(myList),
28  self->fields.entries[i].key);
29  }
30  }
31  } else if (IS_CLOSURE(argv[0])) {
32  /* Why not just make closures instances... */
33  KrkClosure * self = AS_CLOSURE(argv[0]);
34  for (size_t i = 0; i < self->fields.capacity; ++i) {
35  if (!IS_KWARGS(self->fields.entries[i].key)) {
36  krk_writeValueArray(AS_LIST(myList),
37  self->fields.entries[i].key);
38  }
39  }
40  } else if (IS_CLASS(argv[0])) {
41  KrkClass * _class = AS_CLASS(argv[0]);
42  while (_class) {
43  for (size_t i = 0; i < _class->methods.capacity; ++i) {
44  if (!IS_KWARGS(_class->methods.entries[i].key)) {
45  krk_writeValueArray(AS_LIST(myList),
46  _class->methods.entries[i].key);
47  }
48  }
49  _class = _class->base;
50  }
51  }
52 
53  KrkClass * type = krk_getType(argv[0]);
54 
55  while (type) {
56  for (size_t i = 0; i < type->methods.capacity; ++i) {
57  if (!IS_KWARGS(type->methods.entries[i].key)) {
58  krk_writeValueArray(AS_LIST(myList),
59  type->methods.entries[i].key);
60  }
61  }
62  type = type->base;
63  }
64 
65  /* Throw it at a set to get unique, unordered results */
66  krk_push(krk_set_of(AS_LIST(myList)->count, AS_LIST(myList)->values, 0));
67  krk_swap(1);
68  krk_pop();
69 
70  /* Now build a fresh list */
71  myList = krk_list_of(0,NULL,0);
72  krk_push(myList);
73  krk_swap(1);
74  FUNC_NAME(list,__init__)(2,(KrkValue[]){krk_peek(1), krk_peek(0)},0);
75  FUNC_NAME(list,sort)(1,(KrkValue[]){krk_peek(1)},0);
76  krk_pop();
77 
78  return krk_pop();
79 }
80 
81 #define IS_object(o) (1)
82 #define AS_object(o) (o)
83 #define CURRENT_CTYPE KrkValue
84 #define CURRENT_NAME self
85 
86 KRK_Method(object,__dir__) {
87  return krk_dirObject(argc,argv,hasKw);
88 }
89 
90 KRK_Method(object,__class__) {
91  KrkClass * current = krk_getType(self);
92  if (argc > 1) {
93  if (!IS_CLASS(argv[1])) return krk_runtimeError(vm.exceptions->typeError, "'%T' object is not a class", argv[1]);
94  if (!IS_INSTANCE(argv[0]) || current->allocSize != sizeof(KrkInstance)) return krk_runtimeError(vm.exceptions->typeError, "'%T' object does not have modifiable type", argv[0]); /* TODO class? */
95  if (AS_CLASS(argv[1])->allocSize != sizeof(KrkInstance)) return krk_runtimeError(vm.exceptions->typeError, "'%S' type is not assignable", AS_CLASS(argv[1])->name);
96  AS_INSTANCE(argv[0])->_class = AS_CLASS(argv[1]);
97  current = AS_CLASS(argv[1]);
98  }
99  return OBJECT_VAL(current);
100 }
101 
102 KRK_Method(object,__hash__) {
103  if (!IS_OBJECT(self)) {
104  uint32_t hashed;
105  if (krk_hashValue(self, &hashed)) return NONE_VAL();
106  return INTEGER_VAL(hashed);
107  }
108  KrkObj * obj = AS_OBJECT(self);
109  if (!(obj->flags & KRK_OBJ_FLAGS_VALID_HASH)) {
110  obj->hash = (uint32_t)((intptr_t)(obj) >> 3);
111  obj->flags |= KRK_OBJ_FLAGS_VALID_HASH;
112  }
113  return INTEGER_VAL(obj->hash);
114 }
115 
116 KRK_Method(object,__eq__) {
117  METHOD_TAKES_EXACTLY(1);
118  if (krk_valuesSame(argv[0],argv[1])) return BOOLEAN_VAL(1);
119  return NOTIMPL_VAL();
120 }
121 
122 KRK_Function(getattr) {
123  FUNCTION_TAKES_AT_LEAST(2);
124  CHECK_ARG(1,str,KrkString*,property);
125 
126  krk_push(argv[0]);
127  if (!krk_getAttribute(AS_STRING(argv[1]))) {
128  krk_pop();
129  if (argc == 3) return argv[2];
130  return krk_runtimeError(vm.exceptions->attributeError, "'%T' object has no attribute '%S'", argv[0], AS_STRING(argv[1]));
131  }
132  return krk_pop();
133 }
134 
135 KRK_Function(setattr) {
136  FUNCTION_TAKES_EXACTLY(3);
137  CHECK_ARG(1,str,KrkString*,property);
138 
139  krk_push(argv[0]);
140  krk_push(argv[2]);
141  if (!krk_setAttribute(AS_STRING(argv[1]))) {
142  return krk_runtimeError(vm.exceptions->attributeError, "'%T' object has no attribute '%S'", argv[0], AS_STRING(argv[1]));
143  }
144  return krk_pop();
145 }
146 
147 KRK_Function(hasattr) {
148  FUNCTION_TAKES_AT_LEAST(2);
149  CHECK_ARG(1,str,KrkString*,property);
150 
151  krk_push(argv[0]);
152  if (!krk_getAttribute(AS_STRING(argv[1]))) {
153  krk_pop();
154  return BOOLEAN_VAL(0);
155  }
156  krk_pop();
157  return BOOLEAN_VAL(1);
158 }
159 
160 KRK_Function(delattr) {
161  FUNCTION_TAKES_AT_LEAST(2);
162  CHECK_ARG(1,str,KrkString*,property);
163 
164  krk_push(argv[0]);
165  if (!krk_delAttribute(AS_STRING(argv[1]))) {
166  return krk_runtimeError(vm.exceptions->attributeError, "'%T' object has no attribute '%S'", argv[0], AS_STRING(argv[1]));
167  }
168  return NONE_VAL();
169 }
170 
175 KRK_Method(object,__setattr__) {
176  METHOD_TAKES_EXACTLY(2);
177  if (!IS_STRING(argv[1])) return krk_runtimeError(vm.exceptions->typeError, "expected str");
178 
179  if (!IS_INSTANCE(argv[0])) {
180  return FUNC_NAME(krk,setattr)(argc,argv,hasKw);
181  }
182 
183  /* It's an instance, that presumably does not have a `__setattr__`? */
184  return krk_instanceSetAttribute_wrapper(argv[0], AS_STRING(argv[1]), argv[2]);
185 }
186 
187 KRK_StaticMethod(object,__new__) {
188  KrkClass * _class = NULL;
189 
190  /* We don't actually care, but we want to accept them anyway */
191  int _argc = 0;
192  const KrkValue * _args = NULL;
193 
194  if (!krk_parseArgs("O!*~", (const char*[]){"cls"}, vm.baseClasses->typeClass, &_class, &_argc, &_args)) {
195  return NONE_VAL();
196  }
197 
198  KrkClass * _cls = _class;
199  while (_cls) {
200  if (_cls->_new && IS_NATIVE(OBJECT_VAL(_cls->_new)) && _cls->_new != KRK_BASE_CLASS(object)->_new) {
201  return krk_runtimeError(vm.exceptions->typeError, "object.__new__(%S) is not safe, use %S.__new__()", _class->name, _cls->name);
202  }
203  _cls = _cls->base;
204  }
205 
206  if (_class->_init == vm.baseClasses->objectClass->_init && (_argc || (hasKw && AS_DICT(argv[argc])->count))) {
207  return krk_runtimeError(vm.exceptions->typeError, "%S() takes no arguments", _class->name);
208  }
209 
210  return OBJECT_VAL(krk_newInstance(_class));
211 }
212 
213 KRK_Method(object,__init__) {
214  return NONE_VAL();
215 }
216 
217 KRK_StaticMethod(object,__init_subclass__) {
218  if (!krk_parseArgs(".", (const char*[]){NULL}, NULL)) return NONE_VAL();
219  return NONE_VAL();
220 }
221 
222 
236 KRK_Method(object,__repr__) {
237  KrkClass * type = krk_getType(self);
238 
239  KrkValue module = NONE_VAL();
240  krk_tableGet(&type->methods, OBJECT_VAL(S("__module__")), &module);
241  KrkValue qualname = NONE_VAL();
242  krk_tableGet(&type->methods, OBJECT_VAL(S("__qualname__")), &qualname);
243  KrkString * name = IS_STRING(qualname) ? AS_STRING(qualname) : type->name;
244  int includeModule = !(IS_NONE(module) || (IS_STRING(module) && AS_STRING(module) == S("builtins")));
245 
246  struct StringBuilder sb = {0};
247 
248  if (!krk_pushStringBuilderFormat(&sb, "<%s%s%s object",
249  includeModule ? AS_CSTRING(module) : "",
250  includeModule ? "." : "",
251  name->chars)) goto _error;
252 
253  if (IS_OBJECT(self) && !krk_pushStringBuilderFormat(&sb, " at %p", (void*)AS_OBJECT(self))) {
254  goto _error;
255  }
256 
257  krk_pushStringBuilder(&sb, '>');
258  return krk_finishStringBuilder(&sb);
259 
260 _error:
262  return NONE_VAL();
263 }
264 
265 KRK_Method(object,__str__) {
266  KrkClass * type = krk_getType(self);
267  if (unlikely(!type->_reprer)) return krk_runtimeError(vm.exceptions->typeError, "object is not representable");
268  krk_push(self);
269  return krk_callDirect(type->_reprer, 1);
270 }
271 
272 KRK_Method(object,__format__) {
273  METHOD_TAKES_EXACTLY(1);
274  if (!IS_STRING(argv[1])) return TYPE_ERROR(str,argv[1]);
275  if (AS_STRING(argv[1])->length != 0) return krk_runtimeError(vm.exceptions->typeError, "Unsupported format string");
276  KrkClass * type = krk_getType(argv[0]);
277  if (!type->_tostr) return krk_runtimeError(vm.exceptions->typeError, "'%T' can not be converted to str", argv[0]);
278  krk_push(argv[0]);
279  return krk_callDirect(type->_tostr, 1);
280 }
281 
282 #undef CURRENT_CTYPE
283 #undef CURRENT_NAME
284 
285 KRK_Function(len) {
286  FUNCTION_TAKES_EXACTLY(1);
287  /* Shortcuts */
288  if (IS_STRING(argv[0])) return INTEGER_VAL(AS_STRING(argv[0])->codesLength);
289  if (IS_TUPLE(argv[0])) return INTEGER_VAL(AS_TUPLE(argv[0])->values.count);
290 
291  KrkClass * type = krk_getType(argv[0]);
292  if (!type->_len) return krk_runtimeError(vm.exceptions->typeError, "object of type '%T' has no len()", argv[0]);
293  krk_push(argv[0]);
294 
295  return krk_callDirect(type->_len, 1);
296 }
297 
298 KRK_Function(dir) {
299  FUNCTION_TAKES_AT_MOST(1);
300  if (argc) {
301  KrkClass * type = krk_getType(argv[0]);
302  if (!type->_dir) {
303  return krk_dirObject(argc,argv,hasKw); /* Fallback */
304  }
305  krk_push(argv[0]);
306  return krk_callDirect(type->_dir, 1);
307  } else {
308  /* Current globals */
310  return krk_runtimeError(vm.exceptions->nameError, "No active globals context");
311  }
312 
313  /* Set up a new list for our output */
314  KrkValue myList = krk_list_of(0,NULL,0);
315  krk_push(myList);
316 
317  /* Put all the keys from the globals table in it */
319  for (size_t i = 0; i < globals->used; ++i) {
320  KrkTableEntry * entry = &globals->entries[i];
321  if (IS_KWARGS(entry->key)) continue;
322  krk_writeValueArray(AS_LIST(myList), entry->key);
323  }
324 
325  /* Now sort it */
326  FUNC_NAME(list,sort)(1,(KrkValue[]){krk_peek(0)},0);
327  return krk_pop(); /* Return the list */
328  }
329 }
330 
331 KRK_Function(repr) {
332  FUNCTION_TAKES_EXACTLY(1);
333  /* Everything should have a __repr__ */
334  KrkClass * type = krk_getType(argv[0]);
335  krk_push(argv[0]);
336  return krk_callDirect(type->_reprer, 1);
337 }
338 
339 #define trySlowMethod(name) do { \
340  KrkClass * type = krk_getType(argv[0]); \
341  KrkValue method; \
342  while (type) { \
343  if (krk_tableGet(&type->methods, name, &method)) { \
344  krk_push(method); \
345  krk_push(argv[0]); \
346  return krk_callStack(1); \
347  } \
348  type = type->base; \
349  } \
350 } while (0)
351 
352 KRK_Function(ord) {
353  FUNCTION_TAKES_EXACTLY(1);
354  trySlowMethod(vm.specialMethodNames[METHOD_ORD]);
355  return TYPE_ERROR(string of length 1,argv[0]);
356 }
357 
358 KRK_Function(chr) {
359  FUNCTION_TAKES_EXACTLY(1);
360  trySlowMethod(vm.specialMethodNames[METHOD_CHR]);
361  return TYPE_ERROR(int,argv[0]);
362 }
363 
364 KRK_Function(hex) {
365  FUNCTION_TAKES_EXACTLY(1);
366  trySlowMethod(vm.specialMethodNames[METHOD_HEX]);
367  return TYPE_ERROR(int,argv[0]);
368 }
369 
370 KRK_Function(oct) {
371  FUNCTION_TAKES_EXACTLY(1);
372  trySlowMethod(vm.specialMethodNames[METHOD_OCT]);
373  return TYPE_ERROR(int,argv[0]);
374 }
375 
376 KRK_Function(bin) {
377  FUNCTION_TAKES_EXACTLY(1);
378  trySlowMethod(vm.specialMethodNames[METHOD_BIN]);
379  return TYPE_ERROR(int,argv[0]);
380 }
381 
382 #define KRK_STRING_FAST(string,offset) (uint32_t)\
383  ((string->obj.flags & KRK_OBJ_FLAGS_STRING_MASK) <= (KRK_OBJ_FLAGS_STRING_UCS1) ? ((uint8_t*)string->codes)[offset] : \
384  ((string->obj.flags & KRK_OBJ_FLAGS_STRING_MASK) == (KRK_OBJ_FLAGS_STRING_UCS2) ? ((uint16_t*)string->codes)[offset] : \
385  ((uint32_t*)string->codes)[offset]))
386 
387 int krk_unpackIterable(KrkValue iterable, void * context, int callback(void *, const KrkValue *, size_t)) {
388  if (IS_TUPLE(iterable)) {
389  if (callback(context, AS_TUPLE(iterable)->values.values, AS_TUPLE(iterable)->values.count)) return 1;
390  } else if (IS_list(iterable)) {
391  if (callback(context, AS_LIST(iterable)->values, AS_LIST(iterable)->count)) return 1;
392  } else if (IS_dict(iterable)) {
393  for (size_t i = 0; i < AS_DICT(iterable)->used; ++i) {
394  if (!IS_KWARGS(AS_DICT(iterable)->entries[i].key)) {
395  if (callback(context, &AS_DICT(iterable)->entries[i].key, 1)) return 1;
396  }
397  }
398  } else if (IS_STRING(iterable)) {
399  krk_unicodeString(AS_STRING(iterable));
400  for (size_t i = 0; i < AS_STRING(iterable)->codesLength; ++i) {
401  KrkValue s = krk_string_get(2, (KrkValue[]){iterable,INTEGER_VAL(i)}, i);
402  if (unlikely(krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION)) return 1;
403  krk_push(s);
404  if (callback(context, &s, 1)) {
405  krk_pop();
406  return 1;
407  }
408  krk_pop();
409  }
410  } else {
411  KrkClass * type = krk_getType(iterable);
412  if (unlikely(!type->_iter)) {
413  krk_runtimeError(vm.exceptions->typeError, "'%T' object is not iterable", iterable);
414  return 1;
415  }
416 
417  /* Build the iterable */
418  krk_push(iterable);
419  KrkValue iterator = krk_callDirect(type->_iter, 1);
420 
421  if (unlikely(krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION)) return 1;
422 
423  krk_push(iterator);
424 
425  do {
426  /* Call the iterator */
427  krk_push(iterator);
428  KrkValue item = krk_callStack(0);
429 
430  if (unlikely(krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION)) {
431  krk_pop(); /* __iter__() result */
432  return 1;
433  }
434 
435  if (krk_valuesSame(iterator, item)) {
436  break;
437  }
438 
439  krk_push(item);
440  if (callback(context, &item, 1)) {
441  krk_pop(); /* item */
442  krk_pop(); /* __iter__ */
443  return 1;
444  }
445  krk_pop(); /* item */
446  } while (1);
447 
448  krk_pop(); /* __iter__() result */
449  }
450  return 0;
451 }
452 
454  KrkValue base;
455 };
456 
457 static int _any_callback(void * context, const KrkValue * values, size_t count) {
458  struct SimpleContext * _context = context;
459  for (size_t i = 0; i < count; ++i) {
460  if (!krk_isFalsey(values[i])) {
461  _context->base = BOOLEAN_VAL(1);
462  return 1;
463  }
464  }
465  return 0;
466 }
467 
468 KRK_Function(any) {
469  FUNCTION_TAKES_EXACTLY(1);
470  struct SimpleContext context = { BOOLEAN_VAL(0) };
471  krk_unpackIterable(argv[0], &context, _any_callback);
472  return context.base;
473 }
474 
475 static int _all_callback(void * context, const KrkValue * values, size_t count) {
476  struct SimpleContext * _context = context;
477  for (size_t i = 0; i < count; ++i) {
478  if (krk_isFalsey(values[i])) {
479  _context->base = BOOLEAN_VAL(0);
480  return 1;
481  }
482  }
483  return 0;
484 }
485 
486 KRK_Function(all) {
487  FUNCTION_TAKES_EXACTLY(1);
488  struct SimpleContext context = { BOOLEAN_VAL(1) };
489  krk_unpackIterable(argv[0], &context, _all_callback);
490  return context.base;
491 }
492 
493 #define CURRENT_CTYPE KrkInstance *
494 #define CURRENT_NAME self
495 
496 #define IS_map(o) (krk_isInstanceOf(o,KRK_BASE_CLASS(map)))
497 #define AS_map(o) (AS_INSTANCE(o))
498 KRK_Method(map,__init__) {
499  METHOD_TAKES_AT_LEAST(2);
500 
501  /* Attach the function to it */
502  krk_attachNamedValue(&self->fields, "_function", argv[1]);
503 
504  /* Make the iter objects */
505  KrkTuple * iters = krk_newTuple(argc - 2);
506  krk_push(OBJECT_VAL(iters));
507 
508  /* Attach the tuple to the object */
509  krk_attachNamedValue(&self->fields, "_iterables", krk_peek(0));
510  krk_pop();
511 
512  for (int i = 2; i < argc; ++i) {
513  KrkClass * type = krk_getType(argv[i]);
514  if (!type->_iter) {
515  return krk_runtimeError(vm.exceptions->typeError, "'%T' object is not iterable", argv[i]);
516  }
517  krk_push(argv[i]);
518  KrkValue asIter = krk_callDirect(type->_iter, 1);
519  if (krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION) return NONE_VAL();
520  /* Attach it to the tuple */
521  iters->values.values[iters->values.count++] = asIter;
522  }
523 
524  return NONE_VAL();
525 }
526 
527 KRK_Method(map,__iter__) {
528  METHOD_TAKES_NONE();
529  return OBJECT_VAL(self);
530 }
531 
532 KRK_Method(map,__call__) {
533  METHOD_TAKES_NONE();
534 
535  size_t stackOffset = krk_currentThread.stackTop - krk_currentThread.stack;
536 
537  /* Get members */
538  KrkValue function = NONE_VAL();
539  KrkValue iterators = NONE_VAL();
540 
541  if (!krk_tableGet(&self->fields, OBJECT_VAL(S("_function")), &function)) return krk_runtimeError(vm.exceptions->valueError, "corrupt map object");
542  if (!krk_tableGet(&self->fields, OBJECT_VAL(S("_iterables")), &iterators) || !IS_TUPLE(iterators)) return krk_runtimeError(vm.exceptions->valueError, "corrupt map object");
543 
544  krk_push(function);
545 
546  /* Go through each iterator */
547  for (size_t i = 0; i < AS_TUPLE(iterators)->values.count; ++i) {
548  /* Obtain the next value and push it */
549  krk_push(AS_TUPLE(iterators)->values.values[i]);
551  if (krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION) return NONE_VAL();
552  /* End iteration whenever one runs out */
553  if (krk_valuesEqual(krk_peek(0), AS_TUPLE(iterators)->values.values[i])) {
554  for (size_t j = 0; j < i + 1; ++j) krk_pop();
555  krk_pop(); /* the function */
556  return OBJECT_VAL(self);
557  }
558  }
559 
560  /* Call the function */
561  KrkValue val = krk_callStack(AS_TUPLE(iterators)->values.count);
563  return val;
564 }
565 
566 #define IS_zip(o) (krk_isInstanceOf(o,KRK_BASE_CLASS(zip)))
567 #define AS_zip(o) (AS_INSTANCE(o))
568 KRK_Method(zip,__init__) {
569  if (hasKw && AS_DICT(argv[argc])->count) return krk_runtimeError(vm.exceptions->typeError, "%s() takes no keyword arguments", "zip");
570 
571  KrkTuple * iters = krk_newTuple(argc - 1);
572  krk_push(OBJECT_VAL(iters));
573  krk_attachNamedValue(&self->fields, "_iterables", krk_peek(0));
574  krk_pop();
575 
576  for (int i = 1; i < argc; ++i) {
577  KrkClass * type = krk_getType(argv[i]);
578  if (!type->_iter) {
579  return krk_runtimeError(vm.exceptions->typeError, "'%T' object is not iterable", argv[i]);
580  }
581  krk_push(argv[i]);
582  KrkValue asIter = krk_callDirect(type->_iter, 1);
583  if (krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION) return NONE_VAL();
584  /* Attach it to the tuple */
585  iters->values.values[iters->values.count++] = asIter;
586  }
587 
588  return NONE_VAL();
589 }
590 
591 KRK_Method(zip,__iter__) {
592  METHOD_TAKES_NONE();
593  return OBJECT_VAL(self);
594 }
595 
596 KRK_Method(zip,__call__) {
597  METHOD_TAKES_NONE();
598 
599  /* Get members */
600  KrkValue iterators = NONE_VAL();
601  if (!krk_tableGet(&self->fields, OBJECT_VAL(S("_iterables")), &iterators) || !IS_TUPLE(iterators)) return krk_runtimeError(vm.exceptions->valueError, "corrupt zip object");
602 
603  /* Set up a tuple */
604  KrkTuple * out = krk_newTuple(AS_TUPLE(iterators)->values.count);
605  krk_push(OBJECT_VAL(out));
606 
607  /* Go through each iterator */
608  for (size_t i = 0; i < AS_TUPLE(iterators)->values.count; ++i) {
609  krk_push(AS_TUPLE(iterators)->values.values[i]);
611  if (krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION) return NONE_VAL();
612  if (krk_valuesEqual(krk_peek(0), AS_TUPLE(iterators)->values.values[i])) {
613  return OBJECT_VAL(self);
614  }
615  out->values.values[out->values.count++] = krk_pop();
616  }
617 
618  /* Return tuple */
619  return krk_pop();
620 }
621 
622 #define IS_filter(o) (krk_isInstanceOf(o,KRK_BASE_CLASS(filter)))
623 #define AS_filter(o) (AS_INSTANCE(o))
624 KRK_Method(filter,__init__) {
625  METHOD_TAKES_EXACTLY(2);
626  krk_attachNamedValue(&self->fields, "_function", argv[1]);
627  KrkClass * type = krk_getType(argv[2]);
628  if (!type->_iter) {
629  return krk_runtimeError(vm.exceptions->typeError, "'%T' object is not iterable", argv[2]);
630  }
631  krk_push(argv[2]);
632  KrkValue asIter = krk_callDirect(type->_iter, 1);
633  if (krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION) return NONE_VAL();
634  krk_attachNamedValue(&self->fields, "_iterator", asIter);
635 
636  return NONE_VAL();
637 }
638 
639 KRK_Method(filter,__iter__) {
640  METHOD_TAKES_NONE();
641  return OBJECT_VAL(self);
642 }
643 
644 KRK_Method(filter,__call__) {
645  METHOD_TAKES_NONE();
646  size_t stackOffset = krk_currentThread.stackTop - krk_currentThread.stack;
647  KrkValue function = NONE_VAL();
648  KrkValue iterator = NONE_VAL();
649 
650  if (!krk_tableGet(&self->fields, OBJECT_VAL(S("_function")), &function)) return krk_runtimeError(vm.exceptions->valueError, "corrupt filter object");
651  if (!krk_tableGet(&self->fields, OBJECT_VAL(S("_iterator")), &iterator)) return krk_runtimeError(vm.exceptions->valueError, "corrupt filter object");
652 
653  while (1) {
654  krk_push(iterator);
656 
657  if (krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION) return NONE_VAL();
658  if (krk_valuesEqual(iterator, krk_peek(0))) {
660  return OBJECT_VAL(self);
661  }
662 
663  if (IS_NONE(function)) {
664  if (krk_isFalsey(krk_peek(0))) {
665  krk_pop(); /* iterator result */
666  continue;
667  }
668  } else {
669  krk_push(function);
670  krk_push(krk_peek(1));
671  KrkValue result = krk_callStack(1);
672  if (krk_isFalsey(result)) {
673  krk_pop(); /* iterator result */
674  continue;
675  }
676  }
677 
678  KrkValue out = krk_pop();
680  return out;
681  }
682 }
683 
684 #define IS_enumerate(o) (krk_isInstanceOf(o,KRK_BASE_CLASS(enumerate)))
685 #define AS_enumerate(o) (AS_INSTANCE(o))
686 KRK_Method(enumerate,__init__) {
687  KrkValue iterator;
688  KrkValue start = INTEGER_VAL(0);
689  if (!krk_parseArgs(".V|V", (const char*[]){"iterable","start"}, &iterator, &start)) return NONE_VAL();
690 
691  krk_attachNamedValue(&self->fields, "_counter", start);
692 
693  /* Attach iterator */
694  KrkClass * type = krk_getType(iterator);
695  if (!type->_iter) {
696  return krk_runtimeError(vm.exceptions->typeError, "'%T' object is not iterable", iterator);
697  }
698  krk_push(iterator);
699  KrkValue asIter = krk_callDirect(type->_iter, 1);
700  if (krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION) return NONE_VAL();
701  krk_attachNamedValue(&self->fields, "_iterator", asIter);
702 
703  return NONE_VAL();
704 }
705 
706 KRK_Method(enumerate,__iter__) {
707  METHOD_TAKES_NONE();
708  return OBJECT_VAL(self);
709 }
710 
711 extern KrkValue krk_operator_add (KrkValue a, KrkValue b);
712 KRK_Method(enumerate,__call__) {
713  METHOD_TAKES_NONE();
714  size_t stackOffset = krk_currentThread.stackTop - krk_currentThread.stack;
715  KrkValue counter = NONE_VAL();
716  KrkValue iterator = NONE_VAL();
717 
718  if (!krk_tableGet(&self->fields, OBJECT_VAL(S("_counter")), &counter)) return krk_runtimeError(vm.exceptions->valueError, "corrupt enumerate object");
719  if (!krk_tableGet(&self->fields, OBJECT_VAL(S("_iterator")), &iterator)) return krk_runtimeError(vm.exceptions->valueError, "corrupt enumerate object");
720 
721  KrkTuple * tupleOut = krk_newTuple(2);
722  krk_push(OBJECT_VAL(tupleOut));
723 
724  krk_push(iterator);
726 
727  if (krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION) {
729  return NONE_VAL();
730  }
731  if (krk_valuesEqual(iterator, krk_peek(0))) {
732  krk_pop();
733  krk_pop();
735  return OBJECT_VAL(self);
736  }
737 
738  /* Make a tuple */
739  tupleOut->values.values[tupleOut->values.count++] = counter;
740  tupleOut->values.values[tupleOut->values.count++] = krk_pop();
741 
742  krk_push(krk_operator_add(counter, INTEGER_VAL(1)));
743  krk_attachNamedValue(&self->fields, "_counter", krk_pop());
744 
745  KrkValue out = krk_pop();
747  return out;
748 }
749 
750 static int _sum_callback(void * context, const KrkValue * values, size_t count) {
751  struct SimpleContext * _context = context;
752  for (size_t i = 0; i < count; ++i) {
753  _context->base = krk_operator_add(_context->base, values[i]);
754  if (unlikely(krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION)) return 1;
755  }
756  return 0;
757 }
758 
759 KRK_Function(sum) {
760  KrkValue iterable;
761  KrkValue base = INTEGER_VAL(0);
762  if (!krk_parseArgs("V|$V", (const char*[]){"iterable","start"}, &iterable, &base)) return NONE_VAL();
763  struct SimpleContext context = { base };
764  if (krk_unpackIterable(iterable, &context, _sum_callback)) return NONE_VAL();
765  return context.base;
766 }
767 
768 static int _min_callback(void * context, const KrkValue * values, size_t count) {
769  struct SimpleContext * _context = context;
770  for (size_t i = 0; i < count; ++i) {
771  if (IS_KWARGS(_context->base)) _context->base = values[i];
772  else {
773  KrkValue check = krk_operator_lt(values[i], _context->base);
774  if (!IS_BOOLEAN(check)) return 1;
775  else if (AS_BOOLEAN(check) == 1) _context->base = values[i];
776  }
777  }
778  return 0;
779 }
780 
781 KRK_Function(min) {
782  FUNCTION_TAKES_AT_LEAST(1);
783  struct SimpleContext context = { KWARGS_VAL(0) };
784  if (argc > 1) {
785  if (_min_callback(&context, argv, argc)) return NONE_VAL();
786  } else {
787  if (krk_unpackIterable(argv[0], &context, _min_callback)) return NONE_VAL();
788  }
789  if (IS_KWARGS(context.base)) return krk_runtimeError(vm.exceptions->valueError, "empty argument to %s()", "min");
790  return context.base;
791 }
792 
793 static int _max_callback(void * context, const KrkValue * values, size_t count) {
794  struct SimpleContext * _context = context;
795  for (size_t i = 0; i < count; ++i) {
796  if (IS_KWARGS(_context->base)) _context->base = values[i];
797  else {
798  KrkValue check = krk_operator_gt(values[i], _context->base);
799  if (!IS_BOOLEAN(check)) return 1;
800  else if (AS_BOOLEAN(check) == 1) _context->base = values[i];
801  }
802  }
803  return 0;
804 }
805 
806 KRK_Function(max) {
807  FUNCTION_TAKES_AT_LEAST(1);
808  struct SimpleContext context = { KWARGS_VAL(0) };
809  if (argc > 1) {
810  if (_max_callback(&context, argv, argc)) return NONE_VAL();
811  } else {
812  if (krk_unpackIterable(argv[0], &context, _max_callback)) return NONE_VAL();
813  }
814  if (IS_KWARGS(context.base)) return krk_runtimeError(vm.exceptions->valueError, "empty argument to %s()", "max");
815  return context.base;
816 }
817 
818 KRK_Function(print) {
819  char * sep = NULL;
820  char * end = NULL;
821  size_t sepLen = 0;
822  size_t endLen = 0;
823  int remArgc;
824  const KrkValue * remArgv;
825  KrkValue file = NONE_VAL();
826  int flush = 0;
827 
828  if (!krk_parseArgs("*z#z#Vp", (const char*[]){"sep","end","file","flush"},
829  &remArgc, &remArgv,
830  &sep, &sepLen, &end, &endLen,
831  &file, &flush)) {
832  return NONE_VAL();
833  }
834 
835  /* Set default separator and end if not provided or set to None. */
836  if (!sep) { sep = " "; sepLen = 1; }
837  if (!end) { end = "\n"; endLen = 1; }
838 
839  for (int i = 0; i < remArgc; ++i) {
840 
841  /* If printing through a file object, get its @c write method */
842  if (!IS_NONE(file)) {
843  krk_push(krk_valueGetAttribute(file, "write"));
844  if (krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION) return NONE_VAL();
845  }
846 
847  /* Convert the argument to a printable form, first by trying __str__, then __repr__ */
848  KrkValue printable = remArgv[i];
849  krk_push(printable);
850  if (!IS_STRING(printable)) {
851  KrkClass * type = krk_getType(printable);
852  if (type->_tostr) {
853  krk_push((printable = krk_callDirect(type->_tostr, 1)));
854  } else if (type->_reprer) {
855  krk_push((printable = krk_callDirect(type->_reprer, 1)));
856  }
857  if (!IS_STRING(printable)) return krk_runtimeError(vm.exceptions->typeError, "__str__ returned non-string (type %T)", printable);
858  }
859 
860  if (!IS_NONE(file)) {
861  /* Call @c write */
862  krk_callStack(1);
863  if (krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION) return NONE_VAL();
864 
865  /* Print separator */
866  if (i + 1 < remArgc) {
867  krk_push(krk_valueGetAttribute(file, "write"));
868  krk_push(OBJECT_VAL(krk_copyString(sep,sepLen)));
869  krk_callStack(1);
870  if (krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION) return NONE_VAL();
871  }
872  } else {
873  fwrite(AS_CSTRING(printable), AS_STRING(printable)->length, 1, stdout);
874  krk_pop();
875  if (i + 1 < remArgc) fwrite(sep, sepLen, 1, stdout);
876  }
877  }
878 
879  if (!IS_NONE(file)) {
880  /* Print end */
881  krk_push(krk_valueGetAttribute(file, "write"));
882  krk_push(OBJECT_VAL(krk_copyString(end,endLen)));
883  krk_callStack(1);
884  if (krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION) return NONE_VAL();
885 
886  /* Maybe flush */
887  if (flush) {
888  krk_push(krk_valueGetAttribute(file, "flush"));
889  krk_callStack(0);
890  }
891  }else {
892  fwrite(end, endLen, 1, stdout);
893  if (flush) fflush(stdout);
894  }
895 
896  return NONE_VAL();
897 }
898 
904 KRK_Function(globals) {
905  FUNCTION_TAKES_NONE();
906  /* Make a new empty dict */
907  KrkValue dict = krk_dict_of(0, NULL, 0);
908  krk_push(dict);
909  /* Copy the globals table into it */
911  krk_pop();
912 
913  return dict;
914 }
915 
921 KRK_Function(locals) {
922  FUNCTION_TAKES_AT_MOST(1);
923  KrkValue dict = krk_dict_of(0, NULL, 0);
924  krk_push(dict);
925 
926  int index = 1;
927  if (argc > 0 && IS_INTEGER(argv[0])) {
928  if (AS_INTEGER(argv[0]) < 1) {
929  return krk_runtimeError(vm.exceptions->indexError, "Frame index must be >= 1");
930  }
931  if (krk_currentThread.frameCount < (size_t)AS_INTEGER(argv[0])) {
932  return krk_runtimeError(vm.exceptions->indexError, "Frame index out of range");
933  }
934  index = AS_INTEGER(argv[0]);
935  }
936 
938  KrkCodeObject * func = frame->closure->function;
939  size_t offset = frame->ip - func->chunk.code;
940 
941  /* First, we'll populate with arguments */
942  size_t slot = 0;
943  for (short int i = 0; i < func->potentialPositionals; ++i) {
944  krk_tableSet(AS_DICT(dict),
945  func->positionalArgNames.values[i],
946  krk_currentThread.stack[frame->slots + slot]);
947  slot++;
948  }
949  if (func->obj.flags & KRK_OBJ_FLAGS_CODEOBJECT_COLLECTS_ARGS) {
950  krk_tableSet(AS_DICT(dict),
952  krk_currentThread.stack[frame->slots + slot]);
953  slot++;
954  }
955  for (short int i = 0; i < func->keywordArgs; ++i) {
956  krk_tableSet(AS_DICT(dict),
957  func->keywordArgNames.values[i],
958  krk_currentThread.stack[frame->slots + slot]);
959  slot++;
960  }
961  if (func->obj.flags & KRK_OBJ_FLAGS_CODEOBJECT_COLLECTS_KWS) {
962  krk_tableSet(AS_DICT(dict),
963  func->keywordArgNames.values[func->keywordArgs],
964  krk_currentThread.stack[frame->slots + slot]);
965  slot++;
966  }
967  /* Now we need to find out what non-argument locals are valid... */
968  for (size_t i = 0; i < func->localNameCount; ++i) {
969  if (func->localNames[i].birthday <= offset &&
970  func->localNames[i].deathday >= offset) {
971  krk_tableSet(AS_DICT(dict),
972  OBJECT_VAL(func->localNames[i].name),
973  krk_currentThread.stack[frame->slots + func->localNames[i].id]);
974  }
975  }
976 
977  return krk_pop();
978 }
979 
980 KRK_Function(isinstance) {
981  FUNCTION_TAKES_EXACTLY(2);
982  if (IS_CLASS(argv[1])) {
983  return BOOLEAN_VAL(krk_isInstanceOf(argv[0], AS_CLASS(argv[1])));
984  } else if (IS_TUPLE(argv[1])) {
985  for (size_t i = 0; i < AS_TUPLE(argv[1])->values.count; ++i) {
986  if (IS_CLASS(AS_TUPLE(argv[1])->values.values[i]) && krk_isInstanceOf(argv[0], AS_CLASS(AS_TUPLE(argv[1])->values.values[i]))) {
987  return BOOLEAN_VAL(1);
988  }
989  }
990  return BOOLEAN_VAL(0);
991  } else {
992  return TYPE_ERROR(class or tuple,argv[1]);
993  }
994 }
995 
996 KRK_Function(issubclass) {
997  FUNCTION_TAKES_EXACTLY(2);
998  CHECK_ARG(0,class,KrkClass*,cls);
999  if (IS_CLASS(argv[1])) {
1000  return BOOLEAN_VAL(krk_isSubClass(cls, AS_CLASS(argv[1])));
1001  } else if (IS_TUPLE(argv[1])) {
1002  for (size_t i = 0; i < AS_TUPLE(argv[1])->values.count; ++i) {
1003  if (IS_CLASS(AS_TUPLE(argv[1])->values.values[i]) && krk_isSubClass(cls, AS_CLASS(AS_TUPLE(argv[1])->values.values[i]))) {
1004  return BOOLEAN_VAL(1);
1005  }
1006  }
1007  return BOOLEAN_VAL(0);
1008  } else {
1009  return TYPE_ERROR(class or tuple,argv[1]);
1010  }
1011 }
1012 
1013 #define IS_module(o) (IS_INSTANCE(o))
1014 #define AS_module(o) (AS_INSTANCE(o))
1015 
1016 KRK_Method(module,__repr__) {
1017  KrkValue name = NONE_VAL();
1018  krk_tableGet(&self->fields, vm.specialMethodNames[METHOD_NAME], &name);
1019 
1020  if (!IS_STRING(name)) {
1021  return OBJECT_VAL(S("<module>"));
1022  }
1023 
1024  KrkValue file = NONE_VAL();
1025  krk_tableGet(&self->fields, vm.specialMethodNames[METHOD_FILE], &file);
1026 
1027  struct StringBuilder sb = {0};
1028 
1029  if (!krk_pushStringBuilderFormat(&sb,"<module '%S' ", AS_STRING(name))) goto _error;
1030 
1031  if (IS_STRING(file)) {
1032  if (!krk_pushStringBuilderFormat(&sb, "from %R>", file)) goto _error;
1033  } else {
1034  if (!krk_pushStringBuilderFormat(&sb, "(built-in)>")) goto _error;
1035  }
1036 
1037  return krk_finishStringBuilder(&sb);
1038 _error:
1040  return NONE_VAL();
1041 }
1042 
1043 #define IS_Helper(o) (krk_isInstanceOf(o, KRK_BASE_CLASS(Helper)))
1044 #define AS_Helper(o) (AS_INSTANCE(o))
1045 #define IS_LicenseReader(o) (krk_isInstanceOf(o, KRK_BASE_CLASS(LicenseReader)))
1046 #define AS_LicenseReader(o) (AS_INSTANCE(o))
1047 
1048 KRK_Method(Helper,__repr__) {
1049  return OBJECT_VAL(S("Type help() for more help, or help(obj) to describe an object."));
1050 }
1051 
1052 KRK_Method(Helper,__call__) {
1053  METHOD_TAKES_AT_MOST(1);
1054  if (!krk_doRecursiveModuleLoad(S("help"))) return NONE_VAL();
1055  KrkValue helpModule = krk_pop();
1056  KrkValue callable = NONE_VAL();
1057 
1058  if (argc == 2) {
1059  krk_tableGet(&AS_INSTANCE(helpModule)->fields, OBJECT_VAL(S("simple")), &callable);
1060  } else {
1061  krk_tableGet(&AS_INSTANCE(helpModule)->fields, OBJECT_VAL(S("interactive")), &callable);
1062  }
1063 
1064  if (!IS_NONE(callable)) {
1065  krk_push(callable);
1066  if (argc == 2) krk_push(argv[1]);
1067  return krk_callStack(argc == 2);
1068  }
1069 
1070  return krk_runtimeError(vm.exceptions->typeError, "unexpected error");
1071 }
1072 
1073 KRK_Method(LicenseReader,__repr__) {
1074  return OBJECT_VAL(S("Copyright 2020-2022 K. Lange <klange@toaruos.org>. Type `license()` for more information."));
1075 }
1076 
1077 KRK_Method(LicenseReader,__call__) {
1078  METHOD_TAKES_NONE();
1079  if (!krk_doRecursiveModuleLoad(S("help"))) return NONE_VAL();
1080  KrkValue helpModule = krk_pop();
1081 
1082  KrkValue text = NONE_VAL();
1083  krk_tableGet(&AS_INSTANCE(helpModule)->fields, OBJECT_VAL(S("__licenseText")), &text);
1084 
1085  if (IS_STRING(text)) {
1086  printf("%s\n", AS_CSTRING(text));
1087  return NONE_VAL();
1088  }
1089 
1090  return krk_runtimeError(vm.exceptions->typeError, "unexpected error");
1091 }
1092 
1093 #define IS_property(o) (krk_isInstanceOf(o,KRK_BASE_CLASS(property)))
1094 #define AS_property(o) (AS_INSTANCE(o))
1095 
1096 struct Property {
1097  KrkInstance inst;
1098  KrkObj* fget;
1099  KrkObj* fset;
1100 };
1101 
1102 static void _property_gcscan(KrkInstance *_self) {
1103  struct Property * self = (struct Property*)_self;
1104  if (self->fget) krk_markObject(self->fget);
1105  if (self->fset) krk_markObject(self->fset);
1106 }
1107 
1108 KRK_Method(property,__init__) {
1109  METHOD_TAKES_AT_LEAST(1);
1110  METHOD_TAKES_AT_MOST(2); /* TODO fdel */
1111  krk_attachNamedValue(&self->fields, "fget", argv[1]);
1112 
1113  ((struct Property*)self)->fget = IS_OBJECT(argv[1]) ? AS_OBJECT(argv[1]) : NULL;
1114 
1115  /* Try to attach doc */
1116  if (IS_NATIVE(argv[1])) {
1117  krk_attachNamedValue(&self->fields, "__doc__",
1118  AS_NATIVE(argv[1])->doc ? OBJECT_VAL(krk_copyString(AS_NATIVE(argv[1])->doc, strlen(AS_NATIVE(argv[1])->doc))) : NONE_VAL());
1119  } else if (IS_CLOSURE(argv[1])) {
1120  krk_attachNamedValue(&self->fields, "__doc__",
1121  AS_CLOSURE(argv[1])->function->docstring ? OBJECT_VAL(AS_CLOSURE(argv[1])->function->docstring) : NONE_VAL());
1122  }
1123 
1124  /* Try to attach name */
1125  if (IS_NATIVE(argv[1])) {
1126  krk_attachNamedValue(&self->fields, "__name__",
1127  AS_NATIVE(argv[1])->name ? OBJECT_VAL(krk_copyString(AS_NATIVE(argv[1])->name, strlen(AS_NATIVE(argv[1])->name))) : NONE_VAL());
1128  } else if (IS_CLOSURE(argv[1])) {
1129  krk_attachNamedValue(&self->fields, "__name__",
1130  AS_CLOSURE(argv[1])->function->name ? OBJECT_VAL(AS_CLOSURE(argv[1])->function->name) : NONE_VAL());
1131  }
1132 
1133  if (argc > 2) {
1134  krk_attachNamedValue(&self->fields, "fset", argv[2]);
1135  ((struct Property*)self)->fset = IS_OBJECT(argv[2]) ? AS_OBJECT(argv[2]) : NULL;
1136  }
1137 
1138  return NONE_VAL();
1139 }
1140 
1141 KRK_Method(property,setter) {
1142  METHOD_TAKES_EXACTLY(1);
1143  krk_attachNamedValue(&self->fields, "fset", argv[1]);
1144  return argv[0]; /* Return the original property */
1145 }
1146 
1147 KRK_Method(property,__get__) {
1148  METHOD_TAKES_AT_LEAST(1); /* the owner */
1149 
1150  if (IS_NONE(argv[1])) return argv[0];
1151 
1152  struct Property * asProp = (struct Property *)self;
1153 
1154  if (asProp->fget) {
1155  krk_push(argv[1]);
1156  return krk_callDirect(asProp->fget, 1);
1157  }
1158 
1159  KrkValue fget;
1160  if (!krk_tableGet(&self->fields, OBJECT_VAL(S("fget")), &fget))
1161  return krk_runtimeError(vm.exceptions->attributeError, "'%T' object has no attribute '%s'", argv[0], "fget");
1162 
1163  krk_push(fget);
1164  krk_push(argv[1]);
1165  return krk_callStack(1);
1166 }
1167 
1168 KRK_Method(property,__set__) {
1169  METHOD_TAKES_EXACTLY(2); /* the owner and the value */
1170 
1171  struct Property * asProp = (struct Property *)self;
1172 
1173  if (asProp->fset) {
1174  krk_push(argv[1]);
1175  krk_push(argv[2]);
1176  return krk_callDirect(asProp->fset, 2);
1177  }
1178 
1179  KrkValue fset;
1180  if (krk_tableGet(&self->fields, OBJECT_VAL(S("fset")), &fset)) {
1181  krk_push(fset);
1182  krk_push(argv[1]);
1183  krk_push(argv[2]);
1184  return krk_callStack(2);
1185  }
1186 
1187  if (asProp->fget) {
1188  krk_push(argv[1]);
1189  krk_push(argv[2]);
1190  return krk_callDirect(asProp->fget, 2);
1191  }
1192 
1193  KrkValue fget;
1194  if (krk_tableGet(&self->fields, OBJECT_VAL(S("fget")), &fget)) {
1195  krk_push(fget);
1196  krk_push(argv[1]);
1197  krk_push(argv[2]);
1198  return krk_callStack(2);
1199  }
1200 
1201  return krk_runtimeError(vm.exceptions->attributeError, "attribute can not be set");
1202 }
1203 
1204 KRK_Method(property,__setattr__) {
1205  METHOD_TAKES_EXACTLY(2);
1206  if (!IS_STRING(argv[1])) return TYPE_ERROR(str,argv[1]);
1207  krk_instanceSetAttribute_wrapper(argv[0], AS_STRING(argv[1]), argv[2]);
1208  struct Property * asProp = (struct Property *)self;
1209 
1210  KrkValue fget = NONE_VAL();
1211  krk_tableGet(&self->fields, OBJECT_VAL(S("fget")), &fget);
1212  asProp->fget = (IS_CLOSURE(fget) || IS_NATIVE(fget)) ? AS_OBJECT(fget) : NULL;
1213 
1214  KrkValue fset = NONE_VAL();
1215  krk_tableGet(&self->fields, OBJECT_VAL(S("fset")), &fset);
1216  asProp->fset = (IS_CLOSURE(fset) || IS_NATIVE(fset)) ? AS_OBJECT(fset) : NULL;
1217 
1218  return argv[2];
1219 }
1220 
1227 KrkNative * krk_defineNativeProperty(KrkTable * table, const char * name, NativeFn function) {
1228  KrkNative * func = krk_newNative(function, name, 0);
1229  krk_push(OBJECT_VAL(func));
1230  KrkInstance * property = krk_newInstance(vm.baseClasses->propertyClass);
1231  krk_attachNamedObject(table, name, (KrkObj*)property);
1232  krk_attachNamedObject(&property->fields, "fget", (KrkObj*)func);
1233  krk_attachNamedObject(&property->fields, "fset", (KrkObj*)func);
1234  ((struct Property*)property)->fget = (KrkObj*)func;
1235  ((struct Property*)property)->fset = (KrkObj*)func;
1236  krk_pop();
1237  return func;
1238 }
1239 
1240 KRK_Function(id) {
1241  FUNCTION_TAKES_EXACTLY(1);
1242  if (!IS_OBJECT(argv[0])) return krk_runtimeError(vm.exceptions->typeError, "'%T' has no identity", argv[0]);
1243  return INTEGER_VAL((size_t)AS_OBJECT(argv[0]));
1244 }
1245 
1246 KRK_Function(hash) {
1247  FUNCTION_TAKES_EXACTLY(1);
1248  uint32_t hashed;
1249  if (krk_hashValue(argv[0], &hashed)) return NONE_VAL();
1250  return INTEGER_VAL(hashed);
1251 }
1252 
1253 KRK_Function(next) {
1254  FUNCTION_TAKES_EXACTLY(1);
1255  krk_push(argv[0]);
1256  return krk_callStack(0);
1257 }
1258 
1259 KRK_Function(abs) {
1260  FUNCTION_TAKES_EXACTLY(1);
1261  if (IS_INTEGER(argv[0])) {
1262  krk_integer_type i = AS_INTEGER(argv[0]);
1263  return INTEGER_VAL(i >= 0 ? i : -i);
1264 #ifndef KRK_NO_FLOAT
1265  } else if (IS_FLOATING(argv[0])) {
1266  double i = AS_FLOATING(argv[0]);
1267  return FLOATING_VAL(i >= 0 ? i : -i);
1268 #endif
1269  } else {
1270  trySlowMethod(vm.specialMethodNames[METHOD_ABS]);
1271  return krk_runtimeError(vm.exceptions->typeError, "bad operand type for 'abs()': '%T'", argv[0]);
1272  }
1273 }
1274 
1275 KRK_Function(format) {
1276  FUNCTION_TAKES_AT_LEAST(1);
1277  FUNCTION_TAKES_AT_MOST(2);
1278 
1279  KrkClass * type = krk_getType(argv[0]);
1280 
1281  if (!type->_format) {
1282  return krk_runtimeError(vm.exceptions->typeError, "'%T' has no __format__ method", argv[0]);
1283  }
1284 
1285  krk_push(argv[0]);
1286  if (argc < 2) krk_push(OBJECT_VAL(S("")));
1287  else krk_push(argv[1]);
1288 
1289  KrkValue result = krk_callDirect(type->_format, 2);
1290  if (!IS_STRING(result)) {
1291  return krk_runtimeError(vm.exceptions->typeError, "__format__ result was not a string");
1292  }
1293  return result;
1294 }
1295 
1296 static void module_sweep(KrkInstance * inst) {
1297 #ifndef KRK_STATIC_ONLY
1298  struct KrkModule * module = (struct KrkModule*)inst;
1299  if (module->libHandle) {
1300  krk_dlClose(module->libHandle);
1301  }
1302 #endif
1303 }
1304 
1305 KRK_Function(__build_class__) {
1306  KrkValue func = NONE_VAL();
1307  KrkString * name = NULL;
1308  KrkClass * base = vm.baseClasses->objectClass;
1309  KrkValue metaclass = OBJECT_VAL(vm.baseClasses->typeClass);
1310 
1311  if (!krk_parseArgs("VO!|O!$V~",
1312  (const char*[]){"func","name","base","metaclass"},
1313  &func,
1314  vm.baseClasses->strClass, &name,
1315  vm.baseClasses->typeClass, &base,
1316  &metaclass)) {
1317  return NONE_VAL();
1318  }
1319 
1320  if (IS_CLASS(metaclass)) {
1321  KrkClass * basemeta = base->_class ? base->_class : vm.baseClasses->typeClass;
1322  if (krk_isSubClass(AS_CLASS(metaclass), basemeta)) {
1323  /* good to go */
1324  } else if (krk_isSubClass(basemeta, AS_CLASS(metaclass))) {
1325  /* take the more derived one */
1326  metaclass = OBJECT_VAL(basemeta);
1327  } else {
1328  return krk_runtimeError(vm.exceptions->typeError,
1329  "metaclass conflict: %S is not a subclass of %S", AS_CLASS(metaclass)->name, basemeta->name);
1330  }
1331  }
1332 
1333  /* Push function */
1334  krk_push(func);
1335 
1336  /* Call __prepare__ from metaclass */
1337  krk_push(krk_valueGetAttribute_default(metaclass, "__prepare__", KWARGS_VAL(0)));
1338 
1339  /* Bail early on exception */
1340  if (krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION) return NONE_VAL();
1341 
1342  if (IS_KWARGS(krk_peek(0))) {
1343  krk_pop();
1344  krk_push(krk_dict_of(0,NULL,0));
1345  } else {
1346  krk_push(OBJECT_VAL(name));
1347  krk_push(OBJECT_VAL(base));
1348  /* Do we have keywords? */
1349  int args = 2;
1350  if (hasKw) {
1351  args += 3;
1352  krk_push(KWARGS_VAL(KWARGS_DICT));
1353  krk_push(argv[argc]);
1354  krk_push(KWARGS_VAL(1));
1355  }
1356  krk_push(krk_callStack(args));
1357  if (krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION) return NONE_VAL();
1358  }
1359 
1360  /* Run the class function on it */
1361  krk_push(krk_callStack(1));
1362  if (krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION) return NONE_VAL();
1363 
1364  /* Now call the metaclass with the name, base, namespace, and kwds */
1365  int args = 3;
1366  krk_push(OBJECT_VAL(name));
1367  krk_push(OBJECT_VAL(base));
1368  krk_push(metaclass);
1369  krk_swap(3);
1370 
1371  if (hasKw) {
1372  args += 3;
1373  krk_push(KWARGS_VAL(KWARGS_DICT));
1374  krk_push(argv[argc]);
1375  krk_push(KWARGS_VAL(1));
1376  }
1377 
1378  krk_push(krk_callStack(args));
1379  if (krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION) return NONE_VAL();
1380 
1381  /* Now assign the upvalue for the original function if it's a closure. */
1382  if (IS_CLOSURE(func)) {
1383  if (AS_CLOSURE(func)->upvalueCount && AS_CLOSURE(func)->upvalues[0]->location == -1 && IS_NONE(AS_CLOSURE(func)->upvalues[0]->closed)) {
1384  AS_CLOSURE(func)->upvalues[0]->closed = krk_peek(0);
1385  }
1386  }
1387 
1388  /* We're done, return the resulting class object. */
1389  return krk_pop();
1390 }
1391 
1392 #undef CURRENT_CTYPE
1393 #define CURRENT_CTYPE KrkUpvalue *
1394 #define IS_Cell(o) (krk_isObjType((o), KRK_OBJ_UPVALUE))
1395 #define AS_Cell(o) ((KrkUpvalue*)AS_OBJECT(o))
1396 
1397 KRK_StaticMethod(Cell,__new__) {
1398  KrkClass * _class = NULL;
1399  KrkValue contents = NONE_VAL();
1400  if (!krk_parseArgs("O!|V:Cell", (const char*[]){"cls","contents"}, KRK_BASE_CLASS(type), &_class, &contents)) {
1401  return NONE_VAL();
1402  }
1403  if (_class != KRK_BASE_CLASS(Cell)) {
1404  return krk_runtimeError(vm.exceptions->typeError, "can not assemble new Cell from %R", OBJECT_VAL(_class));
1405  }
1406 
1407  KrkUpvalue * out = krk_newUpvalue(-1);
1408  out->closed = contents;
1409  return OBJECT_VAL(out);
1410 }
1411 
1412 #define UPVALUE_LOCATION(upvalue) (upvalue->location == -1 ? &upvalue->closed : &upvalue->owner->stack[upvalue->location])
1413 KRK_Method(Cell,__repr__) {
1414  struct StringBuilder sb = {0};
1415 
1416  KrkValue contents = *UPVALUE_LOCATION(self);
1417 
1418  if (!krk_pushStringBuilderFormat(&sb,"<cell at %p: %T object", (void*)self, contents)) goto _error;
1419  if (IS_OBJECT(contents)) {
1420  if (!krk_pushStringBuilderFormat(&sb, " at %p>", (void*)AS_OBJECT(contents))) goto _error;
1421  } else {
1422  krk_pushStringBuilder(&sb,'>');
1423  }
1424 
1425  return krk_finishStringBuilder(&sb);
1426 
1427 _error:
1429  return NONE_VAL();
1430 }
1431 
1432 KRK_Method(Cell,cell_contents) {
1433  if (argc > 1) {
1434  *UPVALUE_LOCATION(self) = argv[1];
1435  }
1436  return *UPVALUE_LOCATION(self);
1437 }
1438 
1439 _noexport
1440 void _createAndBind_builtins(void) {
1441  vm.baseClasses->objectClass = krk_newClass(S("object"), NULL);
1442  krk_push(OBJECT_VAL(vm.baseClasses->objectClass));
1443 
1444  KrkClass * object = vm.baseClasses->objectClass;
1445  BIND_METHOD(object,__dir__);
1446  BIND_METHOD(object,__str__);
1447  BIND_METHOD(object,__repr__);
1448  BIND_METHOD(object,__hash__);
1449  BIND_METHOD(object,__eq__);
1450  BIND_METHOD(object,__format__);
1451  BIND_STATICMETHOD(object,__setattr__);
1452  BIND_STATICMETHOD(object,__new__);
1453  BIND_METHOD(object,__init__);
1454  BIND_CLASSMETHOD(object,__init_subclass__);
1455  krk_finalizeClass(object);
1456  KRK_DOC(object,
1457  "@brief Base class for all types.\n\n"
1458  "The @c object base class provides the fallback implementations of methods like "
1459  "@ref object___dir__ \"__dir__\". All object and primitive types eventually inherit from @c object."
1460  );
1461 
1462  vm.baseClasses->moduleClass = krk_newClass(S("module"), vm.baseClasses->objectClass);
1463 
1464  KrkClass * module = vm.baseClasses->moduleClass;
1465  module->allocSize = sizeof(struct KrkModule);
1466  module->_ongcsweep = module_sweep;
1467 
1468  krk_push(OBJECT_VAL(module));
1469 
1470  BIND_METHOD(module,__repr__);
1471  krk_finalizeClass(module);
1472  KRK_DOC(module, "Type of imported modules and packages.");
1473 
1474  vm.builtins = krk_newInstance(module);
1475  krk_attachNamedObject(&vm.modules, "builtins", (KrkObj*)vm.builtins);
1476  krk_attachNamedObject(&vm.builtins->fields, "object", (KrkObj*)vm.baseClasses->objectClass);
1477  krk_pop();
1478  krk_pop();
1479 
1480  krk_attachNamedObject(&vm.builtins->fields, "__name__", (KrkObj*)S("builtins"));
1481  krk_attachNamedValue(&vm.builtins->fields, "__file__", NONE_VAL());
1482  KRK_DOC(vm.builtins,
1483  "@brief Internal module containing built-in functions and classes.\n\n"
1484  "Classes and functions from the @c \\__builtins__ module are generally available from "
1485  "all global namespaces. Built-in names can still be shadowed by module-level globals "
1486  "and function-level locals, so none the names in this module are reserved. When "
1487  "a built-in name has been shadowed, the original can be referenced directly as "
1488  " @c \\__builtins__.name instead.\n\n"
1489  "Built-in names may be bound from several sources. Most come from the core interpreter "
1490  "directly, but some may come from loaded C extension modules or the interpreter binary. "
1491  "Kuroko source modules are also free to append new names to the built-in name space by "
1492  "attaching new properties to the @c \\__builtins__ instance."
1493  );
1494 
1495  KrkClass * property = ADD_BASE_CLASS(KRK_BASE_CLASS(property), "property", object);
1496  property->allocSize = sizeof(struct Property);
1497  property->_ongcscan = _property_gcscan;
1498  KRK_DOC(BIND_METHOD(property,__init__),
1499  "@brief Create a property object.\n"
1500  "@arguments fget,[fset]\n\n"
1501  "When a property object is obtained from an instance of the class in which it is defined, "
1502  "the function or method assigned to @p fget is called with the instance as an argument. "
1503  "If @p fset is provided, it will be called with the instance and a value when the property "
1504  "object is assigned to through an instance. For legacy compatibility reasons, a property "
1505  "object's @p fget method may also accept an additional argument to act as a setter if "
1506  "@p fset is not provided, but this functionality may be removed in the future.\n\n"
1507  "The typical use for @c property is as a decorator on methods in a class. See also "
1508  "@ref property_setter \"property.setter\" for the newer Python-style approach to decorating a companion "
1509  "setter method.");
1510  BIND_METHOD(property,__get__);
1511  BIND_METHOD(property,__set__);
1512  KRK_DOC(BIND_METHOD(property,setter),
1513  "@brief Assign the setter method of a property object.\n"
1514  "@arguments fset\n\n"
1515  "This should be used as a decorator from an existing property object as follows:\n\n"
1516  "```\n"
1517  "class Foo():\n"
1518  " @property\n"
1519  " def bar(self):\n"
1520  " return 42\n"
1521  " @bar.setter\n"
1522  " def bar(self, val):\n"
1523  " print('setting bar to',val)\n"
1524  "```\n"
1525  "Be sure to apply the decorator to a function or method with the same name, as this "
1526  "name will be used to assign the property to the class's attribute table; using a "
1527  "different name will create a duplicate alias.");
1528  krk_finalizeClass(property);
1529 
1530  /* Need to do this after creating 'property' */
1531  BIND_PROP(object,__class__);
1532 
1533  KrkClass * Helper = ADD_BASE_CLASS(KRK_BASE_CLASS(Helper), "Helper", object);
1534  KRK_DOC(Helper,
1535  "@brief Special object that prints a helpeful message.\n\n"
1536  "Object that prints help summary when passed to @ref repr.");
1537  KRK_DOC(BIND_METHOD(Helper,__call__),
1538  "@brief Prints help text.\n"
1539  "@arguments obj=None\n\n"
1540  "Prints the help documentation attached to @p obj or starts the interactive help system by "
1541  "importing the @ref mod_help module.");
1542  BIND_METHOD(Helper,__repr__);
1543  krk_finalizeClass(Helper);
1544  krk_attachNamedObject(&vm.builtins->fields, "help", (KrkObj*)krk_newInstance(Helper));
1545 
1546  KrkClass * LicenseReader = ADD_BASE_CLASS(KRK_BASE_CLASS(LicenseReader), "LicenseReader", object);
1547  KRK_DOC(LicenseReader, "Special object that prints Kuroko's copyright information when passed to @ref repr");
1548  KRK_DOC(BIND_METHOD(LicenseReader,__call__), "Print the full license statement.");
1549  BIND_METHOD(LicenseReader,__repr__);
1550  krk_finalizeClass(LicenseReader);
1551  krk_attachNamedObject(&vm.builtins->fields, "license", (KrkObj*)krk_newInstance(LicenseReader));
1552 
1553  KrkClass * map = ADD_BASE_CLASS(KRK_BASE_CLASS(map), "map", object);
1554  KRK_DOC(map, "Return an iterator that applies a function to a series of iterables");
1555  BIND_METHOD(map,__init__);
1556  BIND_METHOD(map,__iter__);
1557  BIND_METHOD(map,__call__);
1558  krk_finalizeClass(map);
1559 
1560  KrkClass * zip = ADD_BASE_CLASS(KRK_BASE_CLASS(zip), "zip", object);
1561  KRK_DOC(zip,
1562  "@brief Returns an iterator that produces tuples of the nth element of each passed iterable.\n"
1563  "@arguments *iterables\n\n"
1564  "Creates an iterator that returns a tuple of elements from each of @p iterables, until one "
1565  "of @p iterables is exhuasted.");
1566  BIND_METHOD(zip,__init__);
1567  BIND_METHOD(zip,__iter__);
1568  BIND_METHOD(zip,__call__);
1569  krk_finalizeClass(zip);
1570 
1571  KrkClass * filter = ADD_BASE_CLASS(KRK_BASE_CLASS(filter), "filter", object);
1572  KRK_DOC(filter, "Return an iterator that returns only the items from an iterable for which the given function returns true.");
1573  BIND_METHOD(filter,__init__);
1574  BIND_METHOD(filter,__iter__);
1575  BIND_METHOD(filter,__call__);
1576  krk_finalizeClass(filter);
1577 
1578  KrkClass * enumerate = ADD_BASE_CLASS(KRK_BASE_CLASS(enumerate), "enumerate", object);
1579  KRK_DOC(enumerate, "Return an iterator that produces a tuple with a count the iterated values of the passed iteratable.");
1580  BIND_METHOD(enumerate,__init__);
1581  BIND_METHOD(enumerate,__iter__);
1582  BIND_METHOD(enumerate,__call__);
1583  krk_finalizeClass(enumerate);
1584 
1585  KrkClass * Cell = ADD_BASE_CLASS(KRK_BASE_CLASS(Cell), "Cell", object);
1586  Cell->allocSize = 0;
1587  Cell->obj.flags |= KRK_OBJ_FLAGS_NO_INHERIT;
1588  BIND_STATICMETHOD(Cell,__new__);
1589  BIND_METHOD(Cell,__repr__);
1590  BIND_PROP(Cell,cell_contents);
1591  krk_finalizeClass(Cell);
1592 
1593  BUILTIN_FUNCTION("isinstance", FUNC_NAME(krk,isinstance),
1594  "@brief Check if an object is an instance of a type.\n"
1595  "@arguments inst, cls\n\n"
1596  "Determine if an object @p inst is an instance of the given class @p cls or one if its subclasses. "
1597  "@p cls may be a single class or a tuple of classes.");
1598  BUILTIN_FUNCTION("issubclass", FUNC_NAME(krk,issubclass),
1599  "@brief Check if a class is a subclass of a type.\n"
1600  "@arguments cls, clsinfo\n\n"
1601  "Determine if the class @p cls is a subclass of the class @p clsinfo. @p clsinfo may be a single "
1602  "class or a tuple of classes.");
1603  BUILTIN_FUNCTION("globals", FUNC_NAME(krk,globals),
1604  "@brief Update and a return a mapping of names in the global namespace.\n\n"
1605  "Produces a dict mapping all of the names of the current globals namespace to their values. "
1606  "Updating this dict has no meaning, but modifying mutable values within it can affect the global namespace.");
1607  BUILTIN_FUNCTION("locals", FUNC_NAME(krk,locals),
1608  "@brief Update and return a mapping of names in the current local scope.\n"
1609  "@arguments callDepth=1\n\n"
1610  "Produces a dict mapping the names of the requested locals scope to their current stack values. "
1611  "If @p callDepth is provided, the locals of an outer call frame will be returned. If the requested "
1612  "call depth is out of range, an exception will be raised.");
1613  BUILTIN_FUNCTION("dir", FUNC_NAME(krk,dir),
1614  "@brief Return a list of known property names for a given object.\n"
1615  "@arguments [obj]\n\n"
1616  "Uses various internal methods to collect a list of property names of @p obj, returning "
1617  "that list sorted lexicographically. If no argument is given, the returned list will "
1618  "be the valid global names in the calling scope.");
1619  BUILTIN_FUNCTION("len", FUNC_NAME(krk,len),
1620  "@brief Return the length of a given sequence object.\n"
1621  "@arguments seq\n\n"
1622  "Returns the length of the sequence object @p seq, which must implement @c __len__.");
1623  BUILTIN_FUNCTION("repr", FUNC_NAME(krk,repr),
1624  "@brief Produce a string representation of the given object.\n"
1625  "@arguments val\n\n"
1626  "Return a string representation of the given object through its @c __repr__ method. "
1627  "@c repr strings should convey all information needed to recreate the object, if this is possible.");
1628  BUILTIN_FUNCTION("print", FUNC_NAME(krk,print),
1629  "@brief Print text to the standard output.\n"
1630  "@arguments *args,sep=' ',end='\\n',file=None,flush=False\n\n"
1631  "Prints the string representation of each argument to the standard output. "
1632  "The keyword argument @p sep specifies the string to print between values. "
1633  "The keyword argument @p end specifies the string to print after all of the values have been printed.");
1634  BUILTIN_FUNCTION("ord", FUNC_NAME(krk,ord),
1635  "@brief Obtain the ordinal integer value of a codepoint or byte.\n"
1636  "@arguments char\n\n"
1637  "Returns the integer codepoint value of a single-character string @p char.");
1638  BUILTIN_FUNCTION("chr", FUNC_NAME(krk,chr),
1639  "@brief Convert an integer codepoint to its string representation.\n"
1640  "@arguments codepoint\n\n"
1641  "Creates a single-codepoint string with the character represented by the integer codepoint @p codepoint.");
1642  BUILTIN_FUNCTION("hex", FUNC_NAME(krk,hex),
1643  "@brief Convert an integer value to a hexadecimal string.\n"
1644  "@arguments i\n\n"
1645  "Returns a string representation of @p i in hexadecimal, with a leading @c 0x.");
1646  BUILTIN_FUNCTION("oct", FUNC_NAME(krk,oct),
1647  "@brief Convert an integer value to an octal string.\n"
1648  "@arguments i\n\n"
1649  "Returns a string representation of @p i in octal, with a leading @c 0o.");
1650  BUILTIN_FUNCTION("any", FUNC_NAME(krk,any),
1651  "@brief Returns True if at least one element in the given iterable is truthy, False otherwise.\n"
1652  "@arguments iterable");
1653  BUILTIN_FUNCTION("all", FUNC_NAME(krk,all),
1654  "@brief Returns True if every element in the given iterable is truthy, False otherwise.\n"
1655  "@arguments iterable");
1656  BUILTIN_FUNCTION("getattr", FUNC_NAME(krk,getattr),
1657  "@brief Perform attribute lookup on an object using a string.\n"
1658  "@arguments obj,attribute,[default]\n\n"
1659  "Obtains the attributed named @p attribute from the object @p obj, if such an "
1660  "attribute exists. Attribute lookup ordering is complex and includes direct "
1661  "attribute tables of instances, dynamic attributes from classes, and so on. "
1662  "The use of @c getattr is equivalent to a dotted access. If @p attribute refers "
1663  "to a method of @p obj's class, a bound method will be obtained. If @p default "
1664  "is provided then the value supplied will be returned in the case where @p obj "
1665  "does not have an attribute named @p attribute, otherwise an @ref AttributeError "
1666  "will be raised.");
1667  BUILTIN_FUNCTION("setattr", FUNC_NAME(krk,setattr),
1668  "@brief Set an attribute of an object using a string name.\n"
1669  "@arguments obj,attribute,value\n\n"
1670  "Sets the attribute named by @p attribute of the object @p obj to @p value. "
1671  "If @p attribute refers to a @ref property object or other descriptor, the "
1672  "descriptor's @c \\__set__ method will be called. If @p obj is a class, instance, "
1673  "or other type with its own attribute table, then the field will be updated. If "
1674  "@p obj is a type without an attribute table and no class property provides an "
1675  "overriding setter for @p attribute, an @ref AttributeError will be raised.");
1676  BUILTIN_FUNCTION("hasattr", FUNC_NAME(krk,hasattr),
1677  "@brief Determines if an object has an attribute.\n"
1678  "@arguments obj,attribute\n\n"
1679  "Uses @ref getattr to determine if @p obj has an attribute named @p attribute.");
1680  BUILTIN_FUNCTION("delattr", FUNC_NAME(krk,delattr),
1681  "@brief Delete an attribute by name.\n"
1682  "@arguments obj,attribute\n\n"
1683  "Deletes the attribute @p attribute from @p obj.");
1684  BUILTIN_FUNCTION("sum", FUNC_NAME(krk,sum),
1685  "@brief add the elements of an iterable.\n"
1686  "@arguments iterable,start=0\n\n"
1687  "Continuously adds all of the elements from @p iterable to @p start and returns the result "
1688  "when @p iterable has been exhausted.");
1689  BUILTIN_FUNCTION("min", FUNC_NAME(krk,min),
1690  "@brief Return the lowest value in an iterable or the passed arguments.\n"
1691  "@arguments iterable");
1692  BUILTIN_FUNCTION("max", FUNC_NAME(krk,max),
1693  "@brief Return the highest value in an iterable or the passed arguments.\n"
1694  "@arguments iterable");
1695  BUILTIN_FUNCTION("id", FUNC_NAME(krk,id),
1696  "@brief Returns the identity of an object.\n"
1697  "@arguments val\n\n"
1698  "Returns the internal identity for @p val. Note that not all objects have "
1699  "identities; primitive values such as @c int or @c float do not have identities. "
1700  "Internally, this is the pointer value for a heap object, but this is an implementation detail.");
1701  BUILTIN_FUNCTION("hash", FUNC_NAME(krk,hash),
1702  "@brief Returns the hash of a value, used for table indexing.\n"
1703  "@arguments val\n\n"
1704  "If @p val is hashable, its hash value will be calculated if necessary and returned. "
1705  "If @p val is not hashable, @ref TypeError will be raised.");
1706  BUILTIN_FUNCTION("bin", FUNC_NAME(krk,bin),
1707  "@brief Convert an integer value to a binary string.\n"
1708  "@arguments i\n\n"
1709  "Produces a string representation of @p i in binary, with a leading @p 0b.");
1710  BUILTIN_FUNCTION("next", FUNC_NAME(krk,next),
1711  "@brief Compatibility function. Calls an iterable.\n"
1712  "@arguments iterable");
1713  BUILTIN_FUNCTION("abs", FUNC_NAME(krk,abs),
1714  "@brief Obtain the absolute value of a numeric.\n"
1715  "@arguments iterable");
1716  BUILTIN_FUNCTION("format", FUNC_NAME(krk,format),
1717  "@brief Format a value for string printing.\n"
1718  "@arguments value[,format_spec]");
1719  BUILTIN_FUNCTION("__build_class__", FUNC_NAME(krk,__build_class__),
1720  "@brief Internal function to build a type object.\n"
1721  "@arguments func, name, base=object, metaclass=type");
1722 }
1723 
Functions for debugging bytecode execution.
KrkValue krk_runtimeError(KrkClass *type, const char *fmt,...)
Produce and raise an exception with a formatted message.
Definition: exceptions.c:460
Functions for dealing with garbage collection and memory allocation.
void krk_markObject(KrkObj *object)
During a GC scan cycle, mark an object as used.
Definition: memory.c:321
Internal header.
Represents a managed call state in a VM thread.
Definition: vm.h:44
size_t slots
Definition: vm.h:47
KrkTable * globals
Definition: vm.h:49
KrkClosure * closure
Definition: vm.h:45
uint8_t * ip
Definition: vm.h:46
Type object.
Definition: object.h:215
KrkObj * _tostr
__str__ Called to produce a string from an instance
Definition: object.h:230
KrkCleanupCallback _ongcsweep
C function to call when the garbage collector is discarding an instance of this class.
Definition: object.h:224
KrkClass * krk_newClass(KrkString *name, KrkClass *base)
Create a new class object.
Definition: object.c:324
KrkObj * _reprer
__repr__ Called to create a reproducible string representation of an instance
Definition: object.h:229
KrkString * name
Name of the class.
Definition: object.h:219
struct KrkClass * base
Pointer to base class implementation.
Definition: object.h:221
KrkObj * _init
__init__ Implicitly called when an instance is created
Definition: object.h:232
KrkObj * _len
__len__ Generally called by len() but may be used to determine truthiness
Definition: object.h:234
size_t allocSize
Size to allocate when creating instances of this class.
Definition: object.h:222
KrkObj obj
Base.
Definition: object.h:216
KrkObj * _iter
__iter__ Called by for ... in ..., etc.
Definition: object.h:238
KrkTable methods
General attributes table.
Definition: object.h:218
KrkObj * _dir
__dir__ Overrides normal behavior for dir()
Definition: object.h:240
void krk_finalizeClass(KrkClass *_class)
Finalize a class by collecting pointers to core methods.
Definition: vm.c:189
struct KrkClass * _class
Metaclass.
Definition: object.h:217
Function object.
Definition: object.h:195
KrkCodeObject * function
The codeobject containing the bytecode run when this function is called.
Definition: object.h:197
Code object.
Definition: object.h:163
unsigned short potentialPositionals
Precalculated positional arguments for complex argument processing.
Definition: object.h:167
KrkChunk chunk
Bytecode data.
Definition: object.h:170
KrkValueArray positionalArgNames
Array of names for positional arguments (and *args)
Definition: object.h:173
KrkLocalEntry * localNames
Stores the names of local variables used in the function, for debugging.
Definition: object.h:177
unsigned short keywordArgs
Arity of keyword (default) arguments.
Definition: object.h:166
KrkObj obj
Base.
Definition: object.h:164
KrkValueArray keywordArgNames
Array of names for keyword-only arguments (and **kwargs)
Definition: object.h:174
size_t localNameCount
Number of entries in localNames.
Definition: object.h:176
KrkValue krk_dict_of(int argc, const KrkValue argv[], int hasKw)
Create a dict object.
Definition: obj_dict.c:19
An object of a class.
Definition: object.h:281
KrkInstance * krk_newInstance(KrkClass *_class)
Create a new instance of the given class.
Definition: object.c:343
KrkClass * _class
Type.
Definition: object.h:283
KrkValue krk_list_of(int argc, const KrkValue argv[], int hasKw)
Create a list object.
Definition: obj_list.c:30
size_t birthday
Instruction offset that this local name became valid on.
Definition: object.h:131
KrkString * name
Name of the local.
Definition: object.h:133
size_t id
Local ID as used by opcodes; offset from the frame's stack base.
Definition: object.h:130
size_t deathday
Instruction offset that this local name becomes invalid on.
Definition: object.h:132
Representation of a loaded module.
Definition: object.h:385
Managed binding to a C function.
Definition: object.h:309
KrkNative * krk_newNative(NativeFn function, const char *name, int type)
Create a native function binding object.
Definition: object.c:281
The most basic object type.
Definition: object.h:41
uint32_t hash
Cached hash value for table keys.
Definition: object.h:44
uint16_t flags
General object flags, mostly related to garbage collection.
Definition: object.h:43
uint16_t type
Tag indicating core type.
Definition: object.h:42
Immutable sequence of Unicode codepoints.
Definition: object.h:93
void * krk_unicodeString(KrkString *string)
Ensure that a codepoint representation of a string is available.
Definition: object.c:153
KrkString * krk_copyString(const char *chars, size_t length)
Obtain a string object representation of the given C string.
Definition: object.c:224
char * chars
UTF8 canonical data.
Definition: object.h:97
One (key,value) pair in a table.
Definition: table.h:20
Simple hash table of arbitrary keys to values.
Definition: table.h:28
int krk_tableGet(KrkTable *table, KrkValue key, KrkValue *value)
Obtain the value associated with a key in a table.
Definition: table.c:211
int krk_tableSet(KrkTable *table, KrkValue key, KrkValue value)
Assign a value to a key in a table.
Definition: table.c:148
void krk_attachNamedObject(KrkTable *table, const char name[], KrkObj *obj)
Attach an object to an attribute table.
Definition: vm.c:808
KrkTableEntry * entries
Definition: table.h:32
void krk_attachNamedValue(KrkTable *table, const char name[], KrkValue obj)
Attach a value to an attribute table.
Definition: vm.c:794
KrkNative * krk_defineNativeProperty(KrkTable *table, const char *name, NativeFn func)
Attach a native dynamic property to an attribute table.
Definition: builtins.c:1227
void krk_tableAddAll(KrkTable *from, KrkTable *to)
Add all key-value pairs from 'from' into 'to'.
Definition: table.c:202
size_t capacity
Definition: table.h:30
size_t used
Definition: table.h:31
size_t frameCount
Definition: vm.h:156
KrkValue * stack
Definition: vm.h:158
KrkValue * stackTop
Definition: vm.h:159
KrkCallFrame * frames
Definition: vm.h:155
int flags
Definition: vm.h:165
Immutable sequence of arbitrary values.
Definition: object.h:323
KrkValueArray values
Stores the length, capacity, and actual values of the tuple.
Definition: object.h:325
KrkTuple * krk_newTuple(size_t length)
Create a new tuple.
Definition: object.c:357
Storage for values referenced from nested functions.
Definition: object.h:115
KrkValue closed
Heap storage for closed value.
Definition: object.h:118
KrkUpvalue * krk_newUpvalue(int slot)
Create an upvalue slot.
Definition: object.c:315
KrkValue * values
Definition: value.h:78
void krk_writeValueArray(KrkValueArray *array, KrkValue value)
Add a value to a value array.
Definition: value.c:17
size_t count
Definition: value.h:77
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.
Definition: vm.c:282
int krk_valuesEqual(KrkValue a, KrkValue b)
Compare two values for equality.
Definition: value.c:106
KrkClass * krk_getType(KrkValue value)
Get the class representing a value.
Definition: vm.c:240
static int krk_valuesSame(KrkValue a, KrkValue b)
Compare two values by identity.
Definition: value.h:141
KrkValue krk_valueGetAttribute(KrkValue value, char *name)
Obtain a property of an object by name.
Definition: vm.c:1769
int krk_isFalsey(KrkValue value)
Determine the truth of a value.
Definition: vm.c:821
int krk_hashValue(KrkValue value, uint32_t *hashOut)
Calculate the hash for a value.
Definition: table.c:47
KrkValue krk_set_of(int argc, const KrkValue argv[], int hasKw)
Create a set object.
Definition: obj_set.c:343
Inline flexible string array.
Definition: util.h:162
Utilities for creating native bindings.
#define krk_parseArgs(f, n,...)
Parse arguments to a function while accepting keyword arguments.
Definition: util.h:360
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
void krk_pushStringBuilder(struct StringBuilder *sb, char c)
Add a character to the end of a string builder.
Definition: obj_str.c:1082
#define KRK_DOC(thing, text)
Attach documentation to a thing of various types.
Definition: util.h:304
Definitions for primitive stack references.
Core API for the bytecode virtual machine.
krk_threadLocal KrkThreadState krk_currentThread
Thread-local VM state.
int krk_getAttribute(KrkString *name)
Implementation of the GET_PROPERTY instruction.
Definition: vm.c:1765
int krk_setAttribute(KrkString *name)
Implementation of the SET_PROPERTY instruction.
Definition: vm.c:1903
KrkValue krk_callStack(int argCount)
Call a callable on the stack with argCount arguments.
Definition: vm.c:732
#define vm
Convenience macro for namespacing.
Definition: vm.h:257
int krk_doRecursiveModuleLoad(KrkString *name)
Load a module by a dotted name.
Definition: vm.c:1572
int krk_delAttribute(KrkString *name)
Implementation of the DEL_PROPERTY instruction.
Definition: vm.c:1825
KrkValue krk_operator_lt(KrkValue, KrkValue)
Compare two values, returning True if the left is less than the right.
KrkValue krk_pop(void)
Pop the top of the stack.
Definition: vm.c:131
KrkValue krk_valueGetAttribute_default(KrkValue value, char *name, KrkValue defaultVal)
See krk_valueGetAttribute.
Definition: vm.c:1780
void krk_swap(int distance)
Swap the top of the stack of the value distance slots down.
Definition: vm.c:145
KrkValue krk_dirObject(int argc, const KrkValue argv[], int hasKw)
Obtain a list of properties for an object.
Definition: builtins.c:13
void krk_push(KrkValue value)
Push a stack value.
Definition: vm.c:118
KrkValue krk_callDirect(KrkObj *callable, int argCount)
Call a closure or native function with argCount arguments.
Definition: vm.c:740
KrkValue krk_instanceSetAttribute_wrapper(KrkValue owner, KrkString *name, KrkValue to)
Set an attribute of an instance object, bypassing __setattr__.
Definition: vm.c:1862
KrkValue krk_peek(int distance)
Peek down from the top of the stack.
Definition: vm.c:139
KrkValue krk_operator_gt(KrkValue, KrkValue)
Compare to values, returning True if the left is greater than the right.