mirror of
				https://github.com/janet-lang/janet
				synced 2025-10-31 15:43:01 +00:00 
			
		
		
		
	More work on renaming functions. Change long string syntax to use
backticks. Allow custom masks in fibers for custom error and debug handling.
This commit is contained in:
		| @@ -908,8 +908,8 @@ int dst_disasm_cfun(DstArgs args) { | ||||
| } | ||||
|  | ||||
| static const DstReg cfuns[] = { | ||||
|     {"asm/asm", dst_asm_cfun}, | ||||
|     {"asm/disasm", dst_disasm_cfun}, | ||||
|     {"asm.asm", dst_asm_cfun}, | ||||
|     {"asm.disasm", dst_disasm_cfun}, | ||||
|     {NULL, NULL} | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -257,7 +257,7 @@ evaluates to true." | ||||
| (defmacro coro | ||||
|  "A wrapper for making fibers. Same as (fiber (fn [] ...body))." | ||||
|  [& body] | ||||
|  (tuple fiber (apply tuple 'fn [] body))) | ||||
|  (tuple fiber.new (apply tuple 'fn [] body))) | ||||
|  | ||||
| (defmacro if-let | ||||
| "Takes the first one or two forms in a vector and if both are true binds | ||||
| @@ -868,7 +868,7 @@ onvalue." | ||||
|  (var going true) | ||||
|  | ||||
|  # The parser object | ||||
|  (def p (parser.make 1)) | ||||
|  (def p (parser.new 1)) | ||||
|  | ||||
|  # Fiber stream of characters | ||||
|  (def chars (coro | ||||
| @@ -879,18 +879,18 @@ onvalue." | ||||
|       (chunks buf p) | ||||
|       (:= len (length buf)) | ||||
|       (for [i 0 len] | ||||
|         (yield (get buf i)))) | ||||
|         (fiber.yield (get buf i)))) | ||||
|    0)) | ||||
|  | ||||
|  # Fiber stream of values | ||||
|  (def vals (coro | ||||
|   (while going | ||||
|     (switch (parser.status p) | ||||
|      :full (yield (parser.produce p)) | ||||
|      :full (fiber.yield (parser.produce p)) | ||||
|      :error (onerr "parse" (parser.error p)) | ||||
|      (switch (fiber.status chars) | ||||
|       :new (parser.byte p (resume chars)) | ||||
|       :pending (parser.byte p (resume chars)) | ||||
|       :new (parser.byte p (fiber.resume chars)) | ||||
|       :pending (parser.byte p (fiber.resume chars)) | ||||
|       (:= going false)))) | ||||
|   (when (not= :root (parser.status p)) | ||||
|    (onerr "parse" "unexpected end of source")))) | ||||
| @@ -898,23 +898,24 @@ onvalue." | ||||
|  # Evaluate 1 source form | ||||
|  (defn eval1 [source] | ||||
|   (var good true) | ||||
|   (def f (coro | ||||
|   (def f (fiber.new (fn [] | ||||
|     (def res (compile source env)) | ||||
|     (if (= (type res) :function) | ||||
|       (res) | ||||
|       (do | ||||
|        (:= good false) | ||||
|        (onerr "compile" (get res :error)))))) | ||||
|   (def res (resume f)) | ||||
|        (onerr "compile" (get res :error))))) :de)) | ||||
|   (def res (fiber.resume f)) | ||||
|   (if good | ||||
|    (if (= (fiber.status f) :error) | ||||
|     (onerr "runtime" res f) | ||||
|     (if going (onvalue res))))) | ||||
|    (cond | ||||
|     (= (fiber.status f) :error) (onerr "runtime" res f) | ||||
|     (= (fiber.status f) :debug) (onerr "debug" res f) | ||||
|     going (onvalue res)))) | ||||
|  | ||||
|  # Run loop | ||||
|  (def oldenv *env*) | ||||
|  (:= *env* env) | ||||
|  (while going (eval1 (resume vals))) | ||||
|  (while going (eval1 (fiber.resume vals))) | ||||
|  (:= *env* oldenv) | ||||
|  | ||||
|  env) | ||||
|   | ||||
| @@ -45,7 +45,6 @@ static const DstReg cfuns[] = { | ||||
|     {"scan-real", dst_core_scanreal}, | ||||
|     {"tuple", dst_core_tuple}, | ||||
|     {"struct", dst_core_struct}, | ||||
|     {"fiber", dst_core_fiber}, | ||||
|     {"buffer", dst_core_buffer}, | ||||
|     {"gensym", dst_core_gensym}, | ||||
|     {"get", dst_core_get}, | ||||
| @@ -65,32 +64,23 @@ DstTable *dst_stl_env() { | ||||
|     static uint32_t error_asm[] = { | ||||
|         DOP_ERROR | ||||
|     }; | ||||
|  | ||||
|     static uint32_t apply_asm[] = { | ||||
|        DOP_PUSH_ARRAY | (1 << 8), | ||||
|        DOP_TAILCALL | ||||
|     }; | ||||
|  | ||||
|     static uint32_t yield_asm[] = { | ||||
|         DOP_YIELD, | ||||
|         DOP_RETURN | ||||
|     static uint32_t debug_asm[] = { | ||||
|        DOP_DEBUG, | ||||
|        DOP_RETURN_NIL | ||||
|     }; | ||||
|  | ||||
|     static uint32_t resume_asm[] = { | ||||
|         DOP_RESUME | (1 << 24), | ||||
|         DOP_RETURN | ||||
|     }; | ||||
|  | ||||
|     DstTable *env = dst_table(0); | ||||
|     Dst ret = dst_wrap_table(env); | ||||
|  | ||||
|     /* Load main functions */ | ||||
|     dst_env_cfuns(env, cfuns); | ||||
|  | ||||
|     dst_env_def(env, "debug", dst_wrap_function(dst_quick_asm(0, 0, 0, debug_asm, sizeof(debug_asm)))); | ||||
|     dst_env_def(env, "error", dst_wrap_function(dst_quick_asm(1, 0, 1, error_asm, sizeof(error_asm)))); | ||||
|     dst_env_def(env, "apply1", dst_wrap_function(dst_quick_asm(2, 0, 2, apply_asm, sizeof(apply_asm)))); | ||||
|     dst_env_def(env, "yield", dst_wrap_function(dst_quick_asm(1, 0, 2, yield_asm, sizeof(yield_asm)))); | ||||
|     dst_env_def(env, "resume", dst_wrap_function(dst_quick_asm(2, 0, 2, resume_asm, sizeof(resume_asm)))); | ||||
|  | ||||
|     dst_env_def(env, "VERSION", dst_cstringv(DST_VERSION)); | ||||
|  | ||||
|   | ||||
| @@ -105,6 +105,15 @@ Dst dst_array_peek(DstArray *array) { | ||||
|  | ||||
| /* C Functions */ | ||||
|  | ||||
| static int cfun_new(DstArgs args) { | ||||
|     int32_t cap; | ||||
|     DstArray *array; | ||||
|     dst_fixarity(args, 1); | ||||
|     dst_arg_integer(cap, args, 0); | ||||
|     array = dst_array(cap); | ||||
|     return dst_return(args, dst_wrap_array(array)); | ||||
| } | ||||
|  | ||||
| static int cfun_pop(DstArgs args) { | ||||
|     dst_fixarity(args, 1); | ||||
|     dst_check(args, 0, DST_ARRAY); | ||||
| @@ -219,6 +228,7 @@ static int cfun_concat(DstArgs args) { | ||||
| } | ||||
|  | ||||
| static const DstReg cfuns[] = { | ||||
|     {"array.new", cfun_new}, | ||||
|     {"array.pop", cfun_pop}, | ||||
|     {"array.peek", cfun_peek}, | ||||
|     {"array.push", cfun_push}, | ||||
|   | ||||
| @@ -157,6 +157,16 @@ int dst_buffer_push_u64(DstBuffer *buffer, uint64_t x) { | ||||
| } | ||||
|  | ||||
| /* C functions */ | ||||
|  | ||||
| static int cfun_new(DstArgs args) { | ||||
|     int32_t cap; | ||||
|     DstBuffer *buffer; | ||||
|     dst_fixarity(args, 1); | ||||
|     dst_arg_integer(cap, args, 0); | ||||
|     buffer = dst_buffer(cap); | ||||
|     return dst_return(args, dst_wrap_buffer(buffer)); | ||||
| } | ||||
|  | ||||
| static int cfun_u8(DstArgs args) { | ||||
|     int32_t i; | ||||
|     DstBuffer *buffer; | ||||
| @@ -258,6 +268,7 @@ static int cfun_slice(DstArgs args) { | ||||
| } | ||||
|  | ||||
| static const DstReg cfuns[] = { | ||||
|     {"buffer.new", cfun_new}, | ||||
|     {"buffer.push-byte", cfun_u8}, | ||||
|     {"buffer.push-integer", cfun_int}, | ||||
|     {"buffer.push-string", cfun_chars}, | ||||
|   | ||||
| @@ -202,14 +202,6 @@ int dst_core_struct(DstArgs args) { | ||||
|     return dst_return(args, dst_wrap_struct(dst_struct_end(st))); | ||||
| } | ||||
|  | ||||
| int dst_core_fiber(DstArgs args) { | ||||
|     DstFiber *fiber; | ||||
|     dst_fixarity(args, 1); | ||||
|     dst_check(args, 0, DST_FUNCTION); | ||||
|     fiber = dst_fiber(dst_unwrap_function(args.v[0]), 64); | ||||
|     return dst_return(args, dst_wrap_fiber(fiber)); | ||||
| } | ||||
|  | ||||
| int dst_core_gensym(DstArgs args) { | ||||
|     dst_maxarity(args, 1); | ||||
|     if (args.n == 0) { | ||||
|   | ||||
| @@ -21,6 +21,7 @@ | ||||
| */ | ||||
|  | ||||
| #include <dst/dst.h> | ||||
| #include <dst/dstopcodes.h> | ||||
| #include "fiber.h" | ||||
| #include "gc.h" | ||||
|  | ||||
| @@ -257,6 +258,35 @@ void dst_fiber_popframe(DstFiber *fiber) { | ||||
|  | ||||
| /* CFuns */ | ||||
|  | ||||
| static int cfun_new(DstArgs args) { | ||||
|     DstFiber *fiber; | ||||
|     dst_minarity(args, 1); | ||||
|     dst_maxarity(args, 2); | ||||
|     dst_check(args, 0, DST_FUNCTION); | ||||
|     fiber = dst_fiber(dst_unwrap_function(args.v[0]), 64); | ||||
|     if (args.n == 2) { | ||||
|         const uint8_t *flags; | ||||
|         int32_t len, i; | ||||
|         dst_arg_bytes(flags, len, args, 1); | ||||
|         fiber->flags |= DST_FIBER_MASK_ERROR; | ||||
|         for (i = 0; i < len; i++) { | ||||
|             switch (flags[i]) { | ||||
|                 default: | ||||
|                     return dst_throw(args, "invalid flag, expected d or e"); | ||||
|                 case ':': | ||||
|                     break; | ||||
|                 case 'd': | ||||
|                     fiber->flags &= ~DST_FIBER_MASK_DEBUG; | ||||
|                     break; | ||||
|                 case 'e': | ||||
|                     fiber->flags &= ~DST_FIBER_MASK_ERROR; | ||||
|                     break; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     return dst_return(args, dst_wrap_fiber(fiber)); | ||||
| } | ||||
|  | ||||
| static int cfun_status(DstArgs args) { | ||||
|     const char *status = ""; | ||||
|     dst_fixarity(args, 1); | ||||
| @@ -338,6 +368,7 @@ static int cfun_stack(DstArgs args) { | ||||
| } | ||||
|  | ||||
| static const DstReg cfuns[] = { | ||||
|     {"fiber.new", cfun_new}, | ||||
|     {"fiber.status", cfun_status}, | ||||
|     {"fiber.stack", cfun_stack}, | ||||
|     {NULL, NULL} | ||||
| @@ -345,7 +376,21 @@ static const DstReg cfuns[] = { | ||||
|  | ||||
| /* Module entry point */ | ||||
| int dst_lib_fiber(DstArgs args) { | ||||
|     static uint32_t yield_asm[] = { | ||||
|         DOP_YIELD, | ||||
|         DOP_RETURN | ||||
|     }; | ||||
|     static uint32_t resume_asm[] = { | ||||
|         DOP_RESUME | (1 << 24), | ||||
|         DOP_RETURN | ||||
|     }; | ||||
|     DstTable *env = dst_env_arg(args); | ||||
|     dst_env_cfuns(env, cfuns); | ||||
|     dst_env_def(env, "fiber.yield",  | ||||
|             dst_wrap_function(dst_quick_asm(1, 0, 2, | ||||
|                     yield_asm, sizeof(yield_asm)))); | ||||
|     dst_env_def(env, "fiber.resume", | ||||
|             dst_wrap_function(dst_quick_asm(2, 0, 2, | ||||
|                     resume_asm, sizeof(resume_asm)))); | ||||
|     return 0; | ||||
| } | ||||
|   | ||||
| @@ -235,6 +235,17 @@ void dst_table_merge_struct(DstTable *table, const DstKV *other) { | ||||
|     dst_table_mergekv(table, other, dst_struct_capacity(other)); | ||||
| } | ||||
|  | ||||
| /* C Functions */ | ||||
|  | ||||
| static int cfun_new(DstArgs args) { | ||||
|     DstTable *t; | ||||
|     int32_t cap; | ||||
|     dst_fixarity(args, 1); | ||||
|     dst_arg_integer(cap, args, 0); | ||||
|     t = dst_table(cap); | ||||
|     return dst_return(args, dst_wrap_table(t)); | ||||
| } | ||||
|  | ||||
| static int cfun_getproto(DstArgs args) { | ||||
|     DstTable *t; | ||||
|     dst_fixarity(args, 1); | ||||
| @@ -269,6 +280,7 @@ static int cfun_rawget(DstArgs args) { | ||||
| } | ||||
|  | ||||
| static const DstReg cfuns[] = { | ||||
|     {"table.new", cfun_new}, | ||||
|     {"table.to-struct", cfun_tostruct}, | ||||
|     {"table.getproto", cfun_getproto}, | ||||
|     {"table.setproto", cfun_setproto}, | ||||
|   | ||||
| @@ -255,6 +255,7 @@ int32_t dst_length(Dst x) { | ||||
|         default: | ||||
|             return 0; | ||||
|         case DST_STRING: | ||||
|         case DST_SYMBOL: | ||||
|             return dst_string_length(dst_unwrap_string(x)); | ||||
|         case DST_ARRAY: | ||||
|             return dst_unwrap_array(x)->count; | ||||
| @@ -275,6 +276,7 @@ Dst dst_getindex(Dst ds, int32_t index) { | ||||
|         default: | ||||
|             return dst_wrap_nil(); | ||||
|         case DST_STRING: | ||||
|         case DST_SYMBOL: | ||||
|             if (index >= dst_string_length(dst_unwrap_string(ds))) return dst_wrap_nil(); | ||||
|             return dst_wrap_integer(dst_unwrap_string(ds)[index]); | ||||
|         case DST_ARRAY: | ||||
|   | ||||
| @@ -750,7 +750,6 @@ static void *op_lookup[255] = { | ||||
|                 break; | ||||
|             default: | ||||
|                 fiber->child = NULL; | ||||
|                 if (nextfiber->flags & DST_FIBER_MASK_RETURN) goto vm_return_root; | ||||
|                 break; | ||||
|         } | ||||
|         stack[oparg(1, 0xFF)] = retreg; | ||||
| @@ -844,6 +843,7 @@ static void *op_lookup[255] = { | ||||
|     vm_debug: | ||||
|     { | ||||
|         fiber->status = DST_FIBER_DEBUG; | ||||
|         retreg = dst_wrap_nil(); | ||||
|         goto vm_exit; | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -92,7 +92,6 @@ int dst_core_tuple(DstArgs args); | ||||
| int dst_core_array(DstArgs args); | ||||
| int dst_core_table(DstArgs args); | ||||
| int dst_core_struct(DstArgs args); | ||||
| int dst_core_fiber(DstArgs args); | ||||
| int dst_core_buffer(DstArgs args); | ||||
| int dst_core_gensym(DstArgs args); | ||||
| int dst_core_length(DstArgs args); | ||||
|   | ||||
| @@ -338,12 +338,12 @@ struct DstArgs { | ||||
|     Dst *ret; | ||||
| }; | ||||
|  | ||||
| /* Fiber signal masks */ | ||||
| #define DST_FIBER_MASK_RETURN 1 | ||||
| #define DST_FIBER_MASK_ERROR 2 | ||||
| #define DST_FIBER_MASK_DEBUG 4 | ||||
| /* Fiber flags */ | ||||
| #define DST_FIBER_FLAG_NEW (1 << 31) | ||||
|  | ||||
| #define DST_FIBER_FLAG_NEW 8 | ||||
| /* Fiber signal masks. Should not overlap any fiber flags. */ | ||||
| #define DST_FIBER_MASK_ERROR 1 | ||||
| #define DST_FIBER_MASK_DEBUG 2 | ||||
|  | ||||
| /* A lightweight green thread in dst. Does not correspond to | ||||
|  * operating system threads. */ | ||||
|   | ||||
| @@ -6,24 +6,24 @@ | ||||
|  | ||||
| # Flag handlers | ||||
| (def handlers :private { | ||||
|     "h" (fn []  | ||||
|               (print "usage: " (get args 0) " [options] scripts...") | ||||
|               (print "Options are:") | ||||
|               (print "  -h Show this help") | ||||
|               (print "  -v Print the version string") | ||||
|               (print "  -s Use raw stdin instead of getline like functionality") | ||||
|               (print "  -e Execute a string of dst") | ||||
|               (print "  -r Enter the repl after running all scripts") | ||||
|               (os.exit 0) | ||||
|               1) | ||||
|       "v" (fn [] (print VERSION) (os.exit 0) 1) | ||||
|       "s" (fn [] (:= *raw-stdin* true) (:= *should-repl* true) 1) | ||||
|       "r" (fn [] (:= *should-repl* true) 1) | ||||
|       "e" (fn [i]  | ||||
|               (:= *no-file* false) | ||||
|               (eval (get args (+ i 1))) | ||||
|               2) | ||||
|       }) | ||||
|   "h" (fn []  | ||||
|     (print "usage: " (get args 0) " [options] scripts...") | ||||
|     (print "Options are:") | ||||
|     (print "  -h Show this help") | ||||
|     (print "  -v Print the version string") | ||||
|     (print "  -s Use raw stdin instead of getline like functionality") | ||||
|     (print "  -e Execute a string of dst") | ||||
|     (print "  -r Enter the repl after running all scripts") | ||||
|     (os.exit 0) | ||||
|     1) | ||||
|   "v" (fn [] (print VERSION) (os.exit 0) 1) | ||||
|   "s" (fn [] (:= *raw-stdin* true) (:= *should-repl* true) 1) | ||||
|   "r" (fn [] (:= *should-repl* true) 1) | ||||
|   "e" (fn [i]  | ||||
|     (:= *no-file* false) | ||||
|     (eval (get args (+ i 1))) | ||||
|     2) | ||||
| }) | ||||
|  | ||||
| (defn- dohandler [n i] | ||||
|   (def h (get handlers n)) | ||||
| @@ -33,13 +33,13 @@ | ||||
| (var i 1) | ||||
| (def lenargs (length args)) | ||||
| (while (< i lenargs) | ||||
|        (def arg (get args i)) | ||||
|        (if (= "-" (string.slice arg 0 1)) | ||||
|          (+= i (dohandler (string.slice arg 1 2) i)) | ||||
|          (do | ||||
|            (:= *no-file* false) | ||||
|            (import arg) | ||||
|            (++ i)))) | ||||
|   (def arg (get args i)) | ||||
|   (if (= "-" (string.slice arg 0 1)) | ||||
|     (+= i (dohandler (string.slice arg 1 2) i)) | ||||
|     (do | ||||
|       (:= *no-file* false) | ||||
|       (import arg) | ||||
|       (++ i)))) | ||||
|  | ||||
| (when (or *should-repl* *no-file*)  | ||||
|   (if *raw-stdin* | ||||
| @@ -47,5 +47,7 @@ | ||||
|     (do | ||||
|       (print (string "Dst " VERSION "  Copyright (C) 2017-2018 Calvin Rose")) | ||||
|       (repl (fn [buf p] | ||||
|                 (def prompt (string (parser.state p) "> ")) | ||||
|                 (getline prompt buf))))))) | ||||
|         (def prompt (string (parser.state p) "> ")) | ||||
|         (getline prompt buf)))))) | ||||
|  | ||||
| ) | ||||
|   | ||||
| @@ -381,10 +381,10 @@ static int dotable(DstParser *p, DstParseState *state, uint8_t c) { | ||||
| static int longstring(DstParser *p, DstParseState *state, uint8_t c) { | ||||
|     if (state->flags & PFLAG_INSTRING) { | ||||
|         /* We are inside the long string */ | ||||
|         if (c == '\\') { | ||||
|         if (c == '`') { | ||||
|             state->flags |= PFLAG_END_CANDIDATE; | ||||
|             state->flags &= ~PFLAG_INSTRING; | ||||
|             state->qcount = 0; /* Use qcount to keep track of number of '=' seen */ | ||||
|             state->qcount = 1; /* Use qcount to keep track of number of '=' seen */ | ||||
|             return 1; | ||||
|         } | ||||
|         dst_v_push(p->buf, c); | ||||
| @@ -392,17 +392,17 @@ static int longstring(DstParser *p, DstParseState *state, uint8_t c) { | ||||
|     } else if (state->flags & PFLAG_END_CANDIDATE) { | ||||
|         int i; | ||||
|         /* We are checking a potential end of the string */ | ||||
|         if (c == '\\' && state->qcount == state->argn) { | ||||
|             return stringend(p, state); | ||||
|         if (c != '`' && state->qcount == state->argn) { | ||||
|             stringend(p, state); | ||||
|             return 0; | ||||
|         } | ||||
|         if (c == '=' && state->qcount < state->argn) { | ||||
|         if (c == '`' && state->qcount < state->argn) { | ||||
|             state->qcount++; | ||||
|             return 1; | ||||
|         } | ||||
|         /* Failed end candidate */ | ||||
|         dst_v_push(p->buf, '\\'); | ||||
|         for (i = 0; i < state->qcount; i++) { | ||||
|             dst_v_push(p->buf, '='); | ||||
|             dst_v_push(p->buf, '`'); | ||||
|         } | ||||
|         dst_v_push(p->buf, c); | ||||
|         state->qcount = 0; | ||||
| @@ -411,17 +411,12 @@ static int longstring(DstParser *p, DstParseState *state, uint8_t c) { | ||||
|         return 1; | ||||
|     } else { | ||||
|         /* We are at beginning of string */ | ||||
|         switch (c) { | ||||
|             default: | ||||
|                 p->error = "unexpected character in long string delimiter"; | ||||
|                 return 1; | ||||
|             case '\\': | ||||
|                 state->flags |= PFLAG_INSTRING; | ||||
|                 return 1; | ||||
|             case '=': | ||||
|                 state->argn++; | ||||
|                 return 1; | ||||
|         state->argn++; | ||||
|         if (c != '`') { | ||||
|             state->flags |= PFLAG_INSTRING; | ||||
|             dst_v_push(p->buf, c); | ||||
|         } | ||||
|         return 1; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -435,7 +430,7 @@ static int ampersand(DstParser *p, DstParseState *state, uint8_t c) { | ||||
|     case '"': | ||||
|         pushstate(p, stringchar, PFLAG_BUFFER | PFLAG_STRING); | ||||
|         return 1; | ||||
|     case '\\': | ||||
|     case '`': | ||||
|         pushstate(p, longstring, PFLAG_BUFFER | PFLAG_LONGSTRING); | ||||
|         return 1; | ||||
|     case '[': | ||||
| @@ -474,7 +469,7 @@ static int root(DstParser *p, DstParseState *state, uint8_t c) { | ||||
|         case '@': | ||||
|             pushstate(p, ampersand, 0); | ||||
|             return 1; | ||||
|         case '\\': | ||||
|         case '`': | ||||
|             pushstate(p, longstring, PFLAG_LONGSTRING); | ||||
|             return 1; | ||||
|         case ')': | ||||
| @@ -769,7 +764,7 @@ static int cfun_node(DstArgs args) { | ||||
| } | ||||
|  | ||||
| static const DstReg cfuns[] = { | ||||
|     {"parser.make", cfun_parser}, | ||||
|     {"parser.new", cfun_parser}, | ||||
|     {"parser.produce", cfun_produce}, | ||||
|     {"parser.consume", cfun_consume}, | ||||
|     {"parser.byte", cfun_byte}, | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Calvin Rose
					Calvin Rose