kuroko: Update with upstream
This commit is contained in:
parent
620cfc69d2
commit
9df6e63dbf
141
apps/bim.c
141
apps/bim.c
@ -14,15 +14,16 @@
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#include "bim-core.h"
|
||||
#define ENABLE_THREADING
|
||||
#include "bim.h"
|
||||
#ifdef __toaru__
|
||||
#include <kuroko.h>
|
||||
#include "vm.h"
|
||||
#include "debug.h"
|
||||
#else
|
||||
#include "kuroko/src/kuroko.h"
|
||||
#include "kuroko/src/vm.h"
|
||||
#include "kuroko/src/debug.h"
|
||||
#include <kuroko/kuroko.h>
|
||||
#include <kuroko/vm.h>
|
||||
#include <kuroko/debug.h>
|
||||
#endif
|
||||
|
||||
global_config_t global_config = {
|
||||
@ -712,24 +713,7 @@ _done:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close a buffer
|
||||
*/
|
||||
buffer_t * buffer_close(buffer_t * buf) {
|
||||
int i;
|
||||
|
||||
/* Locate the buffer in the buffer list */
|
||||
for (i = 0; i < buffers_len; i++) {
|
||||
if (buf == buffers[i])
|
||||
break;
|
||||
}
|
||||
|
||||
/* This buffer doesn't exist? */
|
||||
if (i == buffers_len) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Cancel any background tasks for this env */
|
||||
void cancel_background_tasks(buffer_t * buf) {
|
||||
background_task_t * t = global_config.background_task;
|
||||
background_task_t * last = NULL;
|
||||
while (t) {
|
||||
@ -750,6 +734,27 @@ buffer_t * buffer_close(buffer_t * buf) {
|
||||
t = t->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Close a buffer
|
||||
*/
|
||||
buffer_t * buffer_close(buffer_t * buf) {
|
||||
int i;
|
||||
|
||||
/* Locate the buffer in the buffer list */
|
||||
for (i = 0; i < buffers_len; i++) {
|
||||
if (buf == buffers[i])
|
||||
break;
|
||||
}
|
||||
|
||||
/* This buffer doesn't exist? */
|
||||
if (i == buffers_len) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Cancel any background tasks for this env */
|
||||
cancel_background_tasks(buf);
|
||||
|
||||
update_biminfo(buf, 0);
|
||||
|
||||
@ -909,6 +914,14 @@ int syntax_space = 0;
|
||||
struct syntax_definition * syntaxes = NULL;
|
||||
|
||||
void add_syntax(struct syntax_definition def) {
|
||||
/* See if a name match already exists for this def. */
|
||||
for (struct syntax_definition * s = syntaxes; syntaxes && s->name; ++s) {
|
||||
if (!strcmp(def.name,s->name)) {
|
||||
*s = def;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (syntax_space == 0) {
|
||||
syntax_space = 4;
|
||||
syntaxes = calloc(sizeof(struct syntax_definition), syntax_space);
|
||||
@ -921,6 +934,8 @@ void add_syntax(struct syntax_definition def) {
|
||||
syntax_count++;
|
||||
}
|
||||
|
||||
void redraw_all(void);
|
||||
|
||||
/**
|
||||
* Calculate syntax highlighting for the given line, and lines after
|
||||
* if their initial syntax state has changed by this recalculation.
|
||||
@ -958,21 +973,15 @@ void recalculate_syntax(line_t * line, int line_no) {
|
||||
krk_push(OBJECT_VAL(s));
|
||||
KrkValue result = krk_callSimple(OBJECT_VAL(env->syntax->krkFunc), 1, 0);
|
||||
krk_currentThread.stackTop = krk_currentThread.stack + before;
|
||||
if (IS_NONE(result) && (krk_currentThread.flags & KRK_HAS_EXCEPTION)) {
|
||||
if (IS_NONE(result) && (krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION)) {
|
||||
render_error("Exception occurred in plugin: %s", AS_INSTANCE(krk_currentThread.currentException)->_class->name->chars);
|
||||
render_commandline_message("\n");
|
||||
krk_dumpTraceback();
|
||||
fprintf(stderr,"\n\nThis syntax highlighter will be disabled in this environment.\n\n");
|
||||
int key = 0;
|
||||
while ((key = bim_getkey(DEFAULT_KEY_WAIT)) == KEY_TIMEOUT);
|
||||
env->syntax = NULL;
|
||||
return;
|
||||
goto _syntaxError;
|
||||
} else if (!IS_NONE(result) && !IS_INTEGER(result)) {
|
||||
fprintf(stderr, "Instead of an integer, got %s\n", krk_typeName(result));
|
||||
fprintf(stderr,"\n\nThis syntax highlighter will be disabled in this environment.\n\n");
|
||||
int key = 0;
|
||||
while ((key = bim_getkey(DEFAULT_KEY_WAIT)) == KEY_TIMEOUT);
|
||||
env->syntax = NULL;
|
||||
return;
|
||||
render_error("Instead of an integer, got %s", krk_typeName(result));
|
||||
render_commandline_message("\n");
|
||||
goto _syntaxError;
|
||||
}
|
||||
s->state.state = IS_NONE(result) ? -1 : AS_INTEGER(result);
|
||||
|
||||
@ -996,6 +1005,14 @@ void recalculate_syntax(line_t * line, int line_no) {
|
||||
_next:
|
||||
(void)0;
|
||||
}
|
||||
|
||||
_syntaxError:
|
||||
krk_resetStack();
|
||||
fprintf(stderr,"This syntax highlighter will be disabled in this environment.");
|
||||
env->syntax = NULL;
|
||||
cancel_background_tasks(env);
|
||||
pause_for_key();
|
||||
redraw_all();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -3686,8 +3703,6 @@ void run_onload(buffer_t * env) {
|
||||
static void render_syntax_async(background_task_t * task) {
|
||||
buffer_t * old_env = env;
|
||||
env = task->env;
|
||||
struct syntax_definition * old_syn = env->syntax;
|
||||
env->syntax = task->_private_p;
|
||||
int line_no = task->_private_i;
|
||||
|
||||
if (env->line_count && line_no < env->line_count) {
|
||||
@ -3699,8 +3714,6 @@ static void render_syntax_async(background_task_t * task) {
|
||||
redraw_line(line_no);
|
||||
}
|
||||
}
|
||||
|
||||
env->syntax = old_syn;
|
||||
env = old_env;
|
||||
}
|
||||
|
||||
@ -3717,7 +3730,6 @@ static void schedule_complete_recalc(void) {
|
||||
background_task_t * task = malloc(sizeof(background_task_t));
|
||||
task->env = env;
|
||||
task->_private_i = i;
|
||||
task->_private_p = env->syntax;
|
||||
task->func = render_syntax_async;
|
||||
task->next = NULL;
|
||||
if (global_config.tail_task) {
|
||||
@ -5480,7 +5492,7 @@ BIM_COMMAND(theme,"theme","Set color theme") {
|
||||
ptrdiff_t before = krk_currentThread.stackTop - krk_currentThread.stack;
|
||||
KrkValue result = krk_callSimple(OBJECT_VAL(d->callable), 0, 0);
|
||||
krk_currentThread.stackTop = krk_currentThread.stack + before;
|
||||
if (IS_NONE(result) && (krk_currentThread.flags & KRK_HAS_EXCEPTION)) {
|
||||
if (IS_NONE(result) && (krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION)) {
|
||||
render_error("Exception occurred in theme: %s", AS_INSTANCE(krk_currentThread.currentException)->_class->name->chars);
|
||||
krk_dumpTraceback();
|
||||
int key = 0;
|
||||
@ -6610,7 +6622,12 @@ void find_match_backwards(int from_line, int from_col, int * out_line, int * out
|
||||
void rehighlight_search(line_t * line) {
|
||||
if (!global_config.search) return;
|
||||
int j = 0;
|
||||
while (j < line->actual) {
|
||||
line->text[j].flags &= ~(FLAG_SEARCH);
|
||||
j++;
|
||||
}
|
||||
int ignorecase = smart_case(global_config.search);
|
||||
j = 0;
|
||||
while (j < line->actual) {
|
||||
int matchlen = 0;
|
||||
if (subsearch_matches(line, j, global_config.search, ignorecase, &matchlen)) {
|
||||
@ -9932,7 +9949,7 @@ int process_krk_command(const char * cmd, KrkValue * outVal) {
|
||||
* get printed by the interpreter and we can't catch it here. */
|
||||
krk_currentThread.frames[0].outSlots = 1;
|
||||
/* Call the interpreter */
|
||||
KrkValue out = krk_interpret(cmd,0,"<bim>","<bim>");
|
||||
KrkValue out = krk_interpret(cmd,"<bim>");
|
||||
/* If the user typed just a command name, try to execute it. */
|
||||
if (krk_isInstanceOf(out,CommandDef)) {
|
||||
krk_push(out);
|
||||
@ -9942,7 +9959,7 @@ int process_krk_command(const char * cmd, KrkValue * outVal) {
|
||||
int retval = (IS_INTEGER(out)) ? AS_INTEGER(out) : 0;
|
||||
int hadOutput = 0;
|
||||
/* If we got an exception during execution, print it now */
|
||||
if (krk_currentThread.flags & KRK_HAS_EXCEPTION) {
|
||||
if (krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION) {
|
||||
if (krk_isInstanceOf(krk_currentThread.currentException, vm.exceptions->syntaxError)) {
|
||||
}
|
||||
set_fg_color(COLOR_RED);
|
||||
@ -10028,7 +10045,7 @@ BIM_COMMAND(runkrk,"runkrk", "Run a kuroko script") {
|
||||
/* In case we're running in a weird context? */
|
||||
int previousExitFrame = krk_currentThread.exitOnFrame;
|
||||
krk_currentThread.exitOnFrame = krk_currentThread.frameCount;
|
||||
krk_runfile(argv[1],1,"<bim>",argv[1]);
|
||||
krk_runfile(argv[1],argv[1]);
|
||||
krk_currentThread.exitOnFrame = previousExitFrame;
|
||||
|
||||
redraw_all();
|
||||
@ -10175,7 +10192,7 @@ static KrkValue krk_bim_register_syntax(int argc, KrkValue argv[], int hasKw) {
|
||||
if (!IS_STRING(name))
|
||||
return krk_runtimeError(vm.exceptions->typeError, "%s.name must be str", AS_CLASS(argv[0])->name->chars);
|
||||
if (!IS_TUPLE(extensions))
|
||||
return krk_runtimeError(vm.exceptions->typeError, "%s.extensions must by tuple<str>", AS_CLASS(argv[0])->name->chars);
|
||||
return krk_runtimeError(vm.exceptions->typeError, "%s.extensions must be tuple<str>", AS_CLASS(argv[0])->name->chars);
|
||||
if (!IS_BOOLEAN(spaces))
|
||||
return krk_runtimeError(vm.exceptions->typeError, "%s.spaces must be bool", AS_CLASS(argv[0])->name->chars);
|
||||
if (!IS_CLOSURE(calculate))
|
||||
@ -10528,7 +10545,7 @@ void import_directory(char * dirName) {
|
||||
"if '%s%s' not in kuroko.module_paths:\n"
|
||||
" kuroko.module_paths.insert(0,'%s%s')\n",
|
||||
dirpath, extra, dirpath, extra);
|
||||
krk_interpret(tmp,1,"<bim>","<bim>");
|
||||
krk_interpret(tmp,"<bim>");
|
||||
}
|
||||
|
||||
if (dirpath) free(dirpath);
|
||||
@ -10538,7 +10555,7 @@ void import_directory(char * dirName) {
|
||||
char * tmp = malloc(strlen(dirName) + 1 + strlen(ent->d_name) + 1 + 7);
|
||||
snprintf(tmp, strlen(dirName) + 1 + strlen(ent->d_name) + 1 + 7, "import %s.%s", dirName, ent->d_name);
|
||||
tmp[strlen(tmp)-4] = '\0';
|
||||
krk_interpret(tmp,1,"<bim>",ent->d_name);
|
||||
krk_interpret(tmp,ent->d_name);
|
||||
free(tmp);
|
||||
}
|
||||
ent = readdir(dirp);
|
||||
@ -10576,6 +10593,33 @@ static void findBim(char * argv[]) {
|
||||
} /* Else, give up at this point and just don't attach it at all. */
|
||||
}
|
||||
|
||||
BIM_COMMAND(reload,"reload","Reloads all the Kuroko stuff.") {
|
||||
/* Unload everything syntax-y */
|
||||
KrkValue result = krk_interpret(
|
||||
"if True:\n"
|
||||
" import kuroko\n"
|
||||
" for mod in kuroko.modules():\n"
|
||||
" if mod.startswith('syntax.') or mod.startswith('themes.'):\n"
|
||||
" kuroko.unload(mod)\n", "<bim>");
|
||||
|
||||
if (IS_NONE(result) && (krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION)) {
|
||||
krk_dumpTraceback();
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Reload everything */
|
||||
krk_resetStack();
|
||||
krk_startModule("<bim-syntax>");
|
||||
import_directory("syntax");
|
||||
krk_startModule("<bim-themes>");
|
||||
import_directory("themes");
|
||||
krk_startModule("<bim-repl>");
|
||||
/* Re-run the RC file */
|
||||
load_bimrc();
|
||||
krk_resetStack();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run global initialization tasks
|
||||
*/
|
||||
@ -10614,9 +10658,7 @@ void initialize(void) {
|
||||
global_config.tab_indicator = strdup(">");
|
||||
global_config.space_indicator = strdup("-");
|
||||
|
||||
fprintf(stderr, "init vm\n");
|
||||
krk_initVM(0); /* no debug flags */
|
||||
fprintf(stderr, "done\n");
|
||||
|
||||
KrkInstance * bimModule = krk_newInstance(vm.baseClasses->moduleClass);
|
||||
krk_attachNamedObject(&vm.modules, "bim", (KrkObj*)bimModule);
|
||||
@ -10708,6 +10750,9 @@ void initialize(void) {
|
||||
load_bimrc();
|
||||
krk_resetStack();
|
||||
|
||||
/* Disable default traceback printing */
|
||||
vm.globalFlags |= KRK_GLOBAL_CLEAN_OUTPUT;
|
||||
|
||||
/* Initialize space for buffers */
|
||||
buffers_avail = 4;
|
||||
buffers = malloc(sizeof(buffer_t *) * buffers_avail);
|
||||
|
@ -22,6 +22,11 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/stat.h>
|
||||
#ifdef __toaru__
|
||||
#include "vm.h"
|
||||
#else
|
||||
#include <kuroko/vm.h>
|
||||
#endif
|
||||
|
||||
#ifdef __DATE__
|
||||
# define BIM_BUILD_DATE " built " __DATE__ " at " __TIME__
|
||||
@ -35,7 +40,7 @@
|
||||
# define TAG "-alpha"
|
||||
#endif
|
||||
|
||||
#define BIM_VERSION "3.0.0" TAG
|
||||
#define BIM_VERSION "2.99.0" TAG
|
||||
#define BIM_COPYRIGHT "Copyright 2012-2021 K. Lange <\033[3mklange@toaruos.org\033[23m>"
|
||||
|
||||
#define BLOCK_SIZE 4096
|
326
apps/kuroko.c
326
apps/kuroko.c
@ -28,6 +28,7 @@
|
||||
#include "vm.h"
|
||||
#include "memory.h"
|
||||
#include "scanner.h"
|
||||
#include "compiler.h"
|
||||
|
||||
#define PROMPT_MAIN ">>> "
|
||||
#define PROMPT_BLOCK " > "
|
||||
@ -166,9 +167,10 @@ static void tab_complete_func(rline_context_t * c) {
|
||||
krk_push(thisValue);
|
||||
if (IS_CLOSURE(thisValue) || IS_BOUND_METHOD(thisValue) ||
|
||||
(IS_NATIVE(thisValue) && ((KrkNative*)AS_OBJECT(thisValue))->isMethod != 2)) {
|
||||
char * tmp = malloc(s->length + 2);
|
||||
sprintf(tmp, "%s(", s->chars);
|
||||
s = krk_takeString(tmp, strlen(tmp));
|
||||
size_t allocSize = s->length + 2;
|
||||
char * tmp = malloc(allocSize);
|
||||
size_t len = snprintf(tmp, allocSize, "%s(", s->chars);
|
||||
s = krk_takeString(tmp, len);
|
||||
krk_pop();
|
||||
krk_push(OBJECT_VAL(s));
|
||||
}
|
||||
@ -274,9 +276,253 @@ _cleanup:
|
||||
}
|
||||
#endif
|
||||
|
||||
static char * lastDebugCommand = NULL;
|
||||
static int debuggerHook(KrkCallFrame * frame) {
|
||||
|
||||
/* File information */
|
||||
fprintf(stderr, "At offset 0x%04lx of function '%s' from '%s' on line %lu:\n",
|
||||
(unsigned long)(frame->ip - frame->closure->function->chunk.code),
|
||||
frame->closure->function->name->chars,
|
||||
frame->closure->function->chunk.filename->chars,
|
||||
(unsigned long)krk_lineNumber(&frame->closure->function->chunk,
|
||||
(unsigned long)(frame->ip - frame->closure->function->chunk.code)));
|
||||
|
||||
/* Opcode trace */
|
||||
krk_disassembleInstruction(
|
||||
stderr,
|
||||
frame->closure->function,
|
||||
(size_t)(frame->ip - frame->closure->function->chunk.code));
|
||||
|
||||
krk_debug_dumpStack(stderr, frame);
|
||||
|
||||
while (1) {
|
||||
char buf[4096] = {0};
|
||||
#ifndef NO_RLINE
|
||||
if (enableRline) {
|
||||
rline_exit_string="";
|
||||
rline_exp_set_prompts("(dbg) ", "", 6, 0);
|
||||
rline_exp_set_syntax("krk-dbg");
|
||||
rline_exp_set_tab_complete_func(NULL);
|
||||
if (rline(buf, 4096) == 0) goto _dbgQuit;
|
||||
} else {
|
||||
#endif
|
||||
fprintf(stderr, "(dbg) ");
|
||||
fflush(stderr);
|
||||
char * out = fgets(buf, 4096, stdin);
|
||||
if (!out || !strlen(buf)) {
|
||||
fprintf(stdout, "^D\n");
|
||||
goto _dbgQuit;
|
||||
}
|
||||
#ifndef NO_RLINE
|
||||
}
|
||||
#endif
|
||||
|
||||
char * nl = strstr(buf,"\n");
|
||||
if (nl) *nl = '\0';
|
||||
|
||||
if (!strlen(buf)) {
|
||||
if (lastDebugCommand) {
|
||||
strcpy(buf, lastDebugCommand);
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
#ifndef NO_RLINE
|
||||
if (enableRline) rline_history_insert(strdup(buf));
|
||||
#endif
|
||||
if (lastDebugCommand) free(lastDebugCommand);
|
||||
lastDebugCommand = strdup(buf);
|
||||
}
|
||||
|
||||
/* Try to tokenize the first bit */
|
||||
char * arg = NULL;
|
||||
char * sp = strstr(buf," ");
|
||||
if (sp) {
|
||||
*sp = '\0';
|
||||
arg = sp + 1;
|
||||
}
|
||||
/* Now check commands */
|
||||
if (!strcmp(buf, "c") || !strcmp(buf,"continue")) {
|
||||
return KRK_DEBUGGER_CONTINUE;
|
||||
} else if (!strcmp(buf, "s") || !strcmp(buf, "step")) {
|
||||
return KRK_DEBUGGER_STEP;
|
||||
} else if (!strcmp(buf, "abort")) {
|
||||
return KRK_DEBUGGER_ABORT;
|
||||
} else if (!strcmp(buf, "q") || !strcmp(buf, "quit")) {
|
||||
return KRK_DEBUGGER_QUIT;
|
||||
} else if (!strcmp(buf, "bt") || !strcmp(buf, "backtrace")) {
|
||||
krk_debug_dumpTraceback();
|
||||
} else if (!strcmp(buf, "p") || !strcmp(buf, "print")) {
|
||||
if (!arg) {
|
||||
fprintf(stderr, "print requires an argument\n");
|
||||
} else {
|
||||
size_t frameCount = krk_currentThread.frameCount;
|
||||
/* Compile statement */
|
||||
KrkFunction * expression = krk_compile(arg,"<debugger>");
|
||||
if (expression) {
|
||||
/* Make sure stepping is disabled first. */
|
||||
krk_debug_disableSingleStep();
|
||||
/* Turn our compiled expression into a callable. */
|
||||
krk_push(OBJECT_VAL(expression));
|
||||
krk_push(OBJECT_VAL(krk_newClosure(expression)));
|
||||
/* Stack silliness, don't ask. */
|
||||
krk_push(NONE_VAL());
|
||||
krk_pop();
|
||||
/* Call the compiled expression with no args, but claim 2 method extras. */
|
||||
krk_push(krk_callSimple(krk_peek(0), 0, 2));
|
||||
fprintf(stderr, "\033[1;30m=> ");
|
||||
krk_printValue(stderr, krk_peek(0));
|
||||
fprintf(stderr, "\033[0m\n");
|
||||
krk_pop();
|
||||
}
|
||||
if (krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION) {
|
||||
krk_dumpTraceback();
|
||||
krk_currentThread.flags &= ~(KRK_THREAD_HAS_EXCEPTION);
|
||||
}
|
||||
krk_currentThread.frameCount = frameCount;
|
||||
}
|
||||
} else if (!strcmp(buf, "break") || !strcmp(buf, "b")) {
|
||||
char * filename = arg;
|
||||
if (!filename) {
|
||||
fprintf(stderr, "usage: break FILE LINE [type]\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
char * lineno = strstr(filename, " ");
|
||||
if (!lineno) {
|
||||
fprintf(stderr, "usage: break FILE LINE [type]\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Advance whitespace */
|
||||
*lineno = '\0';
|
||||
lineno++;
|
||||
|
||||
/* collect optional type */
|
||||
int flags = KRK_BREAKPOINT_NORMAL;
|
||||
char * type = strstr(lineno, " ");
|
||||
if (type) {
|
||||
*type = '\0'; type++;
|
||||
if (!strcmp(type, "repeat") || !strcmp(type,"r")) {
|
||||
flags = KRK_BREAKPOINT_REPEAT;
|
||||
} else if (!strcmp(type, "once") || !strcmp(type,"o")) {
|
||||
flags = KRK_BREAKPOINT_ONCE;
|
||||
} else {
|
||||
fprintf(stderr, "Unrecognized breakpoint type: %s\n", type);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
int lineInt = atoi(lineno);
|
||||
int result = krk_debug_addBreakpointFileLine(krk_copyString(filename, strlen(filename)), lineInt, flags);
|
||||
|
||||
if (result == -1) {
|
||||
fprintf(stderr, "Sorry, couldn't add breakpoint.\n");
|
||||
} else {
|
||||
fprintf(stderr, "Breakpoint %d enabled.\n", result);
|
||||
}
|
||||
|
||||
} else if (!strcmp(buf, "i") || !strcmp(buf, "info")) {
|
||||
if (!arg) {
|
||||
fprintf(stderr, " info breakpoints - Show breakpoints.\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(arg,"breakpoints")) {
|
||||
KrkFunction * codeObject = NULL;
|
||||
size_t offset = 0;
|
||||
int flags = 0;
|
||||
int enabled = 0;
|
||||
int breakIndex = 0;
|
||||
while (1) {
|
||||
int result = krk_debug_examineBreakpoint(breakIndex, &codeObject, &offset, &flags, &enabled);
|
||||
if (result == -1) break;
|
||||
if (result == -2) continue;
|
||||
|
||||
fprintf(stderr, "%-4d in %s+%d %s %s\n",
|
||||
breakIndex,
|
||||
codeObject->name->chars,
|
||||
(int)offset,
|
||||
flags == KRK_BREAKPOINT_NORMAL ? "normal":
|
||||
flags == KRK_BREAKPOINT_REPEAT ? "repeat" :
|
||||
flags == KRK_BREAKPOINT_ONCE ? "once" : "?",
|
||||
enabled ? "enabled" : "disabled");
|
||||
|
||||
breakIndex++;
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Unrecognized info object: %s\n", arg);
|
||||
}
|
||||
|
||||
} else if (!strcmp(buf, "e") || !strcmp(buf, "enable")) {
|
||||
if (!arg) {
|
||||
fprintf(stderr, "enable requires an argument\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
int breakIndex = atoi(arg);
|
||||
|
||||
if (krk_debug_enableBreakpoint(breakIndex)) {
|
||||
fprintf(stderr, "Invalid breakpoint handle.\n");
|
||||
} else {
|
||||
fprintf(stderr, "Breakpoint %d enabled.\n", breakIndex);
|
||||
}
|
||||
} else if (!strcmp(buf, "d") || !strcmp(buf, "disable")) {
|
||||
if (!arg) {
|
||||
fprintf(stderr, "disable requires an argument\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
int breakIndex = atoi(arg);
|
||||
|
||||
if (krk_debug_disableBreakpoint(breakIndex)) {
|
||||
fprintf(stderr, "Invalid breakpoint handle.\n");
|
||||
} else {
|
||||
fprintf(stderr, "Breakpoint %d disabled.\n", breakIndex);
|
||||
}
|
||||
} else if (!strcmp(buf, "r") || !strcmp(buf, "remove")) {
|
||||
if (!arg) {
|
||||
fprintf(stderr, "remove requires an argument\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
int breakIndex = atoi(arg);
|
||||
|
||||
if (krk_debug_removeBreakpoint(breakIndex)) {
|
||||
fprintf(stderr, "Invalid breakpoint handle.\n");
|
||||
} else {
|
||||
fprintf(stderr, "Breakpoint %d removed.\n", breakIndex);
|
||||
}
|
||||
} else if (!strcmp(buf, "help")) {
|
||||
fprintf(stderr,
|
||||
"Kuroko Interactive Debugger\n"
|
||||
" c continue - Continue until the next breakpoint.\n"
|
||||
" s step - Execute this instruction and return to the debugger.\n"
|
||||
" bt backtrace - Print a backtrace.\n"
|
||||
" q quit - Exit the interpreter.\n"
|
||||
" abort - Abort the interpreter (may create a core dump).\n"
|
||||
" b break ... - Set a breakpoint.\n"
|
||||
" e enable N - Enable breakpoint 'N'.\n"
|
||||
" d disable N - Disable breakpoint 'N'.\n"
|
||||
" r remove N - Remove breakpoint 'N'.\n"
|
||||
" i info ... - See information about breakpoints.\n"
|
||||
"\n"
|
||||
"Empty input lines will repeat the last command.\n"
|
||||
);
|
||||
} else {
|
||||
fprintf(stderr, "Unrecognized command: %s\n", buf);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return KRK_DEBUGGER_CONTINUE;
|
||||
_dbgQuit:
|
||||
return KRK_DEBUGGER_QUIT;
|
||||
}
|
||||
|
||||
static void handleSigint(int sigNum) {
|
||||
if (krk_currentThread.frameCount) {
|
||||
krk_runtimeError(vm.exceptions->keyboardInterrupt, "Keyboard interrupt.");
|
||||
krk_currentThread.flags |= KRK_THREAD_SIGNALLED;
|
||||
}
|
||||
|
||||
signal(sigNum, handleSigint);
|
||||
@ -287,10 +533,11 @@ static void findInterpreter(char * argv[]) {
|
||||
vm.binpath = strdup(_pgmptr);
|
||||
#else
|
||||
/* Try asking /proc */
|
||||
char * binpath = realpath("/proc/self/exe", NULL);
|
||||
char tmp[4096];
|
||||
char * binpath = realpath("/proc/self/exe", tmp);
|
||||
if (!binpath || (access(binpath, X_OK) != 0)) {
|
||||
if (strchr(argv[0], '/')) {
|
||||
binpath = realpath(argv[0], NULL);
|
||||
binpath = realpath(argv[0], tmp);
|
||||
} else {
|
||||
/* Search PATH for argv[0] */
|
||||
char * _path = strdup(getenv("PATH"));
|
||||
@ -299,10 +546,9 @@ static void findInterpreter(char * argv[]) {
|
||||
char * next = strchr(path,':');
|
||||
if (next) *next++ = '\0';
|
||||
|
||||
char tmp[4096];
|
||||
sprintf(tmp, "%s/%s", path, argv[0]);
|
||||
snprintf(tmp, 4096, "%s/%s", path, argv[0]);
|
||||
if (access(tmp, X_OK) == 0) {
|
||||
binpath = strdup(tmp);
|
||||
binpath = tmp;
|
||||
break;
|
||||
}
|
||||
path = next;
|
||||
@ -320,13 +566,11 @@ static int runString(char * argv[], int flags, char * string) {
|
||||
findInterpreter(argv);
|
||||
krk_initVM(flags);
|
||||
krk_startModule("__main__");
|
||||
krk_interpret(string, 1, "<stdin>","<stdin>");
|
||||
krk_interpret(string, "<stdin>");
|
||||
krk_freeVM();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This isn't normally exposed. */
|
||||
extern KrkFunction * krk_compile(const char * src, int newScope, char * fileName);
|
||||
static int compileFile(char * argv[], int flags, char * fileName) {
|
||||
findInterpreter(argv);
|
||||
krk_initVM(flags);
|
||||
@ -351,10 +595,10 @@ static int compileFile(char * argv[], int flags, char * fileName) {
|
||||
krk_startModule("__main__");
|
||||
|
||||
/* Call the compiler directly. */
|
||||
KrkFunction * func = krk_compile(buf, 0, fileName);
|
||||
KrkFunction * func = krk_compile(buf, fileName);
|
||||
|
||||
/* See if there was an exception. */
|
||||
if (krk_currentThread.flags & KRK_HAS_EXCEPTION) {
|
||||
if (krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION) {
|
||||
krk_dumpTraceback();
|
||||
}
|
||||
|
||||
@ -378,28 +622,35 @@ static int compileFile(char * argv[], int flags, char * fileName) {
|
||||
#endif
|
||||
|
||||
int main(int argc, char * argv[]) {
|
||||
#ifdef _WIN32
|
||||
SetConsoleOutputCP(65001);
|
||||
SetConsoleCP(65001);
|
||||
#endif
|
||||
int flags = 0;
|
||||
int moduleAsMain = 0;
|
||||
int opt;
|
||||
while ((opt = getopt(argc, argv, "+c:C:dgm:rstMV-:")) != -1) {
|
||||
while ((opt = getopt(argc, argv, "+c:C:dgm:rstMSV-:")) != -1) {
|
||||
switch (opt) {
|
||||
case 'c':
|
||||
return runString(argv, flags, optarg);
|
||||
case 'd':
|
||||
/* Disassemble code blocks after compilation. */
|
||||
flags |= KRK_ENABLE_DISASSEMBLY;
|
||||
flags |= KRK_THREAD_ENABLE_DISASSEMBLY;
|
||||
break;
|
||||
case 'g':
|
||||
/* Always garbage collect during an allocation. */
|
||||
flags |= KRK_ENABLE_STRESS_GC;
|
||||
flags |= KRK_GLOBAL_ENABLE_STRESS_GC;
|
||||
break;
|
||||
case 's':
|
||||
/* Print debug information during compilation. */
|
||||
flags |= KRK_ENABLE_SCAN_TRACING;
|
||||
flags |= KRK_THREAD_ENABLE_SCAN_TRACING;
|
||||
break;
|
||||
case 'S':
|
||||
flags |= KRK_THREAD_SINGLE_STEP;
|
||||
break;
|
||||
case 't':
|
||||
/* Disassemble instructions as they are executed. */
|
||||
flags |= KRK_ENABLE_TRACING;
|
||||
flags |= KRK_THREAD_ENABLE_TRACING;
|
||||
break;
|
||||
case 'm':
|
||||
moduleAsMain = 1;
|
||||
@ -429,6 +680,7 @@ int main(int argc, char * argv[]) {
|
||||
" -t Disassemble instructions as they are exceuted.\n"
|
||||
" -C file Compile 'file', but do not execute it.\n"
|
||||
" -M Print the default module import paths.\n"
|
||||
" -S Enable single-step debugging.\n"
|
||||
" -V Print version information.\n"
|
||||
"\n"
|
||||
" --version Print version information.\n"
|
||||
@ -449,6 +701,8 @@ _finishArgs:
|
||||
findInterpreter(argv);
|
||||
krk_initVM(flags);
|
||||
|
||||
krk_debug_registerCallback(debuggerHook);
|
||||
|
||||
/* Attach kuroko.argv - argv[0] will be set to an empty string for the repl */
|
||||
if (argc == optind) krk_push(OBJECT_VAL(krk_copyString("",0)));
|
||||
for (int arg = optind; arg < argc; ++arg) {
|
||||
@ -471,17 +725,11 @@ _finishArgs:
|
||||
KrkValue result = INTEGER_VAL(0);
|
||||
|
||||
if (moduleAsMain) {
|
||||
/* This isn't going to do what we want for built-in modules, but I'm not sure
|
||||
* what we _should_ do for them anyway... let's just leave that as a TODO;
|
||||
* we do let C modules know they are the __main__ now, so non-built-in
|
||||
* C modules can still act as scripts if they want... */
|
||||
KrkValue module;
|
||||
krk_push(OBJECT_VAL(krk_copyString("__main__",8)));
|
||||
int out = !krk_loadModule(
|
||||
int out = !krk_importModule(
|
||||
AS_STRING(AS_LIST(argList)->values[0]),
|
||||
&module,
|
||||
AS_STRING(krk_peek(0)));
|
||||
if (krk_currentThread.flags & KRK_HAS_EXCEPTION) {
|
||||
if (krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION) {
|
||||
krk_dumpTraceback();
|
||||
krk_resetStack();
|
||||
}
|
||||
@ -493,18 +741,9 @@ _finishArgs:
|
||||
|
||||
/* The repl runs in the context of a top-level module so each input
|
||||
* line can share a globals state with the others. */
|
||||
krk_startModule("<module>");
|
||||
krk_startModule("__main__");
|
||||
krk_attachNamedValue(&krk_currentThread.module->fields,"__doc__", NONE_VAL());
|
||||
|
||||
#ifndef NO_RLINE
|
||||
/* Set ^D to send EOF */
|
||||
rline_exit_string="";
|
||||
/* Enable syntax highlight for Kuroko */
|
||||
rline_exp_set_syntax("krk");
|
||||
/* Bind a callback for \t */
|
||||
rline_exp_set_tab_complete_func(tab_complete_func);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Python stores version info in a built-in module called `sys`.
|
||||
* We are not Python, we'll use `sys` to pretend to be Python
|
||||
@ -540,6 +779,12 @@ _finishArgs:
|
||||
#ifndef NO_RLINE
|
||||
/* Main prompt is >>> like in Python */
|
||||
rline_exp_set_prompts(PROMPT_MAIN, "", 4, 0);
|
||||
/* Set ^D to send EOF */
|
||||
rline_exit_string="";
|
||||
/* Enable syntax highlight for Kuroko */
|
||||
rline_exp_set_syntax("krk");
|
||||
/* Bind a callback for \t */
|
||||
rline_exp_set_tab_complete_func(tab_complete_func);
|
||||
#endif
|
||||
|
||||
while (1) {
|
||||
@ -671,7 +916,7 @@ _finishArgs:
|
||||
FREE_ARRAY(char *, lines, lineCapacity);
|
||||
|
||||
if (valid) {
|
||||
KrkValue result = krk_interpret(allData, 0, "<module>","<stdin>");
|
||||
KrkValue result = krk_interpret(allData, "<stdin>");
|
||||
if (!IS_NONE(result)) {
|
||||
KrkClass * type = krk_getType(result);
|
||||
const char * formatStr = " \033[1;30m=> %s\033[0m\n";
|
||||
@ -687,8 +932,8 @@ _finishArgs:
|
||||
} else {
|
||||
fprintf(stdout, formatStr, AS_CSTRING(result));
|
||||
}
|
||||
krk_resetStack();
|
||||
}
|
||||
krk_resetStack();
|
||||
free(allData);
|
||||
}
|
||||
|
||||
@ -696,7 +941,8 @@ _finishArgs:
|
||||
}
|
||||
} else {
|
||||
krk_startModule("__main__");
|
||||
result = krk_runfile(argv[optind],1,"__main__",argv[optind]);
|
||||
result = krk_runfile(argv[optind],argv[optind]);
|
||||
if (IS_NONE(result) && krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION) result = INTEGER_VAL(1);
|
||||
}
|
||||
|
||||
krk_freeVM();
|
||||
|
2
kuroko
2
kuroko
@ -1 +1 @@
|
||||
Subproject commit 6a95c4a97921e9aa76fda65e1f289428dd95e4b2
|
||||
Subproject commit 34c8d68720ea5ee736b49094b8b1836a267604a9
|
Loading…
Reference in New Issue
Block a user