7 #define _DEFAULT_SOURCE
17 #include <toaru/rline.h>
20 #include "vendor/rline.h"
33 #define PROMPT_MAIN ">>> "
34 #define PROMPT_BLOCK " > "
36 static int enableRline = 1;
37 static int exitRepl = 0;
38 static int pasteEnabled = 0;
39 static int noColor = 0;
42 FUNCTION_TAKES_NONE();
48 int enabled = !pasteEnabled;
49 if (!
krk_parseArgs(
"|p",(
const char*[]){
"enabled"},&enabled))
return NONE_VAL();
50 pasteEnabled = enabled;
51 fprintf(stderr,
"Pasting is %s.\n", pasteEnabled ?
"enabled" :
"disabled");
55 static int doRead(
char * buf,
size_t bufSize) {
58 return rline(buf, bufSize);
61 return read(STDIN_FILENO, buf, bufSize);
64 static KrkValue readLine(
char * prompt,
int promptWidth,
char * syntaxHighlighter) {
69 rline_exit_string =
"";
70 rline_exp_set_prompts(prompt,
"", promptWidth, 0);
71 rline_exp_set_syntax(syntaxHighlighter);
72 rline_exp_set_tab_complete_func(NULL);
76 fprintf(stdout,
"%s", prompt);
84 ssize_t bytesRead = doRead(buf, 4096);
89 }
else if (bytesRead == 0 && !sb.length) {
93 pushStringBuilderStr(&sb, buf, bytesRead);
96 if (sb.length && sb.bytes[sb.length-1] ==
'\n') {
102 return finishStringBuilder(&sb);
105 discardStringBuilder(&sb);
115 KRK_Function(input) {
118 char * syntax = NULL;
120 if (!
krk_parseArgs(
"|siz", (
const char*[]){
"prompt",
"promptwidth",
"syntax"},
121 &prompt, &promptwidth, &syntax))
return NONE_VAL();
123 if (promptwidth == 0 && *prompt) {
124 promptwidth = strlen(prompt);
127 return readLine(prompt, promptwidth, syntax);
130 static void printResult(FILE * file,
KrkValue result) {
132 if (!krk_pushStringBuilderFormat(&sb, noColor ?
" => %R\n" :
" \033[1;90m=> %R\033[0m\n", result)) {
135 fwrite(sb.bytes,1,sb.length,file);
157 static char * syn_krk_keywords[] = {
158 "and",
"class",
"def",
"else",
"for",
"if",
"in",
"import",
"del",
159 "let",
"not",
"or",
"return",
"while",
"try",
"except",
"raise",
160 "continue",
"break",
"as",
"from",
"elif",
"lambda",
"with",
"is",
161 "pass",
"assert",
"yield",
"finally",
"async",
"await",
162 "True",
"False",
"None",
166 static void tab_complete_func(rline_context_t * c) {
171 char * tmp = malloc(c->offset + 1);
172 memcpy(tmp, c->buffer, c->offset);
173 tmp[c->offset] =
'\0';
181 }
while (space[count-1].type != TOKEN_EOF && space[count-1].type != TOKEN_ERROR);
191 if (space[count-base].type == TOKEN_DOT) {
195 }
else if (space[count-base].type >= TOKEN_IDENTIFIER && space[count-base].type <= TOKEN_WITH) {
204 if (space[count-n-1].type != TOKEN_DOT)
break;
206 if (n == count)
break;
207 if (space[count-n-1].type != TOKEN_IDENTIFIER)
break;
217 KrkValue next = findFromProperty(root, space[count-n]);
222 if (!isGlobal)
goto _cleanup;
225 krk_copyString(space[count-n].start,space[count-n].literalWidth), &next) || IS_NONE(next)) {
234 if (isGlobal && n < count && (space[count-n-1].type == TOKEN_IMPORT || space[count-n-1].type == TOKEN_FROM)) {
236 root = OBJECT_VAL(modules);
238 for (
size_t i = 0; i <
vm.modules.capacity; ++i) {
240 if (IS_KWARGS(entry->key))
continue;
246 int length = (space[count-base].type == TOKEN_DOT) ? 0 : (space[count-base].length);
247 isGlobal = isGlobal && (length != 0);
258 if (!IS_INSTANCE(dirList)) {
259 fprintf(stderr,
"\nInternal error while tab completting.\n");
263 for (
size_t i = 0; i < AS_LIST(dirList)->count; ++i) {
264 KrkString * s = AS_STRING(AS_LIST(dirList)->values[i]);
267 KrkValue thisValue = findFromProperty(root, asToken);
269 if (IS_CLOSURE(thisValue) || IS_BOUND_METHOD(thisValue) || IS_NATIVE(thisValue)) {
270 size_t allocSize = s->
length + 2;
271 char * tmp = malloc(allocSize);
272 size_t len = snprintf(tmp, allocSize,
"%s(", s->
chars);
281 if (length && (
int)s->
length < length)
continue;
285 for (
int i = 0; i < matchCount; ++i) {
286 if (!strcmp(matches[i], s->
chars)) {
293 if (!memcmp(s->
chars, space[count-base].start, length)) {
294 matches[matchCount] = s->
chars;
296 if (matchCount == 255)
goto _toomany;
305 root = OBJECT_VAL(
vm.builtins);
307 }
else if (isGlobal && AS_OBJECT(root) == (
KrkObj*)
vm.builtins) {
309 root = OBJECT_VAL(fakeKeywordsObject);
311 for (
char ** keyword = syn_krk_keywords; *keyword; keyword++) {
322 if (matchCount == 1) {
324 rline_insert(c, matches[0] + length);
325 rline_place_cursor();
326 }
else if (matchCount) {
330 char m = matches[0][j];
333 for (
int i = 1; i < matchCount; ++i) {
334 if (matches[i][j] != m) {
346 for (
int i = 0; i < matchCount; ++i) {
347 if ((
int)strlen(matches[i]) > maxWidth) maxWidth = strlen(matches[i]);
350 int colsPerLine = rline_terminal_width / (maxWidth + 2);
351 fprintf(stderr,
"\n");
353 for (
int i = 0; i < matchCount; ++i) {
354 fprintf(stderr,
"%-*s ", maxWidth, matches[i]);
356 if (column >= colsPerLine) {
357 fprintf(stderr,
"\n");
361 if (column != 0) fprintf(stderr,
"\n");
364 for (
int i = length; i < j; ++i) {
365 char tmp[2] = {matches[0][i],
'\0'};
366 rline_insert(c, tmp);
380 #ifndef KRK_DISABLE_DEBUG
381 static char * lastDebugCommand = NULL;
385 fprintf(stderr,
"At offset 0x%04lx of function '%s' from '%s' on line %lu:\n",
401 char buf[4096] = {0};
404 rline_exit_string=
"";
405 rline_exp_set_prompts(
"(dbg) ",
"", 6, 0);
406 rline_exp_set_syntax(
"krk-dbg");
407 rline_exp_set_tab_complete_func(NULL);
408 if (rline(buf, 4096) == 0)
goto _dbgQuit;
411 fprintf(stderr,
"(dbg) ");
413 char * out = fgets(buf, 4096, stdin);
414 if (!out || !strlen(buf)) {
415 fprintf(stdout,
"^D\n");
422 char * nl = strstr(buf,
"\n");
426 if (lastDebugCommand) {
427 strcpy(buf, lastDebugCommand);
434 rline_history_insert(strdup(buf));
438 if (lastDebugCommand) free(lastDebugCommand);
439 lastDebugCommand = strdup(buf);
444 char * sp = strstr(buf,
" ");
450 if (!strcmp(buf,
"c") || !strcmp(buf,
"continue")) {
451 return KRK_DEBUGGER_CONTINUE;
452 }
else if (!strcmp(buf,
"s") || !strcmp(buf,
"step")) {
453 return KRK_DEBUGGER_STEP;
454 }
else if (!strcmp(buf,
"abort")) {
455 return KRK_DEBUGGER_ABORT;
456 }
else if (!strcmp(buf,
"q") || !strcmp(buf,
"quit")) {
457 return KRK_DEBUGGER_QUIT;
458 }
else if (!strcmp(buf,
"bt") || !strcmp(buf,
"backtrace")) {
460 }
else if (!strcmp(buf,
"p") || !strcmp(buf,
"print")) {
462 fprintf(stderr,
"print requires an argument\n");
489 }
else if (!strcmp(buf,
"break") || !strcmp(buf,
"b")) {
490 char * filename = arg;
492 fprintf(stderr,
"usage: break FILE LINE [type]\n");
496 char * lineno = strstr(filename,
" ");
498 fprintf(stderr,
"usage: break FILE LINE [type]\n");
508 char * type = strstr(lineno,
" ");
510 *type =
'\0'; type++;
511 if (!strcmp(type,
"repeat") || !strcmp(type,
"r")) {
513 }
else if (!strcmp(type,
"once") || !strcmp(type,
"o")) {
516 fprintf(stderr,
"Unrecognized breakpoint type: %s\n", type);
521 int lineInt = atoi(lineno);
525 fprintf(stderr,
"Sorry, couldn't add breakpoint.\n");
527 fprintf(stderr,
"Breakpoint %d enabled.\n", result);
530 }
else if (!strcmp(buf,
"i") || !strcmp(buf,
"info")) {
532 fprintf(stderr,
" info breakpoints - Show breakpoints.\n");
536 if (!strcmp(arg,
"breakpoints")) {
544 if (result == -1)
break;
545 if (result == -2)
continue;
547 fprintf(stderr,
"%-4d in %s+%d %s %s\n",
554 enabled ?
"enabled" :
"disabled");
559 fprintf(stderr,
"Unrecognized info object: %s\n", arg);
562 }
else if (!strcmp(buf,
"e") || !strcmp(buf,
"enable")) {
564 fprintf(stderr,
"enable requires an argument\n");
568 int breakIndex = atoi(arg);
571 fprintf(stderr,
"Invalid breakpoint handle.\n");
573 fprintf(stderr,
"Breakpoint %d enabled.\n", breakIndex);
575 }
else if (!strcmp(buf,
"d") || !strcmp(buf,
"disable")) {
577 fprintf(stderr,
"disable requires an argument\n");
581 int breakIndex = atoi(arg);
584 fprintf(stderr,
"Invalid breakpoint handle.\n");
586 fprintf(stderr,
"Breakpoint %d disabled.\n", breakIndex);
588 }
else if (!strcmp(buf,
"r") || !strcmp(buf,
"remove")) {
590 fprintf(stderr,
"remove requires an argument\n");
594 int breakIndex = atoi(arg);
597 fprintf(stderr,
"Invalid breakpoint handle.\n");
599 fprintf(stderr,
"Breakpoint %d removed.\n", breakIndex);
601 }
else if (!strcmp(buf,
"help")) {
603 "Kuroko Interactive Debugger\n"
604 " c continue - Continue until the next breakpoint.\n"
605 " s step - Execute this instruction and return to the debugger.\n"
606 " bt backtrace - Print a backtrace.\n"
607 " q quit - Exit the interpreter.\n"
608 " abort - Abort the interpreter (may create a core dump).\n"
609 " b break ... - Set a breakpoint.\n"
610 " e enable N - Enable breakpoint 'N'.\n"
611 " d disable N - Disable breakpoint 'N'.\n"
612 " r remove N - Remove breakpoint 'N'.\n"
613 " i info ... - See information about breakpoints.\n"
615 "Empty input lines will repeat the last command.\n"
618 fprintf(stderr,
"Unrecognized command: %s\n", buf);
623 return KRK_DEBUGGER_CONTINUE;
625 return KRK_DEBUGGER_QUIT;
629 static void handleSigint(
int sigNum) {
635 static void handleSigtrap(
int sigNum) {
640 static void bindSignalHandlers(
void) {
642 struct sigaction sigIntAction;
643 sigIntAction.sa_handler = handleSigint;
644 sigemptyset(&sigIntAction.sa_mask);
645 sigIntAction.sa_flags = 0;
651 struct sigaction sigTrapAction;
652 sigTrapAction.sa_handler = handleSigtrap;
653 sigemptyset(&sigTrapAction.sa_mask);
654 sigTrapAction.sa_flags = 0;
660 signal(SIGINT, handleSigint);
664 static void findInterpreter(
char * argv[]) {
666 vm.binpath = strdup(_pgmptr);
670 char * binpath = realpath(
"/proc/self/exe", NULL);
671 if (!binpath || (access(binpath, X_OK) != 0)) {
676 if (strchr(argv[0],
'/')) {
677 binpath = realpath(argv[0], NULL);
680 char * p = getenv(
"PATH");
682 char * _path = strdup(p);
685 char * next = strchr(path,
':');
686 if (next) *next++ =
'\0';
688 snprintf(tmp, 4096,
"%s/%s", path, argv[0]);
689 if (access(tmp, X_OK) == 0) {
690 binpath = strdup(tmp);
699 vm.binpath = binpath;
704 static int runString(
char * argv[],
int flags,
char *
string) {
705 findInterpreter(argv);
714 static int compileFile(
char * argv[],
int flags,
char * fileName) {
715 findInterpreter(argv);
719 FILE * f = fopen(fileName,
"r");
721 fprintf(stderr,
"%s: could not read file '%s': %s\n", argv[0], fileName, strerror(errno));
726 fseek(f, 0, SEEK_END);
727 size_t size = ftell(f);
728 fseek(f, 0, SEEK_SET);
729 char * buf = malloc(size+1);
730 if (fread(buf, 1, size, f) == 0)
return 2;
754 int main(
int argc,
char * argv[]) {
756 SetConsoleOutputCP(65001);
759 char * runCmd = NULL;
761 int moduleAsMain = 0;
762 int inspectAfter = 0;
765 while ((opt = getopt(argc, argv,
"+:c:C:dgGim:rR:tTMSV-:")) != -1) {
772 flags |= KRK_THREAD_ENABLE_DISASSEMBLY;
776 flags |= KRK_GLOBAL_ENABLE_STRESS_GC;
779 flags |= KRK_GLOBAL_REPORT_GC_COLLECTS;
782 flags |= KRK_THREAD_SINGLE_STEP;
786 flags |= KRK_THREAD_ENABLE_TRACING;
799 maxDepth = atoi(optarg);
802 return runString(argv,0,
"import kuroko; print(kuroko.module_paths)\n");
804 return runString(argv,0,
"import kuroko; print('Kuroko',kuroko.version)\n");
806 return compileFile(argv,flags,optarg);
808 fprintf(stderr,
"%s: option '%c' requires an argument\n", argv[0], optopt);
812 fprintf(stderr,
"%s: unrecognized option '%c'\n", argv[0], optopt);
815 optarg = argv[optind]+2;
818 if (!strcmp(optarg,
"version")) {
819 return runString(argv,0,
"import kuroko; print('Kuroko',kuroko.version)\n");
820 }
else if (!strcmp(optarg,
"help")) {
821 #ifndef KRK_NO_DOCUMENTATION
822 fprintf(stderr,
"usage: %s [flags] [FILE...]\n"
824 "Interpreter options:\n"
825 " -d Debug output from the bytecode compiler.\n"
826 " -g Collect garbage on every allocation.\n"
827 " -G Report GC collections.\n"
828 " -i Enter repl after a running -c, -m, or FILE.\n"
829 " -m mod Run a module as a script.\n"
830 " -r Disable complex line editing in the REPL.\n"
831 " -R depth Set maximum recursion depth.\n"
832 " -t Disassemble instructions as they are exceuted.\n"
833 " -C file Compile 'file', but do not execute it.\n"
834 " -M Print the default module import paths.\n"
835 " -S Enable single-step debugging.\n"
836 " -V Print version information.\n"
838 " --version Print version information.\n"
839 " --help Show this help text.\n"
841 "If no files are provided, the interactive REPL will run.\n",
846 fprintf(stderr,
"%s: unrecognized option '--%s'\n",
854 findInterpreter(argv);
857 if (maxDepth != -1) {
861 #ifndef KRK_DISABLE_DEBUG
867 for (
int arg = optind; arg < argc; ++arg) {
874 for (
int arg = optind; arg < argc + (optind == argc); ++arg)
krk_pop();
877 bindSignalHandlers();
879 #ifdef KRK_BUNDLE_LIBS
881 #define BUNDLED(name) do { \
882 extern KrkValue krk_module_onload_ ## name (KrkString*); \
883 KrkValue moduleOut = krk_module_onload_ ## name (NULL); \
884 krk_attachNamedValue(&vm.modules, # name, moduleOut); \
885 krk_attachNamedObject(&AS_INSTANCE(moduleOut)->fields, "__name__", (KrkObj*)krk_copyString(#name, sizeof(#name)-1)); \
886 krk_attachNamedValue(&AS_INSTANCE(moduleOut)->fields, "__file__", NONE_VAL()); \
894 char * env_KUROKOPATH = getenv(
"KUROKOPATH");
896 if (env_KUROKOPATH) {
911 extern FUNC_SIG(list,extend);
922 char * env_NO_COLOR = getenv(
"NO_COLOR");
924 if (env_NO_COLOR && *env_NO_COLOR) noColor = 1;
930 KRK_DOC(BIND_FUNC(
vm.builtins,input),
"@brief Read a line of input.\n"
931 "@arguments prompt='',promptwidth=0,syntax=None\n\n"
932 "Read a line of input from @c stdin. If the @c rline library is available, "
933 "it will be used to gather input. Input reading stops on end-of file or when "
934 "a read ends with a line feed, which will be removed from the returned string. "
935 "If a prompt is provided, it will be printed without a line feed before requesting "
936 "input. If @c rline is available, the prompt will be passed to the library as the "
937 "left-hand prompt string. If not provided, @p promptwidth will default to the width "
938 "of @p prompt in codepoints; if you are providing a prompt with escape characters or "
939 "characters with multi-column East-Asian Character Width be sure to pass a value "
940 "for @p promptwidth that reflects the display width of your prompt. "
941 "If provided, @p syntax specifies the name of an @c rline syntax module to "
942 "provide color highlighting of the input line.");
945 int out = !
krk_importModule(AS_STRING(AS_LIST(argList)->values[0]), S(
"__main__"));
950 if (!inspectAfter)
return out;
954 }
else if (optind != argc) {
971 if ((!moduleAsMain && !runCmd && optind == argc) || inspectAfter) {
973 KRK_DOC(BIND_FUNC(
vm.builtins,exit),
"@brief Exit the interactive repl.\n\n"
974 "Only available from the interactive interpreter; exits the repl.");
975 KRK_DOC(BIND_FUNC(
vm.builtins,paste),
"@brief Toggle paste mode.\n"
976 "@arguments enabled=None\n\n"
977 "Toggles paste-safe mode, disabling automatic indentation in the repl. "
978 "If @p enabled is specified, the mode can be directly specified, otherwise "
979 "it will be set to the opposite of the current mode. The new mode will be "
980 "printed to stderr.");
992 KrkValue version, buildenv, builddate;
997 fprintf(stdout,
"Kuroko %s (%s) with %s\n",
998 AS_CSTRING(version), AS_CSTRING(builddate), AS_CSTRING(buildenv));
1001 fprintf(stdout,
"Type `help` for guidance, `paste()` to toggle automatic indentation, `license` for copyright information.\n");
1004 size_t lineCapacity = 8;
1005 size_t lineCount = 0;
1006 char ** lines = KRK_ALLOCATE(
char *, lineCapacity);
1007 size_t totalData = 0;
1009 char * allData = NULL;
1015 rline_exp_set_prompts(PROMPT_MAIN,
"", 4, 0);
1017 rline_exit_string=
"";
1019 rline_exp_set_syntax(
"krk");
1021 rline_exp_set_tab_complete_func(tab_complete_func);
1026 char buf[4096] = {0};
1032 rline_exp_set_prompts(PROMPT_BLOCK,
"", 4, 0);
1034 if (!pasteEnabled) {
1035 rline_preload = malloc(blockWidth + 1);
1036 for (
int i = 0; i < blockWidth; ++i) {
1037 rline_preload[i] =
' ';
1039 rline_preload[blockWidth] =
'\0';
1047 fprintf(stdout,
"%s", inBlock ? PROMPT_BLOCK : PROMPT_MAIN);
1054 if (rline(buf, 4096) == 0) {
1061 char * out = fgets(buf, 4096, stdin);
1063 fprintf(stdout,
"\n");
1064 }
else if ((!out || !strlen(buf))) {
1065 fprintf(stdout,
"^D\n");
1076 fprintf(stderr,
"KeyboardInterrupt\n");
1081 if (buf[strlen(buf)-1] !=
'\n') {
1084 fprintf(stderr,
"Expected end of line in repl input. Did you ^D early?\n");
1089 if (lineCapacity < lineCount + 1) {
1091 size_t old = lineCapacity;
1092 lineCapacity = KRK_GROW_CAPACITY(old);
1093 lines = KRK_GROW_ARRAY(
char *,lines,old,lineCapacity);
1096 int i = lineCount++;
1097 lines[i] = strdup(buf);
1099 size_t lineLength = strlen(lines[i]);
1100 totalData += lineLength;
1104 int countSpaces = 0;
1105 for (
size_t j = 0; j < lineLength; ++j) {
1106 if (lines[i][j] !=
' ' && lines[i][j] !=
'\n') {
1117 if (lineLength > 1 && lines[i][lineLength-2] ==
':') {
1119 blockWidth = countSpaces + 4;
1121 }
else if (lineLength > 1 && lines[i][lineLength-2] ==
'\\') {
1124 }
else if (inBlock && lineLength != 1) {
1127 totalData -= lineLength;
1131 blockWidth = countSpaces;
1133 }
else if (lineLength > 1 && lines[i][countSpaces] ==
'@') {
1135 blockWidth = countSpaces;
1140 if (isSpaces && !i) valid = 0;
1148 allData = malloc(totalData + 1);
1152 for (
size_t i = 0; i < lineCount; ++i) {
1153 if (valid) strcat(allData, lines[i]);
1156 rline_history_insert(strdup(lines[i]));
1162 KRK_FREE_ARRAY(
char *, lines, lineCapacity);
1166 if (!IS_NONE(result)) {
1168 printResult(stdout, result);
1180 if (IS_INTEGER(result))
return AS_INTEGER(result);
Structures and enums for bytecode chunks.
KrkCodeObject * krk_compile(const char *src, const 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.
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.
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.
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.
KrkValue krk_discardStringBuilder(struct StringBuilder *sb)
Discard the contents of a string builder.
#define KRK_DOC(thing, text)
Attach documentation to a thing of various types.
Core API for the bytecode virtual machine.
krk_threadLocal KrkThreadState krk_currentThread
Thread-local VM state.
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.
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_interpret(const char *src, const char *fromFile)
Compile and execute a source code input.
KrkValue krk_dirObject(int argc, const KrkValue argv[], int hasKw)
Obtain a list of properties for an object.
KrkValue krk_runfile(const char *fileName, const char *fromFile)
Load and run a source file and return when execution completes.
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_peek(int distance)
Peek down from the top of the stack.