7 #define _DEFAULT_SOURCE
17 #include <toaru/rline.h>
20 #include "vendor/rline.h"
33 #define PROMPT_MAIN ">>> "
34 #define PROMPT_BLOCK " > "
36 #define CALLGRIND_TMP_FILE "/tmp/kuroko.callgrind.tmp"
38 static int enableRline = 1;
39 static int exitRepl = 0;
40 static int pasteEnabled = 0;
43 FUNCTION_TAKES_NONE();
49 int enabled = !pasteEnabled;
50 if (!
krk_parseArgs(
"|p",(
const char*[]){
"enabled"},&enabled))
return NONE_VAL();
51 pasteEnabled = enabled;
52 fprintf(stderr,
"Pasting is %s.\n", pasteEnabled ?
"enabled" :
"disabled");
56 static int doRead(
char * buf,
size_t bufSize) {
59 return rline(buf, bufSize);
62 return read(STDIN_FILENO, buf, bufSize);
65 static KrkValue readLine(
char * prompt,
int promptWidth,
char * syntaxHighlighter) {
70 rline_exit_string =
"";
71 rline_exp_set_prompts(prompt,
"", promptWidth, 0);
72 rline_exp_set_syntax(syntaxHighlighter);
73 rline_exp_set_tab_complete_func(NULL);
77 fprintf(stdout,
"%s", prompt);
85 ssize_t bytesRead = doRead(buf, 4096);
90 }
else if (bytesRead == 0 && !sb.length) {
94 pushStringBuilderStr(&sb, buf, bytesRead);
97 if (sb.length && sb.bytes[sb.length-1] ==
'\n') {
103 return finishStringBuilder(&sb);
106 discardStringBuilder(&sb);
116 KRK_Function(input) {
119 char * syntax = NULL;
121 if (!
krk_parseArgs(
"|siz", (
const char*[]){
"prompt",
"promptwidth",
"syntax"},
122 &prompt, &promptwidth, &syntax))
return NONE_VAL();
124 if (promptwidth == 0 && *prompt) {
125 promptwidth = strlen(prompt);
128 return readLine(prompt, promptwidth, syntax);
148 static char * syn_krk_keywords[] = {
149 "and",
"class",
"def",
"else",
"for",
"if",
"in",
"import",
"del",
150 "let",
"not",
"or",
"return",
"while",
"try",
"except",
"raise",
151 "continue",
"break",
"as",
"from",
"elif",
"lambda",
"with",
"is",
152 "pass",
"assert",
"yield",
"finally",
"async",
"await",
153 "True",
"False",
"None",
157 static void tab_complete_func(rline_context_t * c) {
162 char * tmp = malloc(c->offset + 1);
163 memcpy(tmp, c->buffer, c->offset);
164 tmp[c->offset] =
'\0';
172 }
while (space[count-1].type != TOKEN_EOF && space[count-1].type != TOKEN_ERROR);
182 if (space[count-base].type == TOKEN_DOT) {
186 }
else if (space[count-base].type >= TOKEN_IDENTIFIER && space[count-base].type <= TOKEN_WITH) {
195 if (space[count-n-1].type != TOKEN_DOT)
break;
197 if (n == count)
break;
198 if (space[count-n-1].type != TOKEN_IDENTIFIER)
break;
208 KrkValue next = findFromProperty(root, space[count-n]);
213 if (!isGlobal)
goto _cleanup;
216 krk_copyString(space[count-n].start,space[count-n].literalWidth), &next) || IS_NONE(next)) {
225 if (isGlobal && n < count && (space[count-n-1].type == TOKEN_IMPORT || space[count-n-1].type == TOKEN_FROM)) {
227 root = OBJECT_VAL(modules);
229 for (
size_t i = 0; i <
vm.modules.capacity; ++i) {
231 if (IS_KWARGS(entry->key))
continue;
237 int length = (space[count-base].type == TOKEN_DOT) ? 0 : (space[count-base].length);
238 isGlobal = isGlobal && (length != 0);
249 if (!IS_INSTANCE(dirList)) {
250 fprintf(stderr,
"\nInternal error while tab completting.\n");
254 for (
size_t i = 0; i < AS_LIST(dirList)->count; ++i) {
255 KrkString * s = AS_STRING(AS_LIST(dirList)->values[i]);
258 KrkValue thisValue = findFromProperty(root, asToken);
260 if (IS_CLOSURE(thisValue) || IS_BOUND_METHOD(thisValue) || IS_NATIVE(thisValue)) {
261 size_t allocSize = s->
length + 2;
262 char * tmp = malloc(allocSize);
263 size_t len = snprintf(tmp, allocSize,
"%s(", s->
chars);
272 if (length && (
int)s->
length < length)
continue;
276 for (
int i = 0; i < matchCount; ++i) {
277 if (!strcmp(matches[i], s->
chars)) {
284 if (!memcmp(s->
chars, space[count-base].start, length)) {
285 matches[matchCount] = s->
chars;
287 if (matchCount == 255)
goto _toomany;
296 root = OBJECT_VAL(
vm.builtins);
298 }
else if (isGlobal && AS_OBJECT(root) == (
KrkObj*)
vm.builtins) {
300 root = OBJECT_VAL(fakeKeywordsObject);
302 for (
char ** keyword = syn_krk_keywords; *keyword; keyword++) {
313 if (matchCount == 1) {
315 rline_insert(c, matches[0] + length);
316 rline_place_cursor();
317 }
else if (matchCount) {
321 char m = matches[0][j];
324 for (
int i = 1; i < matchCount; ++i) {
325 if (matches[i][j] != m) {
337 for (
int i = 0; i < matchCount; ++i) {
338 if ((
int)strlen(matches[i]) > maxWidth) maxWidth = strlen(matches[i]);
341 int colsPerLine = rline_terminal_width / (maxWidth + 2);
342 fprintf(stderr,
"\n");
344 for (
int i = 0; i < matchCount; ++i) {
345 fprintf(stderr,
"%-*s ", maxWidth, matches[i]);
347 if (column >= colsPerLine) {
348 fprintf(stderr,
"\n");
352 if (column != 0) fprintf(stderr,
"\n");
355 for (
int i = length; i < j; ++i) {
356 char tmp[2] = {matches[0][i],
'\0'};
357 rline_insert(c, tmp);
371 #ifndef KRK_DISABLE_DEBUG
372 static char * lastDebugCommand = NULL;
376 fprintf(stderr,
"At offset 0x%04lx of function '%s' from '%s' on line %lu:\n",
392 char buf[4096] = {0};
395 rline_exit_string=
"";
396 rline_exp_set_prompts(
"(dbg) ",
"", 6, 0);
397 rline_exp_set_syntax(
"krk-dbg");
398 rline_exp_set_tab_complete_func(NULL);
399 if (rline(buf, 4096) == 0)
goto _dbgQuit;
402 fprintf(stderr,
"(dbg) ");
404 char * out = fgets(buf, 4096, stdin);
405 if (!out || !strlen(buf)) {
406 fprintf(stdout,
"^D\n");
413 char * nl = strstr(buf,
"\n");
417 if (lastDebugCommand) {
418 strcpy(buf, lastDebugCommand);
425 rline_history_insert(strdup(buf));
429 if (lastDebugCommand) free(lastDebugCommand);
430 lastDebugCommand = strdup(buf);
435 char * sp = strstr(buf,
" ");
441 if (!strcmp(buf,
"c") || !strcmp(buf,
"continue")) {
442 return KRK_DEBUGGER_CONTINUE;
443 }
else if (!strcmp(buf,
"s") || !strcmp(buf,
"step")) {
444 return KRK_DEBUGGER_STEP;
445 }
else if (!strcmp(buf,
"abort")) {
446 return KRK_DEBUGGER_ABORT;
447 }
else if (!strcmp(buf,
"q") || !strcmp(buf,
"quit")) {
448 return KRK_DEBUGGER_QUIT;
449 }
else if (!strcmp(buf,
"bt") || !strcmp(buf,
"backtrace")) {
451 }
else if (!strcmp(buf,
"p") || !strcmp(buf,
"print")) {
453 fprintf(stderr,
"print requires an argument\n");
471 fprintf(stderr,
"\033[1;30m=> ");
473 fprintf(stderr,
"\033[0m\n");
482 }
else if (!strcmp(buf,
"break") || !strcmp(buf,
"b")) {
483 char * filename = arg;
485 fprintf(stderr,
"usage: break FILE LINE [type]\n");
489 char * lineno = strstr(filename,
" ");
491 fprintf(stderr,
"usage: break FILE LINE [type]\n");
501 char * type = strstr(lineno,
" ");
503 *type =
'\0'; type++;
504 if (!strcmp(type,
"repeat") || !strcmp(type,
"r")) {
506 }
else if (!strcmp(type,
"once") || !strcmp(type,
"o")) {
509 fprintf(stderr,
"Unrecognized breakpoint type: %s\n", type);
514 int lineInt = atoi(lineno);
518 fprintf(stderr,
"Sorry, couldn't add breakpoint.\n");
520 fprintf(stderr,
"Breakpoint %d enabled.\n", result);
523 }
else if (!strcmp(buf,
"i") || !strcmp(buf,
"info")) {
525 fprintf(stderr,
" info breakpoints - Show breakpoints.\n");
529 if (!strcmp(arg,
"breakpoints")) {
537 if (result == -1)
break;
538 if (result == -2)
continue;
540 fprintf(stderr,
"%-4d in %s+%d %s %s\n",
547 enabled ?
"enabled" :
"disabled");
552 fprintf(stderr,
"Unrecognized info object: %s\n", arg);
555 }
else if (!strcmp(buf,
"e") || !strcmp(buf,
"enable")) {
557 fprintf(stderr,
"enable requires an argument\n");
561 int breakIndex = atoi(arg);
564 fprintf(stderr,
"Invalid breakpoint handle.\n");
566 fprintf(stderr,
"Breakpoint %d enabled.\n", breakIndex);
568 }
else if (!strcmp(buf,
"d") || !strcmp(buf,
"disable")) {
570 fprintf(stderr,
"disable requires an argument\n");
574 int breakIndex = atoi(arg);
577 fprintf(stderr,
"Invalid breakpoint handle.\n");
579 fprintf(stderr,
"Breakpoint %d disabled.\n", breakIndex);
581 }
else if (!strcmp(buf,
"r") || !strcmp(buf,
"remove")) {
583 fprintf(stderr,
"remove requires an argument\n");
587 int breakIndex = atoi(arg);
590 fprintf(stderr,
"Invalid breakpoint handle.\n");
592 fprintf(stderr,
"Breakpoint %d removed.\n", breakIndex);
594 }
else if (!strcmp(buf,
"help")) {
596 "Kuroko Interactive Debugger\n"
597 " c continue - Continue until the next breakpoint.\n"
598 " s step - Execute this instruction and return to the debugger.\n"
599 " bt backtrace - Print a backtrace.\n"
600 " q quit - Exit the interpreter.\n"
601 " abort - Abort the interpreter (may create a core dump).\n"
602 " b break ... - Set a breakpoint.\n"
603 " e enable N - Enable breakpoint 'N'.\n"
604 " d disable N - Disable breakpoint 'N'.\n"
605 " r remove N - Remove breakpoint 'N'.\n"
606 " i info ... - See information about breakpoints.\n"
608 "Empty input lines will repeat the last command.\n"
611 fprintf(stderr,
"Unrecognized command: %s\n", buf);
616 return KRK_DEBUGGER_CONTINUE;
618 return KRK_DEBUGGER_QUIT;
622 static void handleSigint(
int sigNum) {
628 static void handleSigtrap(
int sigNum) {
633 static void bindSignalHandlers(
void) {
635 struct sigaction sigIntAction;
636 sigIntAction.sa_handler = handleSigint;
637 sigemptyset(&sigIntAction.sa_mask);
638 sigIntAction.sa_flags = 0;
644 struct sigaction sigTrapAction;
645 sigTrapAction.sa_handler = handleSigtrap;
646 sigemptyset(&sigTrapAction.sa_mask);
647 sigTrapAction.sa_flags = 0;
653 signal(SIGINT, handleSigint);
657 static void findInterpreter(
char * argv[]) {
659 vm.binpath = strdup(_pgmptr);
663 char * binpath = realpath(
"/proc/self/exe", NULL);
664 if (!binpath || (access(binpath, X_OK) != 0)) {
669 if (strchr(argv[0],
'/')) {
670 binpath = realpath(argv[0], NULL);
673 char * p = getenv(
"PATH");
675 char * _path = strdup(p);
678 char * next = strchr(path,
':');
679 if (next) *next++ =
'\0';
681 snprintf(tmp, 4096,
"%s/%s", path, argv[0]);
682 if (access(tmp, X_OK) == 0) {
683 binpath = strdup(tmp);
692 vm.binpath = binpath;
697 static int runString(
char * argv[],
int flags,
char *
string) {
698 findInterpreter(argv);
707 static int compileFile(
char * argv[],
int flags,
char * fileName) {
708 findInterpreter(argv);
712 FILE * f = fopen(fileName,
"r");
714 fprintf(stderr,
"%s: could not read file '%s': %s\n", argv[0], fileName, strerror(errno));
719 fseek(f, 0, SEEK_END);
720 size_t size = ftell(f);
721 fseek(f, 0, SEEK_SET);
722 char * buf = malloc(size+1);
723 if (fread(buf, 1, size, f) == 0)
return 2;
748 #define BUNDLED(name) do { \
749 extern KrkValue krk_module_onload_ ## name (); \
750 KrkValue moduleOut = krk_module_onload_ ## name (); \
751 krk_attachNamedValue(&vm.modules, # name, moduleOut); \
752 krk_attachNamedObject(&AS_INSTANCE(moduleOut)->fields, "__name__", (KrkObj*)krk_copyString(#name, sizeof(#name)-1)); \
753 krk_attachNamedValue(&AS_INSTANCE(moduleOut)->fields, "__file__", NONE_VAL()); \
757 int main(
int argc,
char * argv[]) {
759 SetConsoleOutputCP(65001);
762 char * runCmd = NULL;
764 int moduleAsMain = 0;
765 int inspectAfter = 0;
768 while ((opt = getopt(argc, argv,
"+:c:C:dgGim:rR:tTMSV-:")) != -1) {
775 flags |= KRK_THREAD_ENABLE_DISASSEMBLY;
779 flags |= KRK_GLOBAL_ENABLE_STRESS_GC;
782 flags |= KRK_GLOBAL_REPORT_GC_COLLECTS;
785 flags |= KRK_THREAD_SINGLE_STEP;
789 flags |= KRK_THREAD_ENABLE_TRACING;
792 flags |= KRK_GLOBAL_CALLGRIND;
793 vm.callgrindFile = fopen(CALLGRIND_TMP_FILE,
"w");
807 maxDepth = atoi(optarg);
810 return runString(argv,0,
"import kuroko; print(kuroko.module_paths)\n");
812 return runString(argv,0,
"import kuroko; print('Kuroko',kuroko.version)\n");
814 return compileFile(argv,flags,optarg);
816 fprintf(stderr,
"%s: option '%c' requires an argument\n", argv[0], optopt);
820 fprintf(stderr,
"%s: unrecognized option '%c'\n", argv[0], optopt);
823 optarg = argv[optind]+2;
826 if (!strcmp(optarg,
"version")) {
827 return runString(argv,0,
"import kuroko; print('Kuroko',kuroko.version)\n");
828 }
else if (!strcmp(optarg,
"help")) {
829 #ifndef KRK_NO_DOCUMENTATION
830 fprintf(stderr,
"usage: %s [flags] [FILE...]\n"
832 "Interpreter options:\n"
833 " -d Debug output from the bytecode compiler.\n"
834 " -g Collect garbage on every allocation.\n"
835 " -G Report GC collections.\n"
836 " -i Enter repl after a running -c, -m, or FILE.\n"
837 " -m mod Run a module as a script.\n"
838 " -r Disable complex line editing in the REPL.\n"
839 " -R depth Set maximum recursion depth.\n"
840 " -t Disassemble instructions as they are exceuted.\n"
841 " -T Write call trace file.\n"
842 " -C file Compile 'file', but do not execute it.\n"
843 " -M Print the default module import paths.\n"
844 " -S Enable single-step debugging.\n"
845 " -V Print version information.\n"
847 " --version Print version information.\n"
848 " --help Show this help text.\n"
850 "If no files are provided, the interactive REPL will run.\n",
855 fprintf(stderr,
"%s: unrecognized option '--%s'\n",
863 findInterpreter(argv);
866 if (maxDepth != -1) {
870 #ifndef KRK_DISABLE_DEBUG
876 for (
int arg = optind; arg < argc; ++arg) {
883 for (
int arg = optind; arg < argc + (optind == argc); ++arg)
krk_pop();
886 bindSignalHandlers();
897 char * _KUROKOPATH = getenv(
"KUROKOPATH");
914 extern FUNC_SIG(list,extend);
929 KRK_DOC(BIND_FUNC(
vm.builtins,input),
"@brief Read a line of input.\n"
930 "@arguments [prompt], promptwidth=None, syntax=None\n\n"
931 "Read a line of input from @c stdin. If the @c rline library is available, "
932 "it will be used to gather input. Input reading stops on end-of file or when "
933 "a read ends with a line feed, which will be removed from the returned string. "
934 "If a prompt is provided, it will be printed without a line feed before requesting "
935 "input. If @c rline is available, the prompt will be passed to the library as the "
936 "left-hand prompt string. If not provided, @p promptwidth will default to the width "
937 "of @p prompt in codepoints; if you are providing a prompt with escape characters or "
938 "characters with multi-column East-Asian Character Width be sure to pass a value "
939 "for @p promptwidth that reflects the display width of your prompt. "
940 "If provided, @p syntax specifies the name of an @c rline syntax module to "
941 "provide color highlighting of the input line.");
946 AS_STRING(AS_LIST(argList)->values[0]),
952 if (!inspectAfter)
return out;
956 }
else if (optind != argc) {
973 if ((!moduleAsMain && !runCmd && optind == argc) || inspectAfter) {
975 KRK_DOC(BIND_FUNC(
vm.builtins,exit),
"@brief Exit the interactive repl.\n\n"
976 "Only available from the interactive interpreter; exits the repl.");
977 KRK_DOC(BIND_FUNC(
vm.builtins,paste),
"@brief Toggle paste mode.\n"
978 "@arguments enabled=None\n\n"
979 "Toggles paste-safe mode, disabling automatic indentation in the repl. "
980 "If @p enabled is specified, the mode can be directly specified, otherwise "
981 "it will be set to the opposite of the current mode. The new mode will be "
982 "printed to stderr.");
995 KrkValue version, buildenv, builddate;
1000 fprintf(stdout,
"Kuroko %s (%s) with %s\n",
1001 AS_CSTRING(version), AS_CSTRING(builddate), AS_CSTRING(buildenv));
1004 fprintf(stdout,
"Type `help` for guidance, `paste()` to toggle automatic indentation, `license` for copyright information.\n");
1007 size_t lineCapacity = 8;
1008 size_t lineCount = 0;
1009 char ** lines = ALLOCATE(
char *, lineCapacity);
1010 size_t totalData = 0;
1012 char * allData = NULL;
1018 rline_exp_set_prompts(PROMPT_MAIN,
"", 4, 0);
1020 rline_exit_string=
"";
1022 rline_exp_set_syntax(
"krk");
1024 rline_exp_set_tab_complete_func(tab_complete_func);
1029 char buf[4096] = {0};
1035 rline_exp_set_prompts(PROMPT_BLOCK,
"", 4, 0);
1037 if (!pasteEnabled) {
1038 rline_preload = malloc(blockWidth + 1);
1039 for (
int i = 0; i < blockWidth; ++i) {
1040 rline_preload[i] =
' ';
1042 rline_preload[blockWidth] =
'\0';
1050 fprintf(stdout,
"%s", inBlock ? PROMPT_BLOCK : PROMPT_MAIN);
1057 if (rline(buf, 4096) == 0) {
1064 char * out = fgets(buf, 4096, stdin);
1066 fprintf(stdout,
"\n");
1067 }
else if ((!out || !strlen(buf))) {
1068 fprintf(stdout,
"^D\n");
1079 fprintf(stderr,
"KeyboardInterrupt\n");
1084 if (buf[strlen(buf)-1] !=
'\n') {
1087 fprintf(stderr,
"Expected end of line in repl input. Did you ^D early?\n");
1092 if (lineCapacity < lineCount + 1) {
1094 size_t old = lineCapacity;
1095 lineCapacity = GROW_CAPACITY(old);
1096 lines = GROW_ARRAY(
char *,lines,old,lineCapacity);
1099 int i = lineCount++;
1100 lines[i] = strdup(buf);
1102 size_t lineLength = strlen(lines[i]);
1103 totalData += lineLength;
1107 int countSpaces = 0;
1108 for (
size_t j = 0; j < lineLength; ++j) {
1109 if (lines[i][j] !=
' ' && lines[i][j] !=
'\n') {
1120 if (lineLength > 1 && lines[i][lineLength-2] ==
':') {
1122 blockWidth = countSpaces + 4;
1124 }
else if (lineLength > 1 && lines[i][lineLength-2] ==
'\\') {
1127 }
else if (inBlock && lineLength != 1) {
1130 totalData -= lineLength;
1134 blockWidth = countSpaces;
1136 }
else if (lineLength > 1 && lines[i][countSpaces] ==
'@') {
1138 blockWidth = countSpaces;
1143 if (isSpaces && !i) valid = 0;
1151 allData = malloc(totalData + 1);
1155 for (
size_t i = 0; i < lineCount; ++i) {
1156 if (valid) strcat(allData, lines[i]);
1159 rline_history_insert(strdup(lines[i]));
1165 FREE_ARRAY(
char *, lines, lineCapacity);
1169 if (!IS_NONE(result)) {
1172 const char * formatStr =
" \033[1;90m=> %s\033[0m\n";
1176 }
else if (type->
_tostr) {
1180 if (!IS_STRING(result)) {
1181 fprintf(stdout,
" \033[1;91m=> Unable to produce representation for value.\033[0m\n");
1183 fprintf(stdout, formatStr, AS_CSTRING(result));
1194 if (
vm.globalFlags & KRK_GLOBAL_CALLGRIND) {
1195 fclose(
vm.callgrindFile);
1196 vm.globalFlags &= ~(KRK_GLOBAL_CALLGRIND);
1202 "from callgrind import processFile\n"
1205 "processFile(filename, os.getpid(), ' '.join(kuroko.argv))",
"<callgrind>");
1210 if (IS_INTEGER(result))
return AS_INTEGER(result);
Structures and enums for bytecode chunks.
KrkCodeObject * krk_compile(const char *src, char *fileName)
Compile a source string to bytecode.
Exported methods for the source compiler.
Functions for debugging bytecode execution.
#define KRK_BREAKPOINT_ONCE
void krk_debug_disableSingleStep(void)
Disable single stepping in the current thread.
int krk_debug_examineBreakpoint(int breakIndex, KrkCodeObject **funcOut, size_t *offsetOut, int *flagsOut, int *enabledOut)
Retreive information on a breakpoint.
int krk_debug_enableBreakpoint(int breakpointId)
Enable a breakpoint.
void krk_debug_dumpTraceback(void)
Safely dump a traceback to stderr.
int krk_debug_removeBreakpoint(int breakpointId)
Remove a breakpoint from the breakpoint table.
int krk_debug_registerCallback(KrkDebugCallback hook)
Register a debugger callback.
int krk_debug_disableBreakpoint(int breakpointId)
Disable a breakpoint.
size_t krk_disassembleInstruction(FILE *f, KrkCodeObject *func, size_t offset)
Print a disassembly of a single opcode instruction.
int krk_debug_addBreakpointFileLine(KrkString *filename, size_t line, int flags)
Add a breakpoint to the given line of a file.
#define KRK_BREAKPOINT_REPEAT
#define KRK_BREAKPOINT_NORMAL
void krk_debug_dumpStack(FILE *f, KrkCallFrame *frame)
Print the elements on the stack.
KrkValue krk_runtimeError(KrkClass *type, const char *fmt,...)
Produce and raise an exception with a formatted message.
void krk_dumpTraceback(void)
If there is an active exception, print a traceback to stderr.
Top-level header with configuration macros.
Functions for dealing with garbage collection and memory allocation.
Definitions used by the token scanner.
KrkToken krk_scanToken(KrkScanner *)
Read the next token from the scanner.
KrkScanner krk_initScanner(const char *src)
Initialize the compiler to scan tokens from 'src'.
Represents a managed call state in a VM thread.
size_t krk_lineNumber(KrkChunk *chunk, size_t offset)
Obtain the line number for a byte offset into a bytecode chunk.
KrkObj * _tostr
__str__ Called to produce a string from an instance
KrkObj * _reprer
__repr__ Called to create a reproducible string representation of an instance
KrkCodeObject * function
The codeobject containing the bytecode run when this function is called.
KrkClosure * krk_newClosure(KrkCodeObject *function, KrkValue globals)
Create a new function object.
KrkChunk chunk
Bytecode data.
KrkString * name
Name of the function.
KrkInstance * krk_newInstance(KrkClass *_class)
Create a new instance of the given class.
KrkTable fields
Attributes table.
KrkValue krk_list_of(int argc, const KrkValue argv[], int hasKw)
Create a list object.
The most basic object type.
Immutable sequence of Unicode codepoints.
KrkString * krk_copyString(const char *chars, size_t length)
Obtain a string object representation of the given C string.
KrkString * krk_takeString(char *chars, size_t length)
Yield ownership of a C string to the GC and obtain a string object.
char * chars
UTF8 canonical data.
size_t length
String length in bytes.
One (key,value) pair in a table.
int krk_tableGet(KrkTable *table, KrkValue key, KrkValue *value)
Obtain the value associated with a key in a table.
void krk_attachNamedObject(KrkTable *table, const char name[], KrkObj *obj)
Attach an object to an attribute table.
void krk_attachNamedValue(KrkTable *table, const char name[], KrkValue obj)
Attach a value to an attribute table.
int krk_tableGet_fast(KrkTable *table, struct KrkString *str, KrkValue *value)
Obtain the value associated with a string key in a table.
A token from the scanner.
void krk_freeVM(void)
Release resources from the VM.
void krk_initVM(int flags)
Initialize the VM at program startup.
Stack reference or primative value.
void krk_printValue(FILE *f, KrkValue value)
Print a string representation of a value.
KrkClass * krk_getType(KrkValue value)
Get the class representing a value.
KrkValue krk_valueGetAttribute(KrkValue value, char *name)
Obtain a property of an object by name.
Inline flexible string array.
Utilities for creating native bindings.
#define krk_parseArgs(f, n,...)
Parse arguments to a function while accepting keyword arguments.
#define KRK_DOC(thing, text)
Attach documentation to a thing of various types.
Core API for the bytecode virtual machine.
int krk_importModule(KrkString *name, KrkString *runAs)
Load the dotted name name with the final element as runAs.
void krk_resetStack(void)
Reset the current thread's stack state to the top level.
KrkValue krk_callStack(int argCount)
Call a callable on the stack with argCount arguments.
#define vm
Convenience macro for namespacing.
KrkValue krk_callNativeOnStack(size_t argCount, const KrkValue *stackArgs, int hasKw, NativeFn native)
Call a native function using a reference to stack arguments safely.
KrkValue krk_pop(void)
Pop the top of the stack.
threadLocal KrkThreadState krk_currentThread
Thread-local VM state.
KrkValue krk_valueGetAttribute_default(KrkValue value, char *name, KrkValue defaultVal)
See krk_valueGetAttribute.
void krk_setMaximumRecursionDepth(size_t maxDepth)
Set the maximum recursion call depth.
void krk_swap(int distance)
Swap the top of the stack of the value distance slots down.
KrkValue krk_runfile(const char *fileName, char *fromFile)
Load and run a source file and return when execution completes.
KrkValue krk_dirObject(int argc, const KrkValue argv[], int hasKw)
Obtain a list of properties for an object.
void krk_push(KrkValue value)
Push a stack value.
KrkInstance * krk_startModule(const char *name)
Set up a new module object in the current thread.
KrkValue krk_callDirect(KrkObj *callable, int argCount)
Call a closure or native function with argCount arguments.
KrkValue krk_peek(int distance)
Peek down from the top of the stack.
KrkValue krk_interpret(const char *src, char *fromFile)
Compile and execute a source code input.