obj_function.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 /* Check for and return the name of a native function as a string object */
9 static KrkValue nativeFunctionName(KrkValue func) {
10  const char * string = ((KrkNative*)AS_OBJECT(func))->name;
11  if (!string) return OBJECT_VAL(S("<unnamed>"));
12  size_t len = strlen(string);
13  return OBJECT_VAL(krk_copyString(string,len));
14 }
15 
16 static KrkTuple * functionArgs(KrkCodeObject * _self) {
17  KrkTuple * tuple = krk_newTuple(_self->totalArguments);
18  krk_push(OBJECT_VAL(tuple));
19 
20  for (short i = 0; i < _self->potentialPositionals; ++i) {
21  tuple->values.values[tuple->values.count++] = _self->positionalArgNames.values[i];
22  }
23 
24  if (_self->obj.flags & KRK_OBJ_FLAGS_CODEOBJECT_COLLECTS_ARGS) {
25  tuple->values.values[tuple->values.count++] = krk_stringFromFormat("*%S", AS_STRING(_self->positionalArgNames.values[_self->potentialPositionals]));
26  }
27 
28  for (short i = 0; i < _self->keywordArgs; ++i) {
29  tuple->values.values[tuple->values.count++] = krk_stringFromFormat("%S=", AS_STRING(_self->keywordArgNames.values[i]));
30  }
31 
32  if (_self->obj.flags & KRK_OBJ_FLAGS_CODEOBJECT_COLLECTS_KWS) {
33  tuple->values.values[tuple->values.count++] = krk_stringFromFormat("**%S", AS_STRING(_self->keywordArgNames.values[_self->keywordArgs]));
34  }
35 
36  krk_pop();
37  return tuple;
38 }
39 
40 #define IS_method(o) IS_BOUND_METHOD(o)
41 #define IS_function(o) (IS_CLOSURE(o)|IS_NATIVE(o))
42 
43 #define AS_method(o) AS_BOUND_METHOD(o)
44 #define AS_function(o) (o)
45 
46 #define CURRENT_NAME self
47 #define CURRENT_CTYPE KrkValue
48 
49 KRK_StaticMethod(function,__new__) {
50  METHOD_TAKES_EXACTLY(3);
51  CHECK_ARG(1,codeobject,KrkCodeObject*,code);
52 
53  if (!IS_INSTANCE(argv[3]))
54  return TYPE_ERROR(dict or instance object,argv[3]);
55 
56  if (IS_CLOSURE(argv[2]) && AS_CLOSURE(argv[2])->upvalueCount == code->upvalueCount) {
57  /* Option 1: A function with the same upvalue count. Copy the upvalues exactly.
58  * As an example, this can be a lambda with a bunch of unused upvalue
59  * references - like "lambda: a, b, c". These variables will be captured
60  * using the relevant scope - and we don't have to care about whether
61  * they were properly marked, because the compiler took care of it
62  * when the lambda was compiled.
63  */
64  krk_push(OBJECT_VAL(krk_newClosure(code, argv[3])));
65  memcpy(AS_CLOSURE(krk_peek(0))->upvalues, AS_CLOSURE(argv[2])->upvalues,
66  sizeof(KrkUpvalue*) * code->upvalueCount);
67  return krk_pop();
68  } else if (IS_TUPLE(argv[2]) && AS_TUPLE(argv[2])->values.count == code->upvalueCount) {
69  /* Option 2: A tuple of values. New upvalue containers are built for each value,
70  * but they are immediately closed with the value in the tuple. They
71  * exist independently for this closure instance, and are not shared with
72  * any other closures.
73  */
74  krk_push(OBJECT_VAL(krk_newClosure(code, argv[3])));
75  for (size_t i = 0; i < code->upvalueCount; ++i) {
76  AS_CLOSURE(krk_peek(0))->upvalues[i] = krk_newUpvalue(-1);
77  AS_CLOSURE(krk_peek(0))->upvalues[i]->closed = AS_TUPLE(argv[2])->values.values[i];
78  }
79  return krk_pop();
80  }
81 
82  return TYPE_ERROR(managed function with equal upvalue count or tuple,argv[2]);
83 }
84 
85 KRK_Method(function,__doc__) {
86  ATTRIBUTE_NOT_ASSIGNABLE();
87 
88  if (IS_NATIVE(self) && AS_NATIVE(self)->doc) {
89  return OBJECT_VAL(krk_copyString(AS_NATIVE(self)->doc, strlen(AS_NATIVE(self)->doc)));
90  } else if (IS_CLOSURE(self) && AS_CLOSURE(self)->function->docstring) {
91  return OBJECT_VAL(AS_CLOSURE(self)->function->docstring);
92  }
93 
94  return NONE_VAL();
95 }
96 
97 KRK_Method(function,__name__) {
98  ATTRIBUTE_NOT_ASSIGNABLE();
99 
100  if (IS_NATIVE(self)) {
101  return nativeFunctionName(self);
102  } else if (IS_CLOSURE(self) && AS_CLOSURE(self)->function->name) {
103  return OBJECT_VAL(AS_CLOSURE(self)->function->name);
104  }
105 
106  return OBJECT_VAL(S(""));
107 }
108 
109 KRK_Method(function,__qualname__) {
110  ATTRIBUTE_NOT_ASSIGNABLE();
111 
112  if (IS_CLOSURE(self) && AS_CLOSURE(self)->function->qualname) {
113  return OBJECT_VAL(AS_CLOSURE(self)->function->qualname);
114  }
115 
116  return NONE_VAL();
117 }
118 
119 KRK_Method(function,__globals__) {
120  ATTRIBUTE_NOT_ASSIGNABLE();
121 
122  if (IS_CLOSURE(self)) {
123  return AS_CLOSURE(self)->globalsOwner;
124  }
125 
126  return NONE_VAL();
127 }
128 
129 KRK_Method(function,_ip_to_line) {
130  METHOD_TAKES_EXACTLY(1);
131  CHECK_ARG(1,int,krk_integer_type,ip);
132 
133  if (!IS_CLOSURE(self)) return NONE_VAL();
134 
135  size_t line = krk_lineNumber(&AS_CLOSURE(self)->function->chunk, ip);
136 
137  return INTEGER_VAL(line);
138 }
139 
140 KRK_Method(function,__repr__) {
141  METHOD_TAKES_NONE();
142 
143  /* Do we have a qualified name? */
144  KrkValue name = FUNC_NAME(function,__qualname__)(1,&self,0);
145  if (IS_NONE(name)) {
146  name = FUNC_NAME(function,__name__)(1,&self,0);
147  }
148 
149  if (!IS_STRING(name)) name = OBJECT_VAL(S("<unnamed>"));
150 
151  krk_push(name);
152 
153  struct StringBuilder sb = {0};
154  krk_pushStringBuilderFormat(&sb, "<function %S at %p>", AS_STRING(name), (void*)AS_OBJECT(self));
155 
156  krk_pop();
157 
158  return krk_finishStringBuilder(&sb);
159 }
160 
161 KRK_Method(function,__file__) {
162  ATTRIBUTE_NOT_ASSIGNABLE();
163 
164  if (IS_NATIVE(self)) return OBJECT_VAL(S("<builtin>"));
165 
166  return AS_CLOSURE(self)->function->chunk.filename ?
167  OBJECT_VAL(AS_CLOSURE(self)->function->chunk.filename) :
168  OBJECT_VAL(S(""));
169 }
170 
171 KRK_Method(function,__args__) {
172  ATTRIBUTE_NOT_ASSIGNABLE();
173  if (!IS_CLOSURE(self)) return OBJECT_VAL(krk_newTuple(0));
174  KrkTuple * tuple = functionArgs(AS_CLOSURE(self)->function);
175  return OBJECT_VAL(tuple);
176 }
177 
178 KRK_Method(function,__annotations__) {
179  ATTRIBUTE_NOT_ASSIGNABLE();
180  if (!IS_CLOSURE(self)) return NONE_VAL();
181  return AS_CLOSURE(self)->annotations;
182 }
183 
184 KRK_Method(function,__code__) {
185  ATTRIBUTE_NOT_ASSIGNABLE();
186  if (!IS_CLOSURE(self)) return NONE_VAL();
187  return OBJECT_VAL(AS_CLOSURE(self)->function);
188 }
189 
190 KRK_Method(function,__closure__) {
191  ATTRIBUTE_NOT_ASSIGNABLE();
192  if (!IS_CLOSURE(self)) {
193  return OBJECT_VAL(krk_newTuple(0));
194  }
195 
196  size_t cnt = AS_CLOSURE(self)->upvalueCount;
197  KrkTuple * out = krk_newTuple(cnt);
198  krk_push(OBJECT_VAL(out));
199  for (size_t i = 0; i < cnt; ++i) {
200  out->values.values[out->values.count++] = OBJECT_VAL(AS_CLOSURE(self)->upvalues[i]);
201  }
202 
203  return krk_pop();
204 }
205 
206 #undef CURRENT_CTYPE
207 #define CURRENT_CTYPE KrkCodeObject*
208 
209 KRK_StaticMethod(codeobject,__new__) {
210  return krk_runtimeError(vm.exceptions->typeError, "codeobject object is not instantiable");
211 }
212 
213 KRK_Method(codeobject,__name__) {
214  ATTRIBUTE_NOT_ASSIGNABLE();
215  return self->name ? OBJECT_VAL(self->name) : OBJECT_VAL(S(""));
216 }
217 
218 KRK_Method(codeobject,__repr__) {
219  METHOD_TAKES_NONE();
220  KrkValue s = FUNC_NAME(codeobject,__name__)(1,argv,0);
221  if (!IS_STRING(s)) return NONE_VAL();
222  krk_push(s);
223 
224  struct StringBuilder sb = {0};
225  krk_pushStringBuilderFormat(&sb, "<codeobject %S at %p>", AS_STRING(s), (void*)self);
226 
227  krk_pop();
228 
229  return krk_finishStringBuilder(&sb);
230 }
231 
232 KRK_Method(codeobject,_ip_to_line) {
233  METHOD_TAKES_EXACTLY(1);
234  CHECK_ARG(1,int,krk_integer_type,ip);
235  size_t line = krk_lineNumber(&self->chunk, ip);
236  return INTEGER_VAL(line);
237 }
238 
239 KRK_Method(codeobject,__constants__) {
240  ATTRIBUTE_NOT_ASSIGNABLE();
241  krk_push(OBJECT_VAL(krk_newTuple(self->chunk.constants.count)));
242  memcpy(AS_TUPLE(krk_peek(0))->values.values,
243  self->chunk.constants.values,
244  sizeof(KrkValue) * self->chunk.constants.count);
245  AS_TUPLE(krk_peek(0))->values.count = self->chunk.constants.count;
246  return krk_pop();
247 }
248 
249 KRK_Method(codeobject,co_code) {
250  return OBJECT_VAL(krk_newBytes(self->chunk.count, self->chunk.code));
251 }
252 
253 KRK_Method(codeobject,co_argcount) {
254  return INTEGER_VAL(self->potentialPositionals);
255 }
256 
257 KRK_Method(codeobject,co_kwonlyargcount) {
258  return INTEGER_VAL(self->keywordArgs);
259 }
260 
261 KRK_Method(codeobject,co_posonlyargcount) {
262  /* This is tricky because we don't store it anywhere */
263  for (size_t i = 0; i < self->potentialPositionals; ++i) {
264  if (!IS_NONE(self->positionalArgNames.values[i])) return INTEGER_VAL(i);
265  }
266  return INTEGER_VAL(0);
267 }
268 
269 KRK_Method(codeobject,__locals__) {
270  krk_push(OBJECT_VAL(krk_newTuple(self->localNameCount)));
271  for (size_t i = 0; i < self->localNameCount; ++i) {
272  krk_push(OBJECT_VAL(krk_newTuple(4)));
273  AS_TUPLE(krk_peek(0))->values.values[AS_TUPLE(krk_peek(0))->values.count++] = INTEGER_VAL(self->localNames[i].id);
274  AS_TUPLE(krk_peek(0))->values.values[AS_TUPLE(krk_peek(0))->values.count++] = INTEGER_VAL(self->localNames[i].birthday);
275  AS_TUPLE(krk_peek(0))->values.values[AS_TUPLE(krk_peek(0))->values.count++] = INTEGER_VAL(self->localNames[i].deathday);
276  AS_TUPLE(krk_peek(0))->values.values[AS_TUPLE(krk_peek(0))->values.count++] = OBJECT_VAL(self->localNames[i].name);
277  AS_TUPLE(krk_peek(1))->values.values[AS_TUPLE(krk_peek(1))->values.count++] = krk_peek(0);
278  krk_pop();
279  }
280  return krk_pop();
281 }
282 
283 /* Python-compatibility */
284 KRK_Method(codeobject,co_flags) {
285  ATTRIBUTE_NOT_ASSIGNABLE();
286 
287  int out = 0;
288 
289  /* For compatibility with Python, mostly because these are specified
290  * in at least one doc page with their raw values, we convert
291  * our flags to the useful CPython flag values... */
292  if (self->obj.flags & KRK_OBJ_FLAGS_CODEOBJECT_COLLECTS_ARGS) out |= 0x04;
293  if (self->obj.flags & KRK_OBJ_FLAGS_CODEOBJECT_COLLECTS_KWS) out |= 0x08;
294  if (self->obj.flags & KRK_OBJ_FLAGS_CODEOBJECT_IS_GENERATOR) out |= 0x20;
295  if (self->obj.flags & KRK_OBJ_FLAGS_CODEOBJECT_IS_COROUTINE) out |= 0x80;
296 
297  return INTEGER_VAL(out);
298 }
299 
300 KRK_Method(codeobject,__args__) {
301  ATTRIBUTE_NOT_ASSIGNABLE();
302  KrkTuple * tuple = functionArgs(self);
303  return OBJECT_VAL(tuple);
304 }
305 
306 KRK_Method(codeobject,__file__) {
307  ATTRIBUTE_NOT_ASSIGNABLE();
308  return self->chunk.filename ? OBJECT_VAL(self->chunk.filename) : OBJECT_VAL(S(""));
309 }
310 
311 #undef CURRENT_CTYPE
312 #define CURRENT_CTYPE KrkBoundMethod*
313 
314 /* __init__ here will be called with a dummy instance as argv[0]; avoid
315  * complications with method argument checking by not using KRK_METHOD. */
316 KRK_StaticMethod(method,__new__) {
317  FUNCTION_TAKES_EXACTLY(3);
318  if (!IS_OBJECT(argv[1])) return krk_runtimeError(vm.exceptions->typeError, "first argument must be a heap object");
319  return OBJECT_VAL(krk_newBoundMethod(argv[2],AS_OBJECT(argv[1])));
320 }
321 
322 KRK_Method(method,__name__) {
323  ATTRIBUTE_NOT_ASSIGNABLE();
324  return IS_function(OBJECT_VAL(self->method)) ? FUNC_NAME(function,__name__)(1,(KrkValue[]){OBJECT_VAL(self->method)},0) : OBJECT_VAL(S("?"));
325 }
326 
327 KRK_Method(method,__qualname__) {
328  ATTRIBUTE_NOT_ASSIGNABLE();
329  return IS_function(OBJECT_VAL(self->method)) ? FUNC_NAME(function,__qualname__)(1,(KrkValue[]){OBJECT_VAL(self->method)},0) : OBJECT_VAL(S("?"));
330 }
331 
332 KRK_Method(method,_ip_to_line) {
333  METHOD_TAKES_EXACTLY(1);
334  return IS_function(OBJECT_VAL(self->method)) ? FUNC_NAME(function,_ip_to_line)(2,(KrkValue[]){OBJECT_VAL(self->method),argv[1]},0) : OBJECT_VAL(S("?"));
335 }
336 
337 KRK_Method(method,__repr__) {
338  METHOD_TAKES_NONE();
339  KrkValue s = FUNC_NAME(method,__qualname__)(1,argv,0);
340  if (!IS_STRING(s)) s = FUNC_NAME(method,__name__)(1,argv,0);
341  if (!IS_STRING(s)) return NONE_VAL();
342  krk_push(s);
343 
344  struct StringBuilder sb = {0};
345  krk_pushStringBuilderFormat(&sb, "<bound method '%S' of %T object", AS_STRING(s), self->receiver);
346  if (IS_OBJECT(self->receiver)) krk_pushStringBuilderFormat(&sb, " at %p", (void*)AS_OBJECT(self->receiver));
347  krk_pushStringBuilder(&sb, '>');
348 
349  krk_pop();
350 
351  return krk_finishStringBuilder(&sb);
352 }
353 
354 KRK_Method(method,__file__) {
355  ATTRIBUTE_NOT_ASSIGNABLE();
356  return IS_function(OBJECT_VAL(self->method)) ? FUNC_NAME(function,__file__)(1,(KrkValue[]){OBJECT_VAL(self->method)},0) : OBJECT_VAL(S("?"));
357 }
358 
359 KRK_Method(method,__args__) {
360  ATTRIBUTE_NOT_ASSIGNABLE();
361  return IS_function(OBJECT_VAL(self->method)) ? FUNC_NAME(function,__args__)(1,(KrkValue[]){OBJECT_VAL(self->method)},0) : OBJECT_VAL(S("?"));
362 }
363 
364 KRK_Method(method,__doc__) {
365  ATTRIBUTE_NOT_ASSIGNABLE();
366  return IS_function(OBJECT_VAL(self->method)) ? FUNC_NAME(function,__doc__)(1,(KrkValue[]){OBJECT_VAL(self->method)},0) : OBJECT_VAL(S("?"));
367 }
368 
369 KRK_Method(method,__annotations__) {
370  ATTRIBUTE_NOT_ASSIGNABLE();
371  return IS_function(OBJECT_VAL(self->method)) ? FUNC_NAME(function,__annotations__)(1,(KrkValue[]){OBJECT_VAL(self->method)},0) : OBJECT_VAL(S("?"));
372 }
373 
374 KRK_Method(method,__code__) {
375  ATTRIBUTE_NOT_ASSIGNABLE();
376  return IS_function(OBJECT_VAL(self->method)) ? FUNC_NAME(function,__code__)(1,(KrkValue[]){OBJECT_VAL(self->method)},0) : OBJECT_VAL(S("?"));
377 }
378 
379 KRK_Method(method,__func__) {
380  ATTRIBUTE_NOT_ASSIGNABLE();
381  return OBJECT_VAL(self->method);
382 }
383 
384 KRK_Method(method,__self__) {
385  ATTRIBUTE_NOT_ASSIGNABLE();
386  return self->receiver;
387 }
388 
389 KRK_Function(staticmethod) {
390  KrkObj* method;
391  if (!krk_parseArgs("O!", (const char*[]){"method"}, KRK_BASE_CLASS(function), &method)) return NONE_VAL();
392  method->flags &= ~(KRK_OBJ_FLAGS_FUNCTION_MASK);
393  method->flags |= KRK_OBJ_FLAGS_FUNCTION_IS_STATIC_METHOD;
394  return OBJECT_VAL(method);
395 }
396 
397 KRK_Function(classmethod) {
398  KrkObj* method;
399  if (!krk_parseArgs("O!", (const char*[]){"method"}, KRK_BASE_CLASS(function), &method)) return NONE_VAL();
400  method->flags &= ~(KRK_OBJ_FLAGS_FUNCTION_MASK);
401  method->flags |= KRK_OBJ_FLAGS_FUNCTION_IS_CLASS_METHOD;
402  return OBJECT_VAL(method);
403 }
404 
405 _noexport
406 void _createAndBind_functionClass(void) {
407  KrkClass * codeobject = ADD_BASE_CLASS(vm.baseClasses->codeobjectClass, "codeobject", vm.baseClasses->objectClass);
408  codeobject->obj.flags |= KRK_OBJ_FLAGS_NO_INHERIT;
409  codeobject->allocSize = 0;
410  BIND_STATICMETHOD(codeobject,__new__);
411  BIND_METHOD(codeobject,__repr__);
412  BIND_METHOD(codeobject,_ip_to_line);
413  BIND_PROP(codeobject,__constants__);
414  BIND_PROP(codeobject,__name__);
415  BIND_PROP(codeobject,co_flags);
416  BIND_PROP(codeobject,co_code);
417  BIND_PROP(codeobject,co_argcount);
418  BIND_PROP(codeobject,co_kwonlyargcount);
419  BIND_PROP(codeobject,co_posonlyargcount);
420  BIND_PROP(codeobject,__locals__);
421  BIND_PROP(codeobject,__args__);
422  BIND_PROP(codeobject,__file__);
423  krk_finalizeClass(codeobject);
424 
425  KrkClass * function = ADD_BASE_CLASS(vm.baseClasses->functionClass, "function", vm.baseClasses->objectClass);
426  function->obj.flags |= KRK_OBJ_FLAGS_NO_INHERIT;
427  function->allocSize = 0;
428  BIND_STATICMETHOD(function,__new__);
429  BIND_METHOD(function,__repr__);
430  BIND_METHOD(function,_ip_to_line);
431  BIND_PROP(function,__doc__);
432  BIND_PROP(function,__name__);
433  BIND_PROP(function,__qualname__);
434  BIND_PROP(function,__file__);
435  BIND_PROP(function,__args__);
436  BIND_PROP(function,__annotations__);
437  BIND_PROP(function,__code__);
438  BIND_PROP(function,__globals__);
439  BIND_PROP(function,__closure__);
440  krk_defineNative(&function->methods, "__class_getitem__", krk_GenericAlias)->obj.flags |= KRK_OBJ_FLAGS_FUNCTION_IS_CLASS_METHOD;
441  krk_finalizeClass(function);
442 
443  KrkClass * method = ADD_BASE_CLASS(vm.baseClasses->methodClass, "method", vm.baseClasses->objectClass);
444  method->obj.flags |= KRK_OBJ_FLAGS_NO_INHERIT;
445  method->allocSize = 0;
446  BIND_STATICMETHOD(method,__new__);
447  BIND_METHOD(method,__repr__);
448  BIND_METHOD(method,_ip_to_line);
449  BIND_PROP(method,__doc__);
450  BIND_PROP(method,__name__);
451  BIND_PROP(method,__qualname__);
452  BIND_PROP(method,__file__);
453  BIND_PROP(method,__args__);
454  BIND_PROP(method,__annotations__);
455  BIND_PROP(method,__self__);
456  BIND_PROP(method,__func__);
457  BIND_PROP(method,__code__);
458  krk_finalizeClass(method);
459 
460  BUILTIN_FUNCTION("staticmethod", FUNC_NAME(krk,staticmethod), "A static method does not take an implicit self or cls argument.");
461  BUILTIN_FUNCTION("classmethod", FUNC_NAME(krk,classmethod), "A class method takes an implicit cls argument, instead of self.");
462 }
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.
NativeFn krk_GenericAlias
Special value for type hint expressions.
Definition: obj_typing.c:67
KrkBoundMethod * krk_newBoundMethod(KrkValue receiver, KrkObj *method)
Create a new bound method.
Definition: object.c:350
KrkBytes * krk_newBytes(size_t length, uint8_t *source)
Create a new byte array.
Definition: object.c:367
size_t krk_lineNumber(KrkChunk *chunk, size_t offset)
Obtain the line number for a byte offset into a bytecode chunk.
Definition: chunk.c:75
Type object.
Definition: object.h:215
size_t allocSize
Size to allocate when creating instances of this class.
Definition: object.h:222
KrkObj obj
Base.
Definition: object.h:216
void krk_finalizeClass(KrkClass *_class)
Finalize a class by collecting pointers to core methods.
Definition: vm.c:189
KrkClosure * krk_newClosure(KrkCodeObject *function, KrkValue globals)
Create a new function object.
Definition: object.c:290
Code object.
Definition: object.h:163
unsigned short potentialPositionals
Precalculated positional arguments for complex argument processing.
Definition: object.h:167
KrkValueArray positionalArgNames
Array of names for positional arguments (and *args)
Definition: object.h:173
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
unsigned short totalArguments
Total argument cells we can fill in complex argument processing.
Definition: object.h:168
Managed binding to a C function.
Definition: object.h:309
KrkObj obj
Base.
Definition: object.h:310
The most basic object type.
Definition: object.h:41
uint16_t flags
General object flags, mostly related to garbage collection.
Definition: object.h:43
KrkString * krk_copyString(const char *chars, size_t length)
Obtain a string object representation of the given C string.
Definition: object.c:224
KrkNative * krk_defineNative(KrkTable *table, const char *name, NativeFn function)
Attach a native C function to an attribute table.
Definition: vm.c:155
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
KrkUpvalue * krk_newUpvalue(int slot)
Create an upvalue slot.
Definition: object.c:315
KrkValue * values
Definition: value.h:78
size_t count
Definition: value.h:77
Stack reference or primative value.
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_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
Definitions for primitive stack references.
Core API for the bytecode virtual machine.
#define vm
Convenience macro for namespacing.
Definition: vm.h:257
KrkValue krk_pop(void)
Pop the top of the stack.
Definition: vm.c:131
void krk_push(KrkValue value)
Push a stack value.
Definition: vm.c:118
KrkValue krk_peek(int distance)
Peek down from the top of the stack.
Definition: vm.c:139