mirror of
				https://github.com/janet-lang/janet
				synced 2025-10-31 07:33:01 +00:00 
			
		
		
		
	Remove lots of headers. Add parse c function.
This commit is contained in:
		| @@ -21,7 +21,6 @@ | ||||
| */ | ||||
|  | ||||
| #include <gst/gst.h> | ||||
| #include <gst/compile.h> | ||||
|  | ||||
| /* During compilation, FormOptions are passed to ASTs | ||||
|  * as configuration options to allow for some optimizations. */ | ||||
| @@ -1209,35 +1208,4 @@ GstFunction *gst_compiler_compile(GstCompiler *c, GstValue form) { | ||||
|         func->env = env; | ||||
|         return func; | ||||
|     } | ||||
| } | ||||
|  | ||||
| /***/ | ||||
| /* Stl */ | ||||
| /***/ | ||||
|  | ||||
| /* Compile a value */ | ||||
| static int gst_stl_compile(Gst *vm) { | ||||
|     GstFunction *ret; | ||||
|     GstValue std; | ||||
| 	GstCompiler c; | ||||
|     gst_compiler(&c, vm); | ||||
|     std = gst_table_get(vm->modules, gst_string_cv(vm, "std")); | ||||
|     gst_compiler_globals(&c, std); | ||||
|     gst_compiler_globals(&c, gst_arg(vm, 1)); | ||||
|     gst_compiler_nilglobals(&c, gst_arg(vm, 2)); | ||||
|     ret = gst_compiler_compile(&c, gst_arg(vm, 0)); | ||||
|     if (!ret) | ||||
|         gst_c_throw(vm, c.error); | ||||
|     gst_c_return(vm, gst_wrap_function(ret)); | ||||
| } | ||||
|  | ||||
| /* The module stuff */ | ||||
| static const GstModuleItem gst_compile_module[] = { | ||||
|     {"compile", gst_stl_compile}, | ||||
|     {NULL, NULL} | ||||
| }; | ||||
|  | ||||
| /* Load compiler library */ | ||||
| void gst_compile_load(Gst *vm) { | ||||
|     gst_module(vm, "std.compile", gst_compile_module); | ||||
| } | ||||
| } | ||||
							
								
								
									
										194
									
								
								core/disasm.c
									
									
									
									
									
								
							
							
						
						
									
										194
									
								
								core/disasm.c
									
									
									
									
									
								
							| @@ -1,194 +0,0 @@ | ||||
| /* | ||||
| * Copyright (c) 2017 Calvin Rose | ||||
| *  | ||||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| * of this software and associated documentation files (the "Software"), to | ||||
| * deal in the Software without restriction, including without limitation the | ||||
| * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | ||||
| * sell copies of the Software, and to permit persons to whom the Software is | ||||
| * furnished to do so, subject to the following conditions: | ||||
| *  | ||||
| * The above copyright notice and this permission notice shall be included in | ||||
| * all copies or substantial portions of the Software. | ||||
| *  | ||||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||||
| * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||||
| * IN THE SOFTWARE. | ||||
| */ | ||||
|  | ||||
| #include <gst/disasm.h> | ||||
|  | ||||
| /* Width of padded opcode names */ | ||||
| #define OP_WIDTH 20 | ||||
|  | ||||
| /* Print various register and arguments to instructions */ | ||||
| static void dasm_print_slot(FILE *out, uint16_t index) { fprintf(out, "%d ", index); } | ||||
| static void dasm_print_i16(FILE *out, int16_t number) { fprintf(out, "#%d ", number); } | ||||
| static void dasm_print_i32(FILE *out, int32_t number) { fprintf(out, "#%d ", number); } | ||||
| static void dasm_print_f64(FILE *out, double number) { fprintf(out, "#%f ", number); } | ||||
| static void dasm_print_literal(FILE *out, uint16_t index) { fprintf(out, "(%d) ", index); } | ||||
| static void dasm_print_upvalue(FILE *out, uint16_t level, uint16_t index) { | ||||
|     fprintf(out, "<%d, %d> ", level, index); | ||||
| } | ||||
|  | ||||
| /* Print the name of the argument but pad it */ | ||||
| static void dasm_print_arg(FILE *out, const char *name) {  | ||||
|     uint32_t i = 0; | ||||
|     char c; | ||||
|     while ((c = *name++)) { | ||||
|         putc(c, out); | ||||
|         ++i; | ||||
|     } | ||||
|     for (; i < OP_WIDTH; ++i) | ||||
|         fputc(' ', out); | ||||
| } | ||||
|  | ||||
| /* Print instructions that take a fixed number of arguments */ | ||||
| static uint32_t dasm_fixed_op(FILE *out, const uint16_t *current, | ||||
|         const char * name, uint32_t size) { | ||||
|     uint32_t i; | ||||
|     dasm_print_arg(out, name); | ||||
|     for (i = 1; i <= size; ++i) | ||||
|         dasm_print_slot(out, current[i]); | ||||
|     return size + 1; | ||||
| } | ||||
|  | ||||
| /* Print instructions that take a variable number of arguments */ | ||||
| static uint32_t dasm_varg_op(FILE *out, const uint16_t *current, | ||||
|         const char * name, uint32_t extra) { | ||||
|     uint32_t i, argCount; | ||||
|     dasm_print_arg(out, name); | ||||
|     for (i = 0; i < extra; ++i) { | ||||
|         dasm_print_slot(out, current[i + 1]); | ||||
|     } | ||||
|     argCount = current[extra + 1]; | ||||
|     if (extra) | ||||
|         fprintf(out, ": "); /* Argument separator */ | ||||
|     for (i = 0; i < argCount; ++i) { | ||||
|         dasm_print_slot(out, current[i + extra + 2]); | ||||
|     } | ||||
|     return argCount + extra + 2; | ||||
| } | ||||
|  | ||||
| /* Print the disassembly for a function definition */ | ||||
| void gst_dasm_funcdef(FILE *out, GstFuncDef *def) { | ||||
|     gst_dasm(out, def->byteCode, def->byteCodeLen); | ||||
| } | ||||
|  | ||||
| /* Print the disassembly for a function */ | ||||
| void gst_dasm_function(FILE *out, GstFunction *f) { | ||||
|     gst_dasm(out, f->def->byteCode, f->def->byteCodeLen); | ||||
| } | ||||
|  | ||||
| /* Disassemble some bytecode and display it as opcode + arguments assembly */ | ||||
| void gst_dasm(FILE *out, uint16_t *byteCode, uint32_t len) { | ||||
|     uint16_t *current = byteCode; | ||||
|     uint16_t *end = byteCode + len; | ||||
|  | ||||
|     while (current < end) { | ||||
|         switch (*current) { | ||||
|             default: | ||||
|                 current += dasm_fixed_op(out, current, "unknown", 0); | ||||
|                 break; | ||||
|             case GST_OP_FLS: | ||||
|                 current += dasm_fixed_op(out, current, "loadFalse", 1); | ||||
|                 break; | ||||
|             case GST_OP_TRU: | ||||
|                 current += dasm_fixed_op(out, current, "loadTrue", 1); | ||||
|                 break; | ||||
|             case GST_OP_NIL: | ||||
|                 current += dasm_fixed_op(out, current, "loadNil", 1); | ||||
|                 break; | ||||
|             case GST_OP_I16: | ||||
|                 dasm_print_arg(out, "loadInt16"); | ||||
|                 dasm_print_slot(out, current[1]); | ||||
|                 dasm_print_i16(out, ((int16_t *)current)[2]); | ||||
|                 current += 3; | ||||
|                 break; | ||||
|             case GST_OP_UPV: | ||||
|                 dasm_print_arg(out, "loadUpValue"); | ||||
|                 dasm_print_slot(out, current[1]); | ||||
|                 dasm_print_upvalue(out, current[2], current[3]); | ||||
|                 current += 4; | ||||
|                 break; | ||||
|             case GST_OP_JIF: | ||||
|                 dasm_print_arg(out, "jumpIf"); | ||||
|                 dasm_print_slot(out, current[1]); | ||||
|                 dasm_print_i32(out, ((int32_t *)(current + 2))[0]); | ||||
|                 current += 4; | ||||
|                 break; | ||||
|             case GST_OP_JMP: | ||||
|                 dasm_print_arg(out, "jump"); | ||||
|                 dasm_print_i32(out, ((int32_t *)(current + 1))[0]); | ||||
|                 current += 3; | ||||
|                 break; | ||||
|             case GST_OP_SUV: | ||||
|                 dasm_print_arg(out, "setUpValue"); | ||||
|                 dasm_print_slot(out, current[1]); | ||||
|                 dasm_print_upvalue(out, current[2], current[3]); | ||||
|                 current += 4; | ||||
|                 break; | ||||
|             case GST_OP_CST: | ||||
|                 dasm_print_arg(out, "loadLiteral"); | ||||
|                 dasm_print_slot(out, current[1]); | ||||
|                 dasm_print_literal(out, current[2]); | ||||
|                 current += 3; | ||||
|                 break; | ||||
|             case GST_OP_I32: | ||||
|                 dasm_print_arg(out, "loadInt32"); | ||||
|                 dasm_print_slot(out, current[1]); | ||||
|                 dasm_print_i32(out, ((int32_t *)(current + 2))[0]); | ||||
|                 current += 4; | ||||
|                 break; | ||||
|             case GST_OP_F64: | ||||
|                 dasm_print_arg(out, "loadFloat64"); | ||||
|                 dasm_print_slot(out, current[1]); | ||||
|                 dasm_print_f64(out, ((double *)(current + 2))[0]); | ||||
|                 current += 6; | ||||
|                 break; | ||||
|             case GST_OP_MOV: | ||||
|                 current += dasm_fixed_op(out, current, "move", 2); | ||||
|                 break; | ||||
|             case GST_OP_CLN: | ||||
|                 dasm_print_arg(out, "makeClosure"); | ||||
|                 dasm_print_slot(out, current[1]); | ||||
|                 dasm_print_literal(out, current[2]); | ||||
|                 current += 3; | ||||
|                 break; | ||||
|             case GST_OP_ARR: | ||||
|                 current += dasm_varg_op(out, current, "array", 1); | ||||
|                 break; | ||||
|             case GST_OP_DIC: | ||||
|                 current += dasm_varg_op(out, current, "table", 1); | ||||
|                 break; | ||||
|             case GST_OP_TUP: | ||||
|                 current += dasm_varg_op(out, current, "tuple", 1); | ||||
|                 break; | ||||
|             case GST_OP_RET: | ||||
|                 current += dasm_fixed_op(out, current, "return", 1); | ||||
|                 break; | ||||
|             case GST_OP_RTN: | ||||
|                 current += dasm_fixed_op(out, current, "returnNil", 0); | ||||
|                 break; | ||||
|             case GST_OP_PSK: | ||||
|                 current += dasm_varg_op(out, current, "pushArgs", 0); | ||||
|                 break; | ||||
|             case GST_OP_PAR: | ||||
|                 current += dasm_fixed_op(out, current, "pushSeq", 1); | ||||
|                 break; | ||||
|             case GST_OP_CAL: | ||||
|                 current += dasm_fixed_op(out, current, "call", 2); | ||||
|                 break; | ||||
|             case GST_OP_TCL: | ||||
|                 current += dasm_fixed_op(out, current, "tailCall", 1); | ||||
|                 break; | ||||
|             case GST_OP_TRN: | ||||
|                 current += dasm_fixed_op(out, current, "transfer", 3); | ||||
|         } | ||||
|         fprintf(out, "\n"); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										187
									
								
								core/parse.c
									
									
									
									
									
								
							
							
						
						
									
										187
									
								
								core/parse.c
									
									
									
									
									
								
							| @@ -21,39 +21,9 @@ | ||||
| */ | ||||
|  | ||||
| #include <gst/gst.h> | ||||
| #include <gst/parse.h> | ||||
|  | ||||
| static const char UNEXPECTED_CLOSING_DELIM[] = "Unexpected closing delimiter"; | ||||
|  | ||||
| /* The type of a ParseState */ | ||||
| typedef enum ParseType { | ||||
|     PTYPE_FORM, | ||||
|     PTYPE_STRING, | ||||
|     PTYPE_TOKEN | ||||
| } ParseType; | ||||
|  | ||||
| /* Contain a parse state that goes on the parse stack */ | ||||
| struct GstParseState { | ||||
|     ParseType type; | ||||
|     union { | ||||
|         struct { | ||||
|             uint8_t endDelimiter; | ||||
|             GstArray *array; | ||||
|         } form; | ||||
|         struct { | ||||
|             GstBuffer *buffer; | ||||
|             uint32_t count; | ||||
|             uint32_t accum; | ||||
|             enum { | ||||
|                 STRING_STATE_BASE, | ||||
|                 STRING_STATE_ESCAPE, | ||||
|                 STRING_STATE_ESCAPE_UNICODE, | ||||
|                 STRING_STATE_ESCAPE_HEX | ||||
|             } state; | ||||
|         } string; | ||||
|     } buf; | ||||
| }; | ||||
|  | ||||
| /* Handle error in parsing */ | ||||
| #define p_error(p, e) ((p)->error = (e), (p)->status = GST_PARSER_ERROR) | ||||
|  | ||||
| @@ -429,7 +399,7 @@ static int form_state(GstParser *p, uint8_t c) { | ||||
| } | ||||
|  | ||||
| /* Handle a character */ | ||||
| static void dispatch_char(GstParser *p, uint8_t c) { | ||||
| void gst_parse_byte(GstParser *p, uint8_t c) { | ||||
|     int done = 0; | ||||
|     ++p->index; | ||||
|     /* Dispatch character to state */ | ||||
| @@ -464,7 +434,7 @@ int gst_parse_cstring(GstParser *p, const char *string) { | ||||
|         return 0; | ||||
|     while ((p->status == GST_PARSER_PENDING || p->status == GST_PARSER_ROOT) | ||||
|             && (string[bytesRead] != '\0')) { | ||||
|         dispatch_char(p, string[bytesRead++]); | ||||
|         gst_parse_byte(p, string[bytesRead++]); | ||||
|     } | ||||
|     return bytesRead; | ||||
| } | ||||
| @@ -476,16 +446,11 @@ int gst_parse_string(GstParser *p, const uint8_t *string) { | ||||
|         return 0; | ||||
|     for (i = 0; i < gst_string_length(string); ++i) { | ||||
|         if (p->status != GST_PARSER_PENDING && p->status != GST_PARSER_ROOT) break; | ||||
|         dispatch_char(p, string[i]); | ||||
|         gst_parse_byte(p, string[i]); | ||||
|     } | ||||
|     return i; | ||||
| } | ||||
|  | ||||
| /* Parse a single byte */ | ||||
| void gst_parse_byte(GstParser *p, uint8_t byte) { | ||||
|     dispatch_char(p, byte); | ||||
| } | ||||
|  | ||||
| /* Check if a parser has a value that needs to be handled. If | ||||
|  * so, the parser will not parse any more input until that value | ||||
|  * is consumed. */ | ||||
| @@ -511,148 +476,4 @@ void gst_parser(GstParser *p, Gst *vm) { | ||||
|     p->error = NULL; | ||||
|     p->status = GST_PARSER_ROOT; | ||||
|     p->value.type = GST_NIL; | ||||
| } | ||||
|  | ||||
| /* GC mark a parser */ | ||||
| static void gst_stl_parser_mark(Gst *vm, void *data, uint32_t len) { | ||||
|     uint32_t i; | ||||
|     GstParser *p = (GstParser *) data; | ||||
|     if (len != sizeof(GstParser)) | ||||
|         return; | ||||
|     gst_mark_mem(vm, p->data); | ||||
|     gst_mark_value(vm, p->value); | ||||
|     for (i = 0; i < p->count; ++i) { | ||||
| 		GstParseState *ps = p->data + i; | ||||
| 		switch (ps->type) { | ||||
| 			case PTYPE_FORM: | ||||
|     			gst_mark_value(vm, gst_wrap_array(ps->buf.form.array)); | ||||
|     			break; | ||||
|     		case PTYPE_STRING: | ||||
|         	case PTYPE_TOKEN: | ||||
|             	gst_mark_value(vm, gst_wrap_buffer(ps->buf.string.buffer)); | ||||
|             	break; | ||||
| 		} | ||||
|     } | ||||
| } | ||||
|  | ||||
| /***/ | ||||
| /* Stl functions */ | ||||
| /***/ | ||||
|  | ||||
| /* Parse filetype */ | ||||
| static const GstUserType gst_stl_parsetype = { | ||||
| 	"std.parser", | ||||
| 	NULL, | ||||
| 	NULL, | ||||
| 	NULL, | ||||
| 	&gst_stl_parser_mark | ||||
| }; | ||||
|  | ||||
| /* Create a parser */ | ||||
| static int gst_stl_parser(Gst *vm) { | ||||
| 	GstParser *p = gst_userdata(vm, sizeof(GstParser), &gst_stl_parsetype); | ||||
| 	gst_parser(p, vm); | ||||
| 	gst_c_return(vm, gst_wrap_userdata(p)); | ||||
| } | ||||
|  | ||||
| /* Consume a value from the parser */ | ||||
| static int gst_stl_parser_consume(Gst *vm) { | ||||
| 	GstParser *p = gst_check_userdata(vm, 0, &gst_stl_parsetype); | ||||
| 	if (p == NULL) | ||||
|     	gst_c_throwc(vm, "expected parser"); | ||||
|     if (p->status == GST_PARSER_ERROR) | ||||
|         gst_c_return(vm, gst_string_cv(vm, p->error)); | ||||
|     if (!gst_parse_hasvalue(p)) | ||||
|         gst_c_throwc(vm, "parser has no pending value"); | ||||
| 	gst_c_return(vm, gst_parse_consume(p)); | ||||
| } | ||||
|  | ||||
| /* Check if the parser has a value to consume */ | ||||
| static int gst_stl_parser_hasvalue(Gst *vm) { | ||||
| 	GstParser *p = gst_check_userdata(vm, 0, &gst_stl_parsetype); | ||||
| 	if (p == NULL) | ||||
|     	gst_c_throwc(vm, "expected parser"); | ||||
| 	gst_c_return(vm, gst_wrap_boolean(gst_parse_hasvalue(p))); | ||||
| } | ||||
|  | ||||
| /* Parse a single byte. Returns if the byte was successfully parsed. */ | ||||
| static int gst_stl_parser_byte(Gst *vm) { | ||||
|     GstInteger b; | ||||
| 	GstParser *p = gst_check_userdata(vm, 0, &gst_stl_parsetype); | ||||
| 	if (p == NULL) | ||||
|     	gst_c_throwc(vm, "expected parser"); | ||||
| 	if (!gst_check_integer(vm, 1, &b)) | ||||
|     	gst_c_throwc(vm, "expected integer"); | ||||
|     if (p->status == GST_PARSER_PENDING || p->status == GST_PARSER_ROOT) { | ||||
|         dispatch_char(p, b); | ||||
|         gst_c_return(vm, gst_wrap_boolean(1)); | ||||
|     } else { | ||||
|         gst_c_return(vm, gst_wrap_boolean(0)); | ||||
|     } | ||||
| } | ||||
|  | ||||
| /* Parse a string or buffer. Returns nil if the entire char array is parsed, | ||||
| * otherwise returns the remainder of what could not be parsed. */ | ||||
| static int gst_stl_parser_charseq(Gst *vm) { | ||||
|     uint32_t i; | ||||
| 	uint32_t len; | ||||
| 	const uint8_t *data; | ||||
| 	GstParser *p = gst_check_userdata(vm, 0, &gst_stl_parsetype); | ||||
| 	if (p == NULL) | ||||
|     	gst_c_throwc(vm, "expected parser"); | ||||
|     if (!gst_chararray_view(gst_arg(vm, 1), &data, &len)) | ||||
|         gst_c_throwc(vm, "expected string/buffer"); | ||||
|     for (i = 0; i < len; ++i) { | ||||
|         if (p->status != GST_PARSER_PENDING && p->status != GST_PARSER_ROOT) break; | ||||
|         dispatch_char(p, data[i]); | ||||
|     } | ||||
|     if (i == len) { | ||||
| 		/* No remainder */ | ||||
| 		gst_c_return(vm, gst_wrap_nil()); | ||||
|     } else { | ||||
| 		/* We have remaining characters */ | ||||
| 		gst_c_return(vm, gst_wrap_string(gst_string_b(vm, data + i, len - i))); | ||||
|     } | ||||
| } | ||||
|  | ||||
| /* Get status of parser */ | ||||
| static int gst_stl_parser_status(Gst *vm) { | ||||
|     GstParser *p = gst_check_userdata(vm, 0, &gst_stl_parsetype); | ||||
|     const char *cstr; | ||||
|     if (p == NULL) | ||||
|         gst_c_throwc(vm, "expected parser"); | ||||
|     switch (p->status) { | ||||
|         case GST_PARSER_ERROR:  | ||||
|             cstr = "error"; | ||||
|             break; | ||||
|         case GST_PARSER_FULL: | ||||
|             cstr = "full"; | ||||
|             break; | ||||
|         case GST_PARSER_PENDING: | ||||
|             cstr = "pending"; | ||||
|             break; | ||||
|         case GST_PARSER_ROOT: | ||||
|             cstr = "root"; | ||||
|             break; | ||||
|         default: | ||||
|             cstr = "unknown"; | ||||
|             break; | ||||
|     } | ||||
|     gst_c_return(vm, gst_string_cv(vm, cstr)); | ||||
| } | ||||
|  | ||||
| /* The module */ | ||||
| static const GstModuleItem gst_parser_module[] = { | ||||
|     {"parser", gst_stl_parser}, | ||||
|     {"parse-byte", gst_stl_parser_byte}, | ||||
| 	{"parse-consume", gst_stl_parser_consume}, | ||||
| 	{"parse-hasvalue", gst_stl_parser_hasvalue}, | ||||
| 	{"parse-charseq", gst_stl_parser_charseq}, | ||||
| 	{"parse-status", gst_stl_parser_status}, | ||||
| 	{NULL, NULL} | ||||
| }; | ||||
|  | ||||
| /* Load the module */ | ||||
| void gst_parse_load(Gst *vm) { | ||||
| 	gst_module(vm, "std.parse", gst_parser_module); | ||||
| } | ||||
| } | ||||
| @@ -513,9 +513,6 @@ const char *gst_serialize_impl( | ||||
|                 write_int(x.data.integer); | ||||
|             } | ||||
|             return NULL; | ||||
|         /*case GST_CFUNCTION:*/ | ||||
|             /* TODO */ | ||||
|             break; | ||||
|         default: | ||||
|             break; | ||||
|     } | ||||
|   | ||||
							
								
								
									
										259
									
								
								core/stl.c
									
									
									
									
									
								
							
							
						
						
									
										259
									
								
								core/stl.c
									
									
									
									
									
								
							| @@ -21,11 +21,6 @@ | ||||
| */ | ||||
|  | ||||
| #include <gst/gst.h> | ||||
| #include <gst/parse.h> | ||||
| #include <gst/compile.h> | ||||
| #include <gst/stl.h> | ||||
|  | ||||
| #include <gst/disasm.h> | ||||
|  | ||||
| static const char GST_EXPECTED_INTEGER[] = "expected integer"; | ||||
| static const char GST_EXPECTED_STRING[] = "expected string"; | ||||
| @@ -682,12 +677,6 @@ int gst_stl_namespace_set(Gst *vm) { | ||||
| /* Get the table or struct associated with a given namespace */ | ||||
| int gst_stl_namespace_get(Gst *vm) { | ||||
|     return gst_callc(vm, gst_stl_get, 2, gst_wrap_table(vm->modules), gst_arg(vm, 0)); | ||||
|     /*GstValue name = gst_arg(vm, 0);*/ | ||||
|     /*GstValue check;*/ | ||||
|     /*if (name.type != GST_STRING)*/ | ||||
|         /*gst_c_throwc(vm, "expected string");*/ | ||||
|     /*check = gst_table_get(vm->modules, name);*/ | ||||
|     /*gst_c_return(vm, check);*/ | ||||
| } | ||||
|  | ||||
| /***/ | ||||
| @@ -808,49 +797,10 @@ int gst_stl_close(Gst *vm) { | ||||
|     gst_c_return(vm, gst_wrap_nil()); | ||||
| } | ||||
|  | ||||
| /* Functions in the io module */ | ||||
| static const GstModuleItem io_dat[] = { | ||||
|     {"open", gst_stl_open}, | ||||
|     {"slurp", gst_stl_slurp}, | ||||
|     {"read", gst_stl_read}, | ||||
|     {"write", gst_stl_write}, | ||||
|     {NULL, NULL} | ||||
| }; | ||||
|  | ||||
| /* Load the io module */ | ||||
| void gst_stlio_load(Gst *vm) { | ||||
|     /* Load the normal c functions */ | ||||
|     gst_module_mutable(vm, "std.io", io_dat); | ||||
|     /* Wrap stdin and stdout */ | ||||
|     FILE **inp = gst_userdata(vm, sizeof(FILE *), &gst_stl_filetype); | ||||
|     FILE **outp = gst_userdata(vm, sizeof(FILE *), &gst_stl_filetype); | ||||
|     *inp = stdin; | ||||
|     *outp = stdout; | ||||
|     gst_module_put(vm, "std.io", "stdin", gst_wrap_userdata(inp)); | ||||
|     gst_module_put(vm, "std.io", "stdout", gst_wrap_userdata(outp)); | ||||
| } | ||||
|  | ||||
| /****/ | ||||
| /* Temporary */ | ||||
| /****/ | ||||
|  | ||||
| /* These functions should definitely be moved to a different module, removed, or | ||||
|  * rewritten in gst when the language is complete enough. This is not to say | ||||
|  * that functions in other section need not be moved. */ | ||||
|  | ||||
| /* Print disassembly for a function */ | ||||
| int gst_stl_dasm(Gst *vm) { | ||||
|     GstValue x = gst_arg(vm, 0); | ||||
|     if (x.type == GST_FUNCTION) { | ||||
|         printf("%c[31m===== Begin Disassembly =====\n", 27); | ||||
|         gst_dasm_function(stdout, x.data.function); | ||||
|         printf("=====  End Disassembly  =====%c[0m\n", 27); | ||||
|     } else { | ||||
|         gst_c_throwc(vm, "expected function"); | ||||
|     } | ||||
|     return GST_RETURN_OK; | ||||
| } | ||||
|  | ||||
| /* Force garbage collection */ | ||||
| int gst_stl_gcollect(Gst *vm) { | ||||
| 	gst_collect(vm); | ||||
| @@ -923,6 +873,184 @@ int gst_stl_debugp(Gst *vm) { | ||||
|     gst_c_return(vm, gst_wrap_string(gst_buffer_to_string(vm, buf))); | ||||
| } | ||||
|  | ||||
| /***/ | ||||
| /* Parsing */ | ||||
| /***/ | ||||
|  | ||||
| /* GC mark a parser */ | ||||
| static void gst_stl_parser_mark(Gst *vm, void *data, uint32_t len) { | ||||
|     uint32_t i; | ||||
|     GstParser *p = (GstParser *) data; | ||||
|     if (len != sizeof(GstParser)) | ||||
|         return; | ||||
|     gst_mark_mem(vm, p->data); | ||||
|     gst_mark_value(vm, p->value); | ||||
|     for (i = 0; i < p->count; ++i) { | ||||
|         GstParseState *ps = p->data + i; | ||||
|         switch (ps->type) { | ||||
|             case PTYPE_FORM: | ||||
|                 gst_mark_value(vm, gst_wrap_array(ps->buf.form.array)); | ||||
|                 break; | ||||
|             case PTYPE_STRING: | ||||
|             case PTYPE_TOKEN: | ||||
|                 gst_mark_value(vm, gst_wrap_buffer(ps->buf.string.buffer)); | ||||
|                 break; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| /* Parse filetype */ | ||||
| static const GstUserType gst_stl_parsetype = { | ||||
|     "std.parser", | ||||
|     NULL, | ||||
|     NULL, | ||||
|     NULL, | ||||
|     &gst_stl_parser_mark | ||||
| }; | ||||
|  | ||||
| /* Create a parser */ | ||||
| static int gst_stl_parser(Gst *vm) { | ||||
|     GstParser *p = gst_userdata(vm, sizeof(GstParser), &gst_stl_parsetype); | ||||
|     gst_parser(p, vm); | ||||
|     gst_c_return(vm, gst_wrap_userdata(p)); | ||||
| } | ||||
|  | ||||
| /* Consume a value from the parser */ | ||||
| static int gst_stl_parser_consume(Gst *vm) { | ||||
|     GstParser *p = gst_check_userdata(vm, 0, &gst_stl_parsetype); | ||||
|     if (p == NULL) | ||||
|         gst_c_throwc(vm, "expected parser"); | ||||
|     if (p->status == GST_PARSER_ERROR) | ||||
|         gst_c_return(vm, gst_string_cv(vm, p->error)); | ||||
|     if (!gst_parse_hasvalue(p)) | ||||
|         gst_c_throwc(vm, "parser has no pending value"); | ||||
|     gst_c_return(vm, gst_parse_consume(p)); | ||||
| } | ||||
|  | ||||
| /* Check if the parser has a value to consume */ | ||||
| static int gst_stl_parser_hasvalue(Gst *vm) { | ||||
|     GstParser *p = gst_check_userdata(vm, 0, &gst_stl_parsetype); | ||||
|     if (p == NULL) | ||||
|         gst_c_throwc(vm, "expected parser"); | ||||
|     gst_c_return(vm, gst_wrap_boolean(gst_parse_hasvalue(p))); | ||||
| } | ||||
|  | ||||
| /* Parse a single byte. Returns if the byte was successfully parsed. */ | ||||
| static int gst_stl_parser_byte(Gst *vm) { | ||||
|     GstInteger b; | ||||
|     GstParser *p = gst_check_userdata(vm, 0, &gst_stl_parsetype); | ||||
|     if (p == NULL) | ||||
|         gst_c_throwc(vm, "expected parser"); | ||||
|     if (!gst_check_integer(vm, 1, &b)) | ||||
|         gst_c_throwc(vm, "expected integer"); | ||||
|     if (p->status == GST_PARSER_PENDING || p->status == GST_PARSER_ROOT) { | ||||
|         gst_parse_byte(p, b); | ||||
|         gst_c_return(vm, gst_wrap_boolean(1)); | ||||
|     } else { | ||||
|         gst_c_return(vm, gst_wrap_boolean(0)); | ||||
|     } | ||||
| } | ||||
|  | ||||
| /* Parse a string or buffer. Returns nil if the entire char array is parsed, | ||||
| * otherwise returns the remainder of what could not be parsed. */ | ||||
| static int gst_stl_parser_charseq(Gst *vm) { | ||||
|     uint32_t i; | ||||
|     uint32_t len; | ||||
|     const uint8_t *data; | ||||
|     GstParser *p = gst_check_userdata(vm, 0, &gst_stl_parsetype); | ||||
|     if (p == NULL) | ||||
|         gst_c_throwc(vm, "expected parser"); | ||||
|     if (!gst_chararray_view(gst_arg(vm, 1), &data, &len)) | ||||
|         gst_c_throwc(vm, "expected string/buffer"); | ||||
|     for (i = 0; i < len; ++i) { | ||||
|         if (p->status != GST_PARSER_PENDING && p->status != GST_PARSER_ROOT) break; | ||||
|         gst_parse_byte(p, data[i]); | ||||
|     } | ||||
|     if (i == len) { | ||||
|         /* No remainder */ | ||||
|         gst_c_return(vm, gst_wrap_nil()); | ||||
|     } else { | ||||
|         /* We have remaining characters */ | ||||
|         gst_c_return(vm, gst_wrap_string(gst_string_b(vm, data + i, len - i))); | ||||
|     } | ||||
| } | ||||
|  | ||||
| /* Get status of parser */ | ||||
| static int gst_stl_parser_status(Gst *vm) { | ||||
|     GstParser *p = gst_check_userdata(vm, 0, &gst_stl_parsetype); | ||||
|     const char *cstr; | ||||
|     if (p == NULL) | ||||
|         gst_c_throwc(vm, "expected parser"); | ||||
|     switch (p->status) { | ||||
|         case GST_PARSER_ERROR:  | ||||
|             cstr = "error"; | ||||
|             break; | ||||
|         case GST_PARSER_FULL: | ||||
|             cstr = "full"; | ||||
|             break; | ||||
|         case GST_PARSER_PENDING: | ||||
|             cstr = "pending"; | ||||
|             break; | ||||
|         case GST_PARSER_ROOT: | ||||
|             cstr = "root"; | ||||
|             break; | ||||
|         default: | ||||
|             cstr = "unknown"; | ||||
|             break; | ||||
|     } | ||||
|     gst_c_return(vm, gst_string_cv(vm, cstr)); | ||||
| } | ||||
|  | ||||
| /* Parse a string */ | ||||
| static int gst_stl_parse(Gst *vm) { | ||||
|     uint32_t len, i; | ||||
|     GstParser p; | ||||
|     const uint8_t *data; | ||||
|     if (!gst_chararray_view(gst_arg(vm, 0), &data, &len)) | ||||
|         gst_c_throwc(vm, "expected string/buffer to parse"); | ||||
|     gst_parser(&p, vm); | ||||
|     for (i = 0; i < len; ++i) { | ||||
|         if (p.status != GST_PARSER_PENDING && p.status != GST_PARSER_ROOT) break; | ||||
|         gst_parse_byte(&p, data[i]); | ||||
|     } | ||||
|     switch (p.status) { | ||||
|         case GST_PARSER_ERROR:  | ||||
|             gst_c_throwc(vm, p.error); | ||||
|             break; | ||||
|         case GST_PARSER_FULL: | ||||
|             gst_c_return(vm, p.value); | ||||
|             break; | ||||
|         case GST_PARSER_PENDING: | ||||
|         case GST_PARSER_ROOT: | ||||
|             gst_c_throwc(vm, "unexpected end of source"); | ||||
|             break; | ||||
|         default: | ||||
|             gst_c_throwc(vm, "unknown error parsing"); | ||||
|             break; | ||||
|     } | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| /***/ | ||||
| /* Compilation */ | ||||
| /***/ | ||||
|  | ||||
| /* Compile a value */ | ||||
| static int gst_stl_compile(Gst *vm) { | ||||
|     GstFunction *ret; | ||||
|     GstValue std; | ||||
|     GstCompiler c; | ||||
|     gst_compiler(&c, vm); | ||||
|     std = gst_table_get(vm->modules, gst_string_cv(vm, "std")); | ||||
|     gst_compiler_globals(&c, std); | ||||
|     gst_compiler_globals(&c, gst_arg(vm, 1)); | ||||
|     gst_compiler_nilglobals(&c, gst_arg(vm, 2)); | ||||
|     ret = gst_compiler_compile(&c, gst_arg(vm, 0)); | ||||
|     if (!ret) | ||||
|         gst_c_throw(vm, c.error); | ||||
|     gst_c_return(vm, gst_wrap_function(ret)); | ||||
| } | ||||
|  | ||||
| /****/ | ||||
| /* Bootstraping */ | ||||
| /****/ | ||||
| @@ -946,6 +1074,22 @@ static const GstModuleItem std_module[] = { | ||||
|     {"blshift", gst_stl_blshift}, | ||||
|     {"brshift", gst_stl_brshift}, | ||||
|     {"bnot", gst_stl_bnot}, | ||||
|     /* IO */ | ||||
|     {"open", gst_stl_open}, | ||||
|     {"slurp", gst_stl_slurp}, | ||||
|     {"read", gst_stl_read}, | ||||
|     {"write", gst_stl_write}, | ||||
|     /* Parsing */ | ||||
|     {"parser", gst_stl_parser}, | ||||
|     {"parse-byte", gst_stl_parser_byte}, | ||||
|     {"parse-consume", gst_stl_parser_consume}, | ||||
|     {"parse-hasvalue", gst_stl_parser_hasvalue}, | ||||
|     {"parse-charseq", gst_stl_parser_charseq}, | ||||
|     {"parse-status", gst_stl_parser_status}, | ||||
|         {"parse-status", gst_stl_parser_status}, | ||||
| {"parse", gst_stl_parse}, | ||||
|     /* Compile */ | ||||
|     {"compile", gst_stl_compile}, | ||||
|     /* Other */ | ||||
|     {"not", gst_stl_not}, | ||||
|     {"length", gst_stl_length}, | ||||
| @@ -988,7 +1132,6 @@ static const GstModuleItem std_module[] = { | ||||
|     {"funcenv", gst_stl_funcenv}, | ||||
|     {"funcdef", gst_stl_funcdef}, | ||||
|     {"funcparent", gst_stl_funcparent}, | ||||
|     {"dasm", gst_stl_dasm}, | ||||
|     {"gcollect", gst_stl_gcollect}, | ||||
|     {"debugp", gst_stl_debugp}, | ||||
|     {NULL, NULL} | ||||
| @@ -996,6 +1139,16 @@ static const GstModuleItem std_module[] = { | ||||
|  | ||||
| /* Load all libraries */ | ||||
| void gst_stl_load(Gst *vm) { | ||||
|     gst_stlio_load(vm); | ||||
|     gst_module(vm, "std", std_module); | ||||
|     /* Load the normal c functions */ | ||||
|     gst_module_mutable(vm, "std", std_module); | ||||
|     /* Wrap stdin and stdout */ | ||||
|     FILE **inp = gst_userdata(vm, sizeof(FILE *), &gst_stl_filetype); | ||||
|     FILE **outp = gst_userdata(vm, sizeof(FILE *), &gst_stl_filetype); | ||||
|     FILE **errp = gst_userdata(vm, sizeof(FILE *), &gst_stl_filetype); | ||||
|     *inp = stdin; | ||||
|     *outp = stdout; | ||||
|     *errp = stderr; | ||||
|     gst_module_put(vm, "std", "stdin", gst_wrap_userdata(inp)); | ||||
|     gst_module_put(vm, "std", "stdout", gst_wrap_userdata(outp)); | ||||
|     gst_module_put(vm, "std", "stderr", gst_wrap_userdata(outp)); | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Calvin Rose
					Calvin Rose