mirror of
				https://github.com/janet-lang/janet
				synced 2025-10-31 07:33:01 +00:00 
			
		
		
		
	Sourcemapping uses line, column instead of offsets.
This should be friendlier to most users. It does, however, mean we lose range information. However, range information could be recovered by re-parsing, as janet's grammar is simple enough to do this.
This commit is contained in:
		
							
								
								
									
										2
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								Makefile
									
									
									
									
									
								
							| @@ -37,7 +37,7 @@ MANPATH?=$(PREFIX)/share/man/man1/ | |||||||
| PKG_CONFIG_PATH?=$(PREFIX)/lib/pkgconfig | PKG_CONFIG_PATH?=$(PREFIX)/lib/pkgconfig | ||||||
| DEBUGGER=gdb | DEBUGGER=gdb | ||||||
|  |  | ||||||
| CFLAGS=-std=c99 -Wall -Wextra -Isrc/include -Isrc/conf -fpic -O2 -fvisibility=hidden \ | CFLAGS=-std=c99 -Wall -Wextra -Isrc/include -Isrc/conf -fpic -O0 -g -fvisibility=hidden \ | ||||||
| 	   -DJANET_BUILD=$(JANET_BUILD) | 	   -DJANET_BUILD=$(JANET_BUILD) | ||||||
| LDFLAGS=-rdynamic | LDFLAGS=-rdynamic | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1598,19 +1598,33 @@ | |||||||
| (defn bad-parse | (defn bad-parse | ||||||
|   "Default handler for a parse error." |   "Default handler for a parse error." | ||||||
|   [p where] |   [p where] | ||||||
|  |   (def ec (dyn :err-color)) | ||||||
|  |   (def [line col] (parser/where p)) | ||||||
|   (file/write stderr |   (file/write stderr | ||||||
|  |               (if ec "\e[31m" "") | ||||||
|               "parse error in " |               "parse error in " | ||||||
|               where |               where | ||||||
|               " around byte " |               " around line " | ||||||
|               (string (parser/where p)) |               (string line) | ||||||
|  |               ", column " | ||||||
|  |               (string col) | ||||||
|               ": " |               ": " | ||||||
|               (parser/error p) |               (parser/error p) | ||||||
|  |               (if ec "\e[0m" "") | ||||||
|               "\n")) |               "\n")) | ||||||
|  |  | ||||||
| (defn bad-compile | (defn bad-compile | ||||||
|   "Default handler for a compile error." |   "Default handler for a compile error." | ||||||
|   [msg macrof where] |   [msg macrof where] | ||||||
|   (file/write stderr "compile error: " msg " while compiling " where "\n") |   (def ec (dyn :err-color)) | ||||||
|  |   (file/write stderr | ||||||
|  |               (if ec "\e[31m" "") | ||||||
|  |               "compile error: " | ||||||
|  |               msg | ||||||
|  |               " while compiling " | ||||||
|  |               where | ||||||
|  |               (if ec "\e[0m" "") | ||||||
|  |               "\n") | ||||||
|   (when macrof (debug/stacktrace macrof))) |   (when macrof (debug/stacktrace macrof))) | ||||||
|  |  | ||||||
| (defn run-context | (defn run-context | ||||||
| @@ -1660,10 +1674,10 @@ | |||||||
|             (unless compile-only (res)) |             (unless compile-only (res)) | ||||||
|             (do |             (do | ||||||
|               (set good false) |               (set good false) | ||||||
|               (def {:error err :start start :end end :fiber errf} res) |               (def {:error err :line line :column column :fiber errf} res) | ||||||
|               (def msg |               (def msg | ||||||
|                 (if (<= 0 start) |                 (if (<= 0 line) | ||||||
|                   (string err " at (" start ":" end ")") |                   (string err " on line " line ", column " column) | ||||||
|                   err)) |                   err)) | ||||||
|               (on-compile-error msg errf where)))) |               (on-compile-error msg errf where)))) | ||||||
|         (or guard :a))) |         (or guard :a))) | ||||||
| @@ -1946,7 +1960,7 @@ | |||||||
|   (def level (+ (dyn :debug-level 0) 1)) |   (def level (+ (dyn :debug-level 0) 1)) | ||||||
|   (default env (make-env)) |   (default env (make-env)) | ||||||
|   (default chunks (fn [buf p] (getline (string "repl:" |   (default chunks (fn [buf p] (getline (string "repl:" | ||||||
|                                                (parser/where p) |                                                ((parser/where p) 0) | ||||||
|                                                ":" |                                                ":" | ||||||
|                                                (parser/state p :delimiters) "> ") |                                                (parser/state p :delimiters) "> ") | ||||||
|                                        buf))) |                                        buf))) | ||||||
| @@ -1967,7 +1981,7 @@ _fiber is bound to the suspended fiber | |||||||
| ```) | ```) | ||||||
|                           (repl (fn [buf p] |                           (repl (fn [buf p] | ||||||
|                                   (def status (parser/state p :delimiters)) |                                   (def status (parser/state p :delimiters)) | ||||||
|                                   (def c (parser/where p)) |                                   (def c ((parser/where p) 0)) | ||||||
|                                   (def prompt (string "debug[" level "]:" c ":" status "> ")) |                                   (def prompt (string "debug[" level "]:" c ":" status "> ")) | ||||||
|                                   (getline prompt buf)) |                                   (getline prompt buf)) | ||||||
|                                 onsignal nextenv)) |                                 onsignal nextenv)) | ||||||
|   | |||||||
| @@ -705,8 +705,8 @@ static JanetAssembleResult janet_asm1(JanetAssembler *parent, Janet source, int | |||||||
|             if (!janet_checkint(tup[1])) { |             if (!janet_checkint(tup[1])) { | ||||||
|                 janet_asm_error(&a, "expected integer"); |                 janet_asm_error(&a, "expected integer"); | ||||||
|             } |             } | ||||||
|             mapping.start = janet_unwrap_integer(tup[0]); |             mapping.line = janet_unwrap_integer(tup[0]); | ||||||
|             mapping.end = janet_unwrap_integer(tup[1]); |             mapping.column = janet_unwrap_integer(tup[1]); | ||||||
|             def->sourcemap[i] = mapping; |             def->sourcemap[i] = mapping; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @@ -749,31 +749,31 @@ static const JanetInstructionDef *janet_asm_reverse_lookup(uint32_t instr) { | |||||||
| } | } | ||||||
|  |  | ||||||
| /* Create some constant sized tuples */ | /* Create some constant sized tuples */ | ||||||
| static Janet tup1(Janet x) { | static const Janet *tup1(Janet x) { | ||||||
|     Janet *tup = janet_tuple_begin(1); |     Janet *tup = janet_tuple_begin(1); | ||||||
|     tup[0] = x; |     tup[0] = x; | ||||||
|     return janet_wrap_tuple(janet_tuple_end(tup)); |     return janet_tuple_end(tup); | ||||||
| } | } | ||||||
| static Janet tup2(Janet x, Janet y) { | static const Janet *tup2(Janet x, Janet y) { | ||||||
|     Janet *tup = janet_tuple_begin(2); |     Janet *tup = janet_tuple_begin(2); | ||||||
|     tup[0] = x; |     tup[0] = x; | ||||||
|     tup[1] = y; |     tup[1] = y; | ||||||
|     return janet_wrap_tuple(janet_tuple_end(tup)); |     return janet_tuple_end(tup); | ||||||
| } | } | ||||||
| static Janet tup3(Janet x, Janet y, Janet z) { | static const Janet *tup3(Janet x, Janet y, Janet z) { | ||||||
|     Janet *tup = janet_tuple_begin(3); |     Janet *tup = janet_tuple_begin(3); | ||||||
|     tup[0] = x; |     tup[0] = x; | ||||||
|     tup[1] = y; |     tup[1] = y; | ||||||
|     tup[2] = z; |     tup[2] = z; | ||||||
|     return janet_wrap_tuple(janet_tuple_end(tup)); |     return janet_tuple_end(tup); | ||||||
| } | } | ||||||
| static Janet tup4(Janet w, Janet x, Janet y, Janet z) { | static const Janet *tup4(Janet w, Janet x, Janet y, Janet z) { | ||||||
|     Janet *tup = janet_tuple_begin(4); |     Janet *tup = janet_tuple_begin(4); | ||||||
|     tup[0] = w; |     tup[0] = w; | ||||||
|     tup[1] = x; |     tup[1] = x; | ||||||
|     tup[2] = y; |     tup[2] = y; | ||||||
|     tup[3] = z; |     tup[3] = z; | ||||||
|     return janet_wrap_tuple(janet_tuple_end(tup)); |     return janet_tuple_end(tup); | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Given an argument, convert it to the appropriate integer or symbol */ | /* Given an argument, convert it to the appropriate integer or symbol */ | ||||||
| @@ -784,41 +784,56 @@ Janet janet_asm_decode_instruction(uint32_t instr) { | |||||||
|         return janet_wrap_integer((int32_t)instr); |         return janet_wrap_integer((int32_t)instr); | ||||||
|     } |     } | ||||||
|     name = janet_csymbolv(def->name); |     name = janet_csymbolv(def->name); | ||||||
|  |     const Janet *ret = NULL; | ||||||
| #define oparg(shift, mask) ((instr >> ((shift) << 3)) & (mask)) | #define oparg(shift, mask) ((instr >> ((shift) << 3)) & (mask)) | ||||||
|     switch (janet_instructions[def->opcode]) { |     switch (janet_instructions[def->opcode]) { | ||||||
|         case JINT_0: |         case JINT_0: | ||||||
|             return tup1(name); |             ret = tup1(name); | ||||||
|  |             break; | ||||||
|         case JINT_S: |         case JINT_S: | ||||||
|             return tup2(name, janet_wrap_integer(oparg(1, 0xFFFFFF))); |             ret = tup2(name, janet_wrap_integer(oparg(1, 0xFFFFFF))); | ||||||
|  |             break; | ||||||
|         case JINT_L: |         case JINT_L: | ||||||
|             return tup2(name, janet_wrap_integer((int32_t)instr >> 8)); |             ret = tup2(name, janet_wrap_integer((int32_t)instr >> 8)); | ||||||
|  |             break; | ||||||
|         case JINT_SS: |         case JINT_SS: | ||||||
|         case JINT_ST: |         case JINT_ST: | ||||||
|         case JINT_SC: |         case JINT_SC: | ||||||
|         case JINT_SU: |         case JINT_SU: | ||||||
|         case JINT_SD: |         case JINT_SD: | ||||||
|             return tup3(name, |             ret = tup3(name, | ||||||
|                     janet_wrap_integer(oparg(1, 0xFF)), |                     janet_wrap_integer(oparg(1, 0xFF)), | ||||||
|                     janet_wrap_integer(oparg(2, 0xFFFF))); |                     janet_wrap_integer(oparg(2, 0xFFFF))); | ||||||
|  |             break; | ||||||
|         case JINT_SI: |         case JINT_SI: | ||||||
|         case JINT_SL: |         case JINT_SL: | ||||||
|             return tup3(name, |             ret =  tup3(name, | ||||||
|                     janet_wrap_integer(oparg(1, 0xFF)), |                     janet_wrap_integer(oparg(1, 0xFF)), | ||||||
|                     janet_wrap_integer((int32_t)instr >> 16)); |                     janet_wrap_integer((int32_t)instr >> 16)); | ||||||
|  |             break; | ||||||
|         case JINT_SSS: |         case JINT_SSS: | ||||||
|         case JINT_SES: |         case JINT_SES: | ||||||
|         case JINT_SSU: |         case JINT_SSU: | ||||||
|             return tup4(name, |             ret = tup4(name, | ||||||
|                     janet_wrap_integer(oparg(1, 0xFF)), |                     janet_wrap_integer(oparg(1, 0xFF)), | ||||||
|                     janet_wrap_integer(oparg(2, 0xFF)), |                     janet_wrap_integer(oparg(2, 0xFF)), | ||||||
|                     janet_wrap_integer(oparg(3, 0xFF))); |                     janet_wrap_integer(oparg(3, 0xFF))); | ||||||
|  |             break; | ||||||
|         case JINT_SSI: |         case JINT_SSI: | ||||||
|             return tup4(name, |             ret = tup4(name, | ||||||
|                     janet_wrap_integer(oparg(1, 0xFF)), |                     janet_wrap_integer(oparg(1, 0xFF)), | ||||||
|                     janet_wrap_integer(oparg(2, 0xFF)), |                     janet_wrap_integer(oparg(2, 0xFF)), | ||||||
|                     janet_wrap_integer((int32_t)instr >> 24)); |                     janet_wrap_integer((int32_t)instr >> 24)); | ||||||
|  |             break; | ||||||
|     } |     } | ||||||
| #undef oparg | #undef oparg | ||||||
|  |     if (ret) { | ||||||
|  |         /* Check if break point set */ | ||||||
|  |         if (instr & 0x80) { | ||||||
|  |             janet_tuple_flag(ret) |= JANET_TUPLE_FLAG_BRACKETCTOR; | ||||||
|  |         } | ||||||
|  |         return janet_wrap_tuple(ret); | ||||||
|  |     } | ||||||
|     return janet_wrap_nil(); |     return janet_wrap_nil(); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -849,7 +864,7 @@ Janet janet_disasm(JanetFuncDef *def) { | |||||||
|             Janet src = def->constants[i]; |             Janet src = def->constants[i]; | ||||||
|             Janet dest; |             Janet dest; | ||||||
|             if (janet_checktype(src, JANET_TUPLE)) { |             if (janet_checktype(src, JANET_TUPLE)) { | ||||||
|                 dest = tup2(janet_csymbolv("quote"), src); |                 dest = janet_wrap_tuple(tup2(janet_csymbolv("quote"), src)); | ||||||
|             } else { |             } else { | ||||||
|                 dest = src; |                 dest = src; | ||||||
|             } |             } | ||||||
| @@ -870,8 +885,8 @@ Janet janet_disasm(JanetFuncDef *def) { | |||||||
|         for (i = 0; i < def->bytecode_length; i++) { |         for (i = 0; i < def->bytecode_length; i++) { | ||||||
|             Janet *t = janet_tuple_begin(2); |             Janet *t = janet_tuple_begin(2); | ||||||
|             JanetSourceMapping mapping = def->sourcemap[i]; |             JanetSourceMapping mapping = def->sourcemap[i]; | ||||||
|             t[0] = janet_wrap_integer(mapping.start); |             t[0] = janet_wrap_integer(mapping.line); | ||||||
|             t[1] = janet_wrap_integer(mapping.end); |             t[1] = janet_wrap_integer(mapping.column); | ||||||
|             sourcemap->data[i] = janet_wrap_tuple(janet_tuple_end(t)); |             sourcemap->data[i] = janet_wrap_tuple(janet_tuple_end(t)); | ||||||
|         } |         } | ||||||
|         sourcemap->count = def->bytecode_length; |         sourcemap->count = def->bytecode_length; | ||||||
|   | |||||||
| @@ -474,9 +474,9 @@ static int macroexpand1( | |||||||
|     if (janet_tuple_length(form) == 0) |     if (janet_tuple_length(form) == 0) | ||||||
|         return 0; |         return 0; | ||||||
|     /* Source map - only set when we get a tuple */ |     /* Source map - only set when we get a tuple */ | ||||||
|     if (janet_tuple_sm_start(form) >= 0) { |     if (janet_tuple_sm_line(form) >= 0) { | ||||||
|         c->current_mapping.start = janet_tuple_sm_start(form); |         c->current_mapping.line = janet_tuple_sm_line(form); | ||||||
|         c->current_mapping.end = janet_tuple_sm_end(form); |         c->current_mapping.column = janet_tuple_sm_column(form); | ||||||
|     } |     } | ||||||
|     /* Bracketed tuples are not specials or macros! */ |     /* Bracketed tuples are not specials or macros! */ | ||||||
|     if (janet_tuple_flag(form) & JANET_TUPLE_FLAG_BRACKETCTOR) |     if (janet_tuple_flag(form) & JANET_TUPLE_FLAG_BRACKETCTOR) | ||||||
| @@ -664,15 +664,15 @@ static void janetc_init(JanetCompiler *c, JanetTable *env, const uint8_t *where) | |||||||
|     c->recursion_guard = JANET_RECURSION_GUARD; |     c->recursion_guard = JANET_RECURSION_GUARD; | ||||||
|     c->env = env; |     c->env = env; | ||||||
|     c->source = where; |     c->source = where; | ||||||
|     c->current_mapping.start = -1; |     c->current_mapping.line = -1; | ||||||
|     c->current_mapping.end = -1; |     c->current_mapping.column = -1; | ||||||
|     /* Init result */ |     /* Init result */ | ||||||
|     c->result.error = NULL; |     c->result.error = NULL; | ||||||
|     c->result.status = JANET_COMPILE_OK; |     c->result.status = JANET_COMPILE_OK; | ||||||
|     c->result.funcdef = NULL; |     c->result.funcdef = NULL; | ||||||
|     c->result.macrofiber = NULL; |     c->result.macrofiber = NULL; | ||||||
|     c->result.error_mapping.start = -1; |     c->result.error_mapping.line = -1; | ||||||
|     c->result.error_mapping.end = -1; |     c->result.error_mapping.column = -1; | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Deinitialize a compiler struct */ | /* Deinitialize a compiler struct */ | ||||||
| @@ -733,8 +733,8 @@ static Janet cfun(int32_t argc, Janet *argv) { | |||||||
|     } else { |     } else { | ||||||
|         JanetTable *t = janet_table(4); |         JanetTable *t = janet_table(4); | ||||||
|         janet_table_put(t, janet_ckeywordv("error"), janet_wrap_string(res.error)); |         janet_table_put(t, janet_ckeywordv("error"), janet_wrap_string(res.error)); | ||||||
|         janet_table_put(t, janet_ckeywordv("start"), janet_wrap_integer(res.error_mapping.start)); |         janet_table_put(t, janet_ckeywordv("line"), janet_wrap_integer(res.error_mapping.line)); | ||||||
|         janet_table_put(t, janet_ckeywordv("end"), janet_wrap_integer(res.error_mapping.end)); |         janet_table_put(t, janet_ckeywordv("column"), janet_wrap_integer(res.error_mapping.column)); | ||||||
|         if (res.macrofiber) { |         if (res.macrofiber) { | ||||||
|             janet_table_put(t, janet_ckeywordv("fiber"), janet_wrap_fiber(res.macrofiber)); |             janet_table_put(t, janet_ckeywordv("fiber"), janet_wrap_fiber(res.macrofiber)); | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -52,35 +52,38 @@ void janet_debug_unbreak(JanetFuncDef *def, int32_t pc) { | |||||||
|  */ |  */ | ||||||
| void janet_debug_find( | void janet_debug_find( | ||||||
|     JanetFuncDef **def_out, int32_t *pc_out, |     JanetFuncDef **def_out, int32_t *pc_out, | ||||||
|     const uint8_t *source, int32_t offset) { |     const uint8_t *source, int32_t sourceLine, int32_t sourceColumn) { | ||||||
|     /* Scan the heap for right func def */ |     /* Scan the heap for right func def */ | ||||||
|     JanetGCObject *current = janet_vm_blocks; |     JanetGCObject *current = janet_vm_blocks; | ||||||
|     /* Keep track of the best source mapping we have seen so far */ |     /* Keep track of the best source mapping we have seen so far */ | ||||||
|     int32_t besti = -1; |     int32_t besti = -1; | ||||||
|     int32_t best_range = INT32_MAX; |     int32_t best_line = -1; | ||||||
|  |     int32_t best_column = -1; | ||||||
|     JanetFuncDef *best_def = NULL; |     JanetFuncDef *best_def = NULL; | ||||||
|     while (NULL != current) { |     while (NULL != current) { | ||||||
|         if ((current->flags & JANET_MEM_TYPEBITS) == JANET_MEMORY_FUNCDEF) { |         if ((current->flags & JANET_MEM_TYPEBITS) == JANET_MEMORY_FUNCDEF) { | ||||||
|             JanetFuncDef *def = (JanetFuncDef *)(current + 1); |             JanetFuncDef *def = (JanetFuncDef *)(current); | ||||||
|             if (def->sourcemap && |             if (def->sourcemap && | ||||||
|                     def->source && |                     def->source && | ||||||
|                     !janet_string_compare(source, def->source)) { |                     !janet_string_compare(source, def->source)) { | ||||||
|                 /* Correct source file, check mappings. The chosen |                 /* Correct source file, check mappings. The chosen | ||||||
|                  * pc index is the first match with the smallest range. */ |                  * pc index is the instruction closest to the given line column, but | ||||||
|  |                  * not after. */ | ||||||
|                 int32_t i; |                 int32_t i; | ||||||
|                 for (i = 0; i < def->bytecode_length; i++) { |                 for (i = 0; i < def->bytecode_length; i++) { | ||||||
|                     int32_t start = def->sourcemap[i].start; |                     int32_t line = def->sourcemap[i].line; | ||||||
|                     int32_t end = def->sourcemap[i].end; |                     int32_t column = def->sourcemap[i].column; | ||||||
|                     if (end - start < best_range && |                     if (line <= sourceLine && line >= best_line) { | ||||||
|                             start <= offset && |                         if (column <= sourceColumn && column > best_column) { | ||||||
|                             end >= offset) { |                             best_line = line; | ||||||
|                         best_range = end - start; |                             best_column = column; | ||||||
|                             besti = i; |                             besti = i; | ||||||
|                             best_def = def; |                             best_def = def; | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  |         } | ||||||
|         current = current->next; |         current = current->next; | ||||||
|     } |     } | ||||||
|     if (best_def) { |     if (best_def) { | ||||||
| @@ -150,44 +153,8 @@ void janet_stacktrace(JanetFiber *fiber, Janet err) { | |||||||
|             if (frame->func && frame->pc) { |             if (frame->func && frame->pc) { | ||||||
|                 int32_t off = (int32_t)(frame->pc - def->bytecode); |                 int32_t off = (int32_t)(frame->pc - def->bytecode); | ||||||
|                 if (def->sourcemap) { |                 if (def->sourcemap) { | ||||||
|                     /* Try to get line and column information */ |  | ||||||
|                     JanetSourceMapping mapping = def->sourcemap[off]; |                     JanetSourceMapping mapping = def->sourcemap[off]; | ||||||
|                     char buf[1024]; |                     fprintf(out, " on line %d, column %d", mapping.line, mapping.column); | ||||||
|                     size_t nread; |  | ||||||
|                     int32_t offset = 0; |  | ||||||
|                     int32_t line = 1; |  | ||||||
|                     int32_t col = 1; |  | ||||||
|                     int notdone = 1; |  | ||||||
|                     char last = 0; |  | ||||||
|                     FILE *f; |  | ||||||
|                     if (def->source && (f = fopen((const char *)def->source, "rb"))) { |  | ||||||
|                         while (notdone && (nread = fread(buf, 1, sizeof(buf), f)) > 0) { |  | ||||||
|                             for (size_t i = 0; i < nread; i++) { |  | ||||||
|                                 char c = buf[i]; |  | ||||||
|                                 if (c == '\r') { |  | ||||||
|                                     line++; |  | ||||||
|                                     col = 1; |  | ||||||
|                                 } else if (c == '\n') { |  | ||||||
|                                     col = 1; |  | ||||||
|                                     if (last != '\r') { |  | ||||||
|                                         line++; |  | ||||||
|                                     } |  | ||||||
|                                 } else { |  | ||||||
|                                     col++; |  | ||||||
|                                 } |  | ||||||
|                                 last = c; |  | ||||||
|                                 if (offset == mapping.start) { |  | ||||||
|                                     fprintf(out, " on line %d, column %d", line, col); |  | ||||||
|                                     notdone = 0; |  | ||||||
|                                     break; |  | ||||||
|                                 } |  | ||||||
|                                 offset++; |  | ||||||
|                             } |  | ||||||
|                         } |  | ||||||
|                         fclose(f); |  | ||||||
|                     } else { |  | ||||||
|                         fprintf(out, " at (%d:%d)", mapping.start, mapping.end); |  | ||||||
|                     } |  | ||||||
|                 } else { |                 } else { | ||||||
|                     fprintf(out, " pc=%d", off); |                     fprintf(out, " pc=%d", off); | ||||||
|                 } |                 } | ||||||
| @@ -208,10 +175,11 @@ void janet_stacktrace(JanetFiber *fiber, Janet err) { | |||||||
| /* Helper to find funcdef and bytecode offset to insert or remove breakpoints. | /* Helper to find funcdef and bytecode offset to insert or remove breakpoints. | ||||||
|  * Takes a source file name and byte offset. */ |  * Takes a source file name and byte offset. */ | ||||||
| static void helper_find(int32_t argc, Janet *argv, JanetFuncDef **def, int32_t *bytecode_offset) { | static void helper_find(int32_t argc, Janet *argv, JanetFuncDef **def, int32_t *bytecode_offset) { | ||||||
|     janet_fixarity(argc, 2); |     janet_fixarity(argc, 3); | ||||||
|     const uint8_t *source = janet_getstring(argv, 0); |     const uint8_t *source = janet_getstring(argv, 0); | ||||||
|     int32_t source_offset = janet_getinteger(argv, 1); |     int32_t line = janet_getinteger(argv, 1); | ||||||
|     janet_debug_find(def, bytecode_offset, source, source_offset); |     int32_t col = janet_getinteger(argv, 2); | ||||||
|  |     janet_debug_find(def, bytecode_offset, source, line, col); | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Helper to find funcdef and bytecode offset to insert or remove breakpoints. | /* Helper to find funcdef and bytecode offset to insert or remove breakpoints. | ||||||
| @@ -298,8 +266,8 @@ static Janet doframe(JanetStackFrame *frame) { | |||||||
|         janet_table_put(t, janet_ckeywordv("pc"), janet_wrap_integer(off)); |         janet_table_put(t, janet_ckeywordv("pc"), janet_wrap_integer(off)); | ||||||
|         if (def->sourcemap) { |         if (def->sourcemap) { | ||||||
|             JanetSourceMapping mapping = def->sourcemap[off]; |             JanetSourceMapping mapping = def->sourcemap[off]; | ||||||
|             janet_table_put(t, janet_ckeywordv("source-start"), janet_wrap_integer(mapping.start)); |             janet_table_put(t, janet_ckeywordv("source-line"), janet_wrap_integer(mapping.line)); | ||||||
|             janet_table_put(t, janet_ckeywordv("source-end"), janet_wrap_integer(mapping.end)); |             janet_table_put(t, janet_ckeywordv("source-column"), janet_wrap_integer(mapping.column)); | ||||||
|         } |         } | ||||||
|         if (def->source) { |         if (def->source) { | ||||||
|             janet_table_put(t, janet_ckeywordv("source"), janet_wrap_string(def->source)); |             janet_table_put(t, janet_ckeywordv("source"), janet_wrap_string(def->source)); | ||||||
| @@ -349,17 +317,17 @@ static const JanetReg debug_cfuns[] = { | |||||||
|     { |     { | ||||||
|         "debug/break", cfun_debug_break, |         "debug/break", cfun_debug_break, | ||||||
|         JDOC("(debug/break source byte-offset)\n\n" |         JDOC("(debug/break source byte-offset)\n\n" | ||||||
|              "Sets a breakpoint with source a key at a given byte offset. An offset " |              "Sets a breakpoint with source a key at a given line and column. " | ||||||
|              "of 0 is the first byte in a file. Will throw an error if the breakpoint location " |              "Will throw an error if the breakpoint location " | ||||||
|              "cannot be found. For example\n\n" |              "cannot be found. For example\n\n" | ||||||
|              "\t(debug/break \"core.janet\" 1000)\n\n" |              "\t(debug/break \"core.janet\" 1000)\n\n" | ||||||
|              "wil set a breakpoint at the 1000th byte of the file core.janet.") |              "wil set a breakpoint at the 1000th byte of the file core.janet.") | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|         "debug/unbreak", cfun_debug_unbreak, |         "debug/unbreak", cfun_debug_unbreak, | ||||||
|         JDOC("(debug/unbreak source byte-offset)\n\n" |         JDOC("(debug/unbreak source line column)\n\n" | ||||||
|              "Remove a breakpoint with a source key at a given byte offset. An offset " |              "Remove a breakpoint with a source key at a given line and column. " | ||||||
|              "of 0 is the first byte in a file. Will throw an error if the breakpoint " |              "Will throw an error if the breakpoint " | ||||||
|              "cannot be found.") |              "cannot be found.") | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|   | |||||||
| @@ -258,9 +258,9 @@ static void marshal_one_def(MarshalState *st, JanetFuncDef *def, int flags) { | |||||||
|         int32_t current = 0; |         int32_t current = 0; | ||||||
|         for (int32_t i = 0; i < def->bytecode_length; i++) { |         for (int32_t i = 0; i < def->bytecode_length; i++) { | ||||||
|             JanetSourceMapping map = def->sourcemap[i]; |             JanetSourceMapping map = def->sourcemap[i]; | ||||||
|             pushint(st, map.start - current); |             pushint(st, map.line - current); | ||||||
|             pushint(st, map.end - map.start); |             pushint(st, map.column); | ||||||
|             current = map.end; |             current = map.line; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -827,9 +827,8 @@ static const uint8_t *unmarshal_one_def( | |||||||
|             } |             } | ||||||
|             for (int32_t i = 0; i < bytecode_length; i++) { |             for (int32_t i = 0; i < bytecode_length; i++) { | ||||||
|                 current += readint(st, &data); |                 current += readint(st, &data); | ||||||
|                 def->sourcemap[i].start = current; |                 def->sourcemap[i].line = current; | ||||||
|                 current += readint(st, &data); |                 def->sourcemap[i].column = readint(st, &data); | ||||||
|                 def->sourcemap[i].end = current; |  | ||||||
|             } |             } | ||||||
|         } else { |         } else { | ||||||
|             def->sourcemap = NULL; |             def->sourcemap = NULL; | ||||||
|   | |||||||
| @@ -106,7 +106,8 @@ struct JanetParseState { | |||||||
|     int32_t counter; |     int32_t counter; | ||||||
|     int32_t argn; |     int32_t argn; | ||||||
|     int flags; |     int flags; | ||||||
|     size_t start; |     size_t line; | ||||||
|  |     size_t column; | ||||||
|     Consumer consumer; |     Consumer consumer; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -153,7 +154,8 @@ static void pushstate(JanetParser *p, Consumer consumer, int flags) { | |||||||
|     s.argn = 0; |     s.argn = 0; | ||||||
|     s.flags = flags; |     s.flags = flags; | ||||||
|     s.consumer = consumer; |     s.consumer = consumer; | ||||||
|     s.start = p->offset; |     s.line = p->line; | ||||||
|  |     s.column = p->column; | ||||||
|     _pushstate(p, s); |     _pushstate(p, s); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -164,8 +166,8 @@ static void popstate(JanetParser *p, Janet val) { | |||||||
|         if (newtop->flags & PFLAG_CONTAINER) { |         if (newtop->flags & PFLAG_CONTAINER) { | ||||||
|             /* Source mapping info */ |             /* Source mapping info */ | ||||||
|             if (janet_checktype(val, JANET_TUPLE)) { |             if (janet_checktype(val, JANET_TUPLE)) { | ||||||
|                 janet_tuple_sm_start(janet_unwrap_tuple(val)) = (int32_t) top.start; |                 janet_tuple_sm_line(janet_unwrap_tuple(val)) = (int32_t) top.line; | ||||||
|                 janet_tuple_sm_end(janet_unwrap_tuple(val)) = (int32_t) p->offset; |                 janet_tuple_sm_column(janet_unwrap_tuple(val)) = (int32_t) top.column; | ||||||
|             } |             } | ||||||
|             newtop->argn++; |             newtop->argn++; | ||||||
|             /* Keep track of number of values in the root state */ |             /* Keep track of number of values in the root state */ | ||||||
| @@ -184,8 +186,8 @@ static void popstate(JanetParser *p, Janet val) { | |||||||
|             t[0] = janet_csymbolv(which); |             t[0] = janet_csymbolv(which); | ||||||
|             t[1] = val; |             t[1] = val; | ||||||
|             /* Quote source mapping info */ |             /* Quote source mapping info */ | ||||||
|             janet_tuple_sm_start(t) = (int32_t) newtop->start; |             janet_tuple_sm_line(t) = (int32_t) newtop->line; | ||||||
|             janet_tuple_sm_end(t) = (int32_t) p->offset; |             janet_tuple_sm_column(t) = (int32_t) newtop->column; | ||||||
|             val = janet_wrap_tuple(janet_tuple_end(t)); |             val = janet_wrap_tuple(janet_tuple_end(t)); | ||||||
|         } else { |         } else { | ||||||
|             return; |             return; | ||||||
| @@ -562,7 +564,16 @@ static void janet_parser_checkdead(JanetParser *parser) { | |||||||
| void janet_parser_consume(JanetParser *parser, uint8_t c) { | void janet_parser_consume(JanetParser *parser, uint8_t c) { | ||||||
|     int consumed = 0; |     int consumed = 0; | ||||||
|     janet_parser_checkdead(parser); |     janet_parser_checkdead(parser); | ||||||
|     parser->offset++; |     if (c == '\r') { | ||||||
|  |         parser->line++; | ||||||
|  |         parser->column = 0; | ||||||
|  |     } else if (c == '\n') { | ||||||
|  |         parser->column = 0; | ||||||
|  |         if (parser->lookback != '\r') | ||||||
|  |             parser->line++; | ||||||
|  |     } else { | ||||||
|  |         parser->column++; | ||||||
|  |     } | ||||||
|     while (!consumed && !parser->error) { |     while (!consumed && !parser->error) { | ||||||
|         JanetParseState *state = parser->states + parser->statecount - 1; |         JanetParseState *state = parser->states + parser->statecount - 1; | ||||||
|         consumed = state->consumer(parser, state, c); |         consumed = state->consumer(parser, state, c); | ||||||
| @@ -572,11 +583,14 @@ void janet_parser_consume(JanetParser *parser, uint8_t c) { | |||||||
|  |  | ||||||
| void janet_parser_eof(JanetParser *parser) { | void janet_parser_eof(JanetParser *parser) { | ||||||
|     janet_parser_checkdead(parser); |     janet_parser_checkdead(parser); | ||||||
|  |     size_t oldcolumn = parser->column; | ||||||
|  |     size_t oldline = parser->line; | ||||||
|     janet_parser_consume(parser, '\n'); |     janet_parser_consume(parser, '\n'); | ||||||
|     if (parser->statecount > 1) { |     if (parser->statecount > 1) { | ||||||
|         parser->error = "unexpected end of source"; |         parser->error = "unexpected end of source"; | ||||||
|     } |     } | ||||||
|     parser->offset--; |     parser->line = oldline; | ||||||
|  |     parser->column = oldcolumn; | ||||||
|     parser->flag = 1; |     parser->flag = 1; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -630,7 +644,8 @@ void janet_parser_init(JanetParser *parser) { | |||||||
|     parser->statecap = 0; |     parser->statecap = 0; | ||||||
|     parser->error = NULL; |     parser->error = NULL; | ||||||
|     parser->lookback = -1; |     parser->lookback = -1; | ||||||
|     parser->offset = 0; |     parser->line = 1; | ||||||
|  |     parser->column = 0; | ||||||
|     parser->pending = 0; |     parser->pending = 0; | ||||||
|     parser->flag = 0; |     parser->flag = 0; | ||||||
|  |  | ||||||
| @@ -648,7 +663,8 @@ void janet_parser_clone(const JanetParser *src, JanetParser *dest) { | |||||||
|     dest->flag = src->flag; |     dest->flag = src->flag; | ||||||
|     dest->pending = src->pending; |     dest->pending = src->pending; | ||||||
|     dest->lookback = src->lookback; |     dest->lookback = src->lookback; | ||||||
|     dest->offset = src->offset; |     dest->line = src->line; | ||||||
|  |     dest->column = src->column; | ||||||
|     dest->error = src->error; |     dest->error = src->error; | ||||||
|  |  | ||||||
|     /* Keep counts */ |     /* Keep counts */ | ||||||
| @@ -771,7 +787,7 @@ static Janet cfun_parse_insert(int32_t argc, Janet *argv) { | |||||||
|     JanetParseState *s = p->states + p->statecount - 1; |     JanetParseState *s = p->states + p->statecount - 1; | ||||||
|     if (s->consumer == tokenchar) { |     if (s->consumer == tokenchar) { | ||||||
|         janet_parser_consume(p, ' '); |         janet_parser_consume(p, ' '); | ||||||
|         p->offset--; |         p->column--; | ||||||
|         s = p->states + p->statecount - 1; |         s = p->states + p->statecount - 1; | ||||||
|     } |     } | ||||||
|     if (s->flags & PFLAG_CONTAINER) { |     if (s->flags & PFLAG_CONTAINER) { | ||||||
| @@ -855,15 +871,12 @@ static Janet cfun_parse_flush(int32_t argc, Janet *argv) { | |||||||
| } | } | ||||||
|  |  | ||||||
| static Janet cfun_parse_where(int32_t argc, Janet *argv) { | static Janet cfun_parse_where(int32_t argc, Janet *argv) { | ||||||
|     janet_arity(argc, 1, 2); |     janet_fixarity(argc, 1); | ||||||
|     JanetParser *p = janet_getabstract(argv, 0, &janet_parse_parsertype); |     JanetParser *p = janet_getabstract(argv, 0, &janet_parse_parsertype); | ||||||
|     if (argc > 1) { |     Janet *tup = janet_tuple_begin(2); | ||||||
|         int32_t offset = janet_getinteger(argv, 1); |     tup[0] = janet_wrap_integer(p->line); | ||||||
|         p->offset = offset; |     tup[1] = janet_wrap_integer(p->column); | ||||||
|         return argv[0]; |     return janet_wrap_tuple(janet_tuple_end(tup)); | ||||||
|     } else { |  | ||||||
|         return janet_wrap_integer(p->offset); |  | ||||||
|     } |  | ||||||
| } | } | ||||||
|  |  | ||||||
| static Janet janet_wrap_parse_state(JanetParseState *s, Janet *args, | static Janet janet_wrap_parse_state(JanetParseState *s, Janet *args, | ||||||
| @@ -928,8 +941,8 @@ static Janet janet_wrap_parse_state(JanetParseState *s, Janet *args, | |||||||
|         janet_table_put(state, janet_ckeywordv("buffer"), janet_wrap_string(buffer)); |         janet_table_put(state, janet_ckeywordv("buffer"), janet_wrap_string(buffer)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     janet_table_put(state, janet_ckeywordv("start"), |     janet_table_put(state, janet_ckeywordv("line"), janet_wrap_integer(s->line)); | ||||||
|                     janet_wrap_integer(s->start)); |     janet_table_put(state, janet_ckeywordv("column"), janet_wrap_integer(s->column)); | ||||||
|     return janet_wrap_table(state); |     return janet_wrap_table(state); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -1121,10 +1134,8 @@ static const JanetReg parse_cfuns[] = { | |||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|         "parser/where", cfun_parse_where, |         "parser/where", cfun_parse_where, | ||||||
|         JDOC("(parser/where parser &opt offset)\n\n" |         JDOC("(parser/where parser)\n\n" | ||||||
|              "Returns the current line number and column number of the parser's location " |              "Returns the current line number and column of the parser's internal state.") | ||||||
|              "in the byte stream as an index, counted from 0. " |  | ||||||
|              "If offset is supplied, then the byte offset is updated to that new value.") |  | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|         "parser/eof", cfun_parse_eof, |         "parser/eof", cfun_parse_eof, | ||||||
|   | |||||||
| @@ -175,8 +175,8 @@ static int destructure(JanetCompiler *c, | |||||||
| static const Janet *janetc_make_sourcemap(JanetCompiler *c) { | static const Janet *janetc_make_sourcemap(JanetCompiler *c) { | ||||||
|     Janet *tup = janet_tuple_begin(3); |     Janet *tup = janet_tuple_begin(3); | ||||||
|     tup[0] = c->source ? janet_wrap_string(c->source) : janet_wrap_nil(); |     tup[0] = c->source ? janet_wrap_string(c->source) : janet_wrap_nil(); | ||||||
|     tup[1] = janet_wrap_integer(c->current_mapping.start); |     tup[1] = janet_wrap_integer(c->current_mapping.line); | ||||||
|     tup[2] = janet_wrap_integer(c->current_mapping.end); |     tup[2] = janet_wrap_integer(c->current_mapping.column); | ||||||
|     return janet_tuple_end(tup); |     return janet_tuple_end(tup); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -33,8 +33,8 @@ | |||||||
| Janet *janet_tuple_begin(int32_t length) { | Janet *janet_tuple_begin(int32_t length) { | ||||||
|     size_t size = sizeof(JanetTupleHead) + (length * sizeof(Janet)); |     size_t size = sizeof(JanetTupleHead) + (length * sizeof(Janet)); | ||||||
|     JanetTupleHead *head = janet_gcalloc(JANET_MEMORY_TUPLE, size); |     JanetTupleHead *head = janet_gcalloc(JANET_MEMORY_TUPLE, size); | ||||||
|     head->sm_start = -1; |     head->sm_line = -1; | ||||||
|     head->sm_end = -1; |     head->sm_column = -1; | ||||||
|     head->length = length; |     head->length = length; | ||||||
|     return (Janet *)(head->data); |     return (Janet *)(head->data); | ||||||
| } | } | ||||||
| @@ -119,16 +119,16 @@ static Janet cfun_tuple_sourcemap(int32_t argc, Janet *argv) { | |||||||
|     janet_fixarity(argc, 1); |     janet_fixarity(argc, 1); | ||||||
|     const Janet *tup = janet_gettuple(argv, 0); |     const Janet *tup = janet_gettuple(argv, 0); | ||||||
|     Janet contents[2]; |     Janet contents[2]; | ||||||
|     contents[0] = janet_wrap_integer(janet_tuple_head(tup)->sm_start); |     contents[0] = janet_wrap_integer(janet_tuple_head(tup)->sm_line); | ||||||
|     contents[1] = janet_wrap_integer(janet_tuple_head(tup)->sm_end); |     contents[1] = janet_wrap_integer(janet_tuple_head(tup)->sm_column); | ||||||
|     return janet_wrap_tuple(janet_tuple_n(contents, 2)); |     return janet_wrap_tuple(janet_tuple_n(contents, 2)); | ||||||
| } | } | ||||||
|  |  | ||||||
| static Janet cfun_tuple_setmap(int32_t argc, Janet *argv) { | static Janet cfun_tuple_setmap(int32_t argc, Janet *argv) { | ||||||
|     janet_fixarity(argc, 3); |     janet_fixarity(argc, 3); | ||||||
|     const Janet *tup = janet_gettuple(argv, 0); |     const Janet *tup = janet_gettuple(argv, 0); | ||||||
|     janet_tuple_head(tup)->sm_start = janet_getinteger(argv, 1); |     janet_tuple_head(tup)->sm_line = janet_getinteger(argv, 1); | ||||||
|     janet_tuple_head(tup)->sm_end = janet_getinteger(argv, 2); |     janet_tuple_head(tup)->sm_column = janet_getinteger(argv, 2); | ||||||
|     return argv[0]; |     return argv[0]; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -158,16 +158,14 @@ static const JanetReg tuple_cfuns[] = { | |||||||
|     { |     { | ||||||
|         "tuple/sourcemap", cfun_tuple_sourcemap, |         "tuple/sourcemap", cfun_tuple_sourcemap, | ||||||
|         JDOC("(tuple/sourcemap tup)\n\n" |         JDOC("(tuple/sourcemap tup)\n\n" | ||||||
|              "Returns the sourcemap metadata attached to a tuple. " |              "Returns the sourcemap metadata attached to a tuple, " | ||||||
|              "The mapping is represented by a pair of byte offsets into the " |              " which is another tuple (line, column).") | ||||||
|              "the source code representing the start and end byte indices where " |  | ||||||
|              "the tuple is. ") |  | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|         "tuple/setmap", cfun_tuple_setmap, |         "tuple/setmap", cfun_tuple_setmap, | ||||||
|         JDOC("(tuple/setmap tup start end)\n\n" |         JDOC("(tuple/setmap tup line column)\n\n" | ||||||
|              "Set the sourcemap metadata on a tuple. start and end should " |              "Set the sourcemap metadata on a tuple. line and column indicate " | ||||||
|              "be integers representing byte offsets into the file. Returns tup.") |              "should be integers.") | ||||||
|     }, |     }, | ||||||
|     {NULL, NULL, NULL} |     {NULL, NULL, NULL} | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -58,7 +58,7 @@ JANET_THREAD_LOCAL jmp_buf *janet_vm_jmp_buf = NULL; | |||||||
|  * a switch inside an infinite loop. For GCC/clang, we use |  * a switch inside an infinite loop. For GCC/clang, we use | ||||||
|  * computed gotos. */ |  * computed gotos. */ | ||||||
| #if defined(__GNUC__) && !defined(__EMSCRIPTEN__) | #if defined(__GNUC__) && !defined(__EMSCRIPTEN__) | ||||||
| #define JANET_USE_COMPUTED_GOTOS | /*#define JANET_USE_COMPUTED_GOTOS*/ | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #ifdef JANET_USE_COMPUTED_GOTOS | #ifdef JANET_USE_COMPUTED_GOTOS | ||||||
|   | |||||||
| @@ -755,8 +755,8 @@ struct JanetTupleHead { | |||||||
|     JanetGCObject gc; |     JanetGCObject gc; | ||||||
|     int32_t length; |     int32_t length; | ||||||
|     int32_t hash; |     int32_t hash; | ||||||
|     int32_t sm_start; |     int32_t sm_line; | ||||||
|     int32_t sm_end; |     int32_t sm_column; | ||||||
|     const Janet data[]; |     const Janet data[]; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -798,8 +798,8 @@ struct JanetAbstractHead { | |||||||
|  |  | ||||||
| /* Source mapping structure for a bytecode instruction */ | /* Source mapping structure for a bytecode instruction */ | ||||||
| struct JanetSourceMapping { | struct JanetSourceMapping { | ||||||
|     int32_t start; |     int32_t line; | ||||||
|     int32_t end; |     int32_t column; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| /* A function definition. Contains information needed to instantiate closures. */ | /* A function definition. Contains information needed to instantiate closures. */ | ||||||
| @@ -869,7 +869,8 @@ struct JanetParser { | |||||||
|     size_t statecap; |     size_t statecap; | ||||||
|     size_t bufcount; |     size_t bufcount; | ||||||
|     size_t bufcap; |     size_t bufcap; | ||||||
|     size_t offset; |     size_t line; | ||||||
|  |     size_t column; | ||||||
|     size_t pending; |     size_t pending; | ||||||
|     int lookback; |     int lookback; | ||||||
|     int flag; |     int flag; | ||||||
| @@ -1100,7 +1101,7 @@ JANET_API void janet_debug_break(JanetFuncDef *def, int32_t pc); | |||||||
| JANET_API void janet_debug_unbreak(JanetFuncDef *def, int32_t pc); | JANET_API void janet_debug_unbreak(JanetFuncDef *def, int32_t pc); | ||||||
| JANET_API void janet_debug_find( | JANET_API void janet_debug_find( | ||||||
|     JanetFuncDef **def_out, int32_t *pc_out, |     JanetFuncDef **def_out, int32_t *pc_out, | ||||||
|     const uint8_t *source, int32_t offset); |     const uint8_t *source, int32_t line, int32_t column); | ||||||
|  |  | ||||||
| /* Array functions */ | /* Array functions */ | ||||||
| JANET_API JanetArray *janet_array(int32_t capacity); | JANET_API JanetArray *janet_array(int32_t capacity); | ||||||
| @@ -1133,8 +1134,8 @@ JANET_API void janet_buffer_push_u64(JanetBuffer *buffer, uint64_t x); | |||||||
| #define janet_tuple_head(t) ((JanetTupleHead *)((char *)t - offsetof(JanetTupleHead, data))) | #define janet_tuple_head(t) ((JanetTupleHead *)((char *)t - offsetof(JanetTupleHead, data))) | ||||||
| #define janet_tuple_length(t) (janet_tuple_head(t)->length) | #define janet_tuple_length(t) (janet_tuple_head(t)->length) | ||||||
| #define janet_tuple_hash(t) (janet_tuple_head(t)->hash) | #define janet_tuple_hash(t) (janet_tuple_head(t)->hash) | ||||||
| #define janet_tuple_sm_start(t) (janet_tuple_head(t)->sm_start) | #define janet_tuple_sm_line(t) (janet_tuple_head(t)->sm_line) | ||||||
| #define janet_tuple_sm_end(t) (janet_tuple_head(t)->sm_end) | #define janet_tuple_sm_column(t) (janet_tuple_head(t)->sm_column) | ||||||
| #define janet_tuple_flag(t) (janet_tuple_head(t)->gc.flags) | #define janet_tuple_flag(t) (janet_tuple_head(t)->gc.flags) | ||||||
| JANET_API Janet *janet_tuple_begin(int32_t length); | JANET_API Janet *janet_tuple_begin(int32_t length); | ||||||
| JANET_API const Janet *janet_tuple_end(Janet *tuple); | JANET_API const Janet *janet_tuple_end(Janet *tuple); | ||||||
|   | |||||||
| @@ -80,8 +80,8 @@ | |||||||
|       (print "Janet " janet/version "-" janet/build "  Copyright (C) 2017-2019 Calvin Rose")) |       (print "Janet " janet/version "-" janet/build "  Copyright (C) 2017-2019 Calvin Rose")) | ||||||
|     (defn noprompt [_] "") |     (defn noprompt [_] "") | ||||||
|     (defn getprompt [p] |     (defn getprompt [p] | ||||||
|       (def offset (parser/where p)) |       (def [line] (parser/where p)) | ||||||
|       (string "janet:" offset ":" (parser/state p :delimiters) "> ")) |       (string "janet:" line ":" (parser/state p :delimiters) "> ")) | ||||||
|     (def prompter (if *quiet* noprompt getprompt)) |     (def prompter (if *quiet* noprompt getprompt)) | ||||||
|     (defn getstdin [prompt buf] |     (defn getstdin [prompt buf] | ||||||
|       (file/write stdout prompt) |       (file/write stdout prompt) | ||||||
|   | |||||||
| @@ -155,5 +155,12 @@ | |||||||
| (assert (= (|(+ $1 $1 $1 $1) 2 4) 16) "function shorthand 8") | (assert (= (|(+ $1 $1 $1 $1) 2 4) 16) "function shorthand 8") | ||||||
| (assert (= (|(+ $0 $1 $3 $2 $6) 0 1 2 3 4 5 6) 12) "function shorthand 9") | (assert (= (|(+ $0 $1 $3 $2 $6) 0 1 2 3 4 5 6) 12) "function shorthand 9") | ||||||
|  |  | ||||||
|  | # Simple function break | ||||||
|  | (debug/fbreak map) | ||||||
|  | (def f (fiber/new (fn [] (map inc [1 2 3])) :a)) | ||||||
|  | (resume f) | ||||||
|  | (assert (= :debug (fiber/status f)) "debug/fbreak") | ||||||
|  | (debug/unfbreak map) | ||||||
|  | (map inc [1 2 3]) | ||||||
|  |  | ||||||
| (end-suite) | (end-suite) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Calvin Rose
					Calvin Rose