mirror of
				https://github.com/janet-lang/janet
				synced 2025-10-31 15:43:01 +00:00 
			
		
		
		
	Add 64 bit signed integers as a basic type. Will enable
more native bitwise operations and c integration at the expense of complicating arithmetic.
This commit is contained in:
		| @@ -106,7 +106,8 @@ static FormOptions form_options_default() { | |||||||
|  * to the byte buffer. This helps us create the byte code for the compiled |  * to the byte buffer. This helps us create the byte code for the compiled | ||||||
|  * functions. */ |  * functions. */ | ||||||
| BUFFER_DEFINE(i32, int32_t) | BUFFER_DEFINE(i32, int32_t) | ||||||
| BUFFER_DEFINE(number, GstNumber) | BUFFER_DEFINE(i64, int64_t) | ||||||
|  | BUFFER_DEFINE(real, GstReal) | ||||||
| BUFFER_DEFINE(u16, uint16_t) | BUFFER_DEFINE(u16, uint16_t) | ||||||
| BUFFER_DEFINE(i16, int16_t) | BUFFER_DEFINE(i16, int16_t) | ||||||
|  |  | ||||||
| @@ -321,13 +322,13 @@ static uint16_t compiler_add_literal(GstCompiler *c, GstScope *scope, GstValue x | |||||||
|     uint16_t literalIndex = 0; |     uint16_t literalIndex = 0; | ||||||
|     if (checkDup.type != GST_NIL) { |     if (checkDup.type != GST_NIL) { | ||||||
|         /* An equal literal is already registered in the current scope */ |         /* An equal literal is already registered in the current scope */ | ||||||
|         return (uint16_t) checkDup.data.number; |         return (uint16_t) checkDup.data.integer; | ||||||
|     } else { |     } else { | ||||||
|         /* Add our literal for tracking */ |         /* Add our literal for tracking */ | ||||||
|         GstValue valIndex; |         GstValue valIndex; | ||||||
|         valIndex.type = GST_NUMBER; |         valIndex.type = GST_INTEGER; | ||||||
|         literalIndex = scope->literalsArray->count; |         literalIndex = scope->literalsArray->count; | ||||||
|         valIndex.data.number = literalIndex; |         valIndex.data.integer = literalIndex; | ||||||
|         gst_object_put(c->vm, scope->literals, x, valIndex); |         gst_object_put(c->vm, scope->literals, x, valIndex); | ||||||
|         gst_array_push(c->vm, scope->literalsArray, x); |         gst_array_push(c->vm, scope->literalsArray, x); | ||||||
|     } |     } | ||||||
| @@ -341,8 +342,8 @@ static uint16_t compiler_declare_symbol(GstCompiler *c, GstScope *scope, GstValu | |||||||
|     if (sym.type != GST_STRING) |     if (sym.type != GST_STRING) | ||||||
|         c_error(c, "expected string"); |         c_error(c, "expected string"); | ||||||
|     target = compiler_get_local(c, scope); |     target = compiler_get_local(c, scope); | ||||||
|     x.type = GST_NUMBER; |     x.type = GST_INTEGER; | ||||||
|     x.data.number = target; |     x.data.integer = target; | ||||||
|     gst_object_put(c->vm, scope->locals, sym, x); |     gst_object_put(c->vm, scope->locals, sym, x); | ||||||
|     return target; |     return target; | ||||||
| } | } | ||||||
| @@ -356,7 +357,7 @@ static int symbol_resolve(GstCompiler *c, GstValue x, uint16_t *level, uint16_t | |||||||
|         GstValue check = gst_object_get(scope->locals, x); |         GstValue check = gst_object_get(scope->locals, x); | ||||||
|         if (check.type != GST_NIL) { |         if (check.type != GST_NIL) { | ||||||
|             *level = currentLevel - scope->level; |             *level = currentLevel - scope->level; | ||||||
|             *index = (uint16_t) check.data.number; |             *index = (uint16_t) check.data.integer; | ||||||
|             return 1; |             return 1; | ||||||
|         } |         } | ||||||
|          |          | ||||||
| @@ -405,24 +406,23 @@ static Slot compile_nonref_type(GstCompiler *c, FormOptions opts, GstValue x) { | |||||||
|     } else if (x.type == GST_BOOLEAN) { |     } else if (x.type == GST_BOOLEAN) { | ||||||
|         gst_buffer_push_u16(c->vm, buffer, x.data.boolean ? GST_OP_TRU : GST_OP_FLS); |         gst_buffer_push_u16(c->vm, buffer, x.data.boolean ? GST_OP_TRU : GST_OP_FLS); | ||||||
|         gst_buffer_push_u16(c->vm, buffer, ret.index); |         gst_buffer_push_u16(c->vm, buffer, ret.index); | ||||||
|     } else if (x.type == GST_NUMBER) { |     } else if (x.type == GST_REAL) { | ||||||
|         GstNumber number = x.data.number; |         gst_buffer_push_u16(c->vm, buffer, GST_OP_F64); | ||||||
|         int32_t int32Num = (int32_t) number; |         gst_buffer_push_u16(c->vm, buffer, ret.index); | ||||||
|         if (number == (GstNumber) int32Num) { |         gst_buffer_push_real(c->vm, buffer, x.data.real); | ||||||
|             if (int32Num <= 32767 && int32Num >= -32768) { |     } else if (x.type == GST_INTEGER) { | ||||||
|                 int16_t int16Num = (int16_t) number; |         if (x.data.integer <= 32767 && x.data.integer >= -32768) { | ||||||
|                 gst_buffer_push_u16(c->vm, buffer, GST_OP_I16); |             gst_buffer_push_u16(c->vm, buffer, GST_OP_I16); | ||||||
|                 gst_buffer_push_u16(c->vm, buffer, ret.index); |  | ||||||
|                 gst_buffer_push_i16(c->vm, buffer, int16Num); |  | ||||||
|             } else { |  | ||||||
|                 gst_buffer_push_u16(c->vm, buffer, GST_OP_I32); |  | ||||||
|                 gst_buffer_push_u16(c->vm, buffer, ret.index); |  | ||||||
|                 gst_buffer_push_i32(c->vm, buffer, int32Num); |  | ||||||
|             } |  | ||||||
|         } else { |  | ||||||
|             gst_buffer_push_u16(c->vm, buffer, GST_OP_F64); |  | ||||||
|             gst_buffer_push_u16(c->vm, buffer, ret.index); |             gst_buffer_push_u16(c->vm, buffer, ret.index); | ||||||
|             gst_buffer_push_number(c->vm, buffer, number); |             gst_buffer_push_i16(c->vm, buffer, x.data.integer); | ||||||
|  |         } else if (x.data.integer <= 2147483647 && x.data.integer >= -2147483648) { | ||||||
|  |             gst_buffer_push_u16(c->vm, buffer, GST_OP_I32); | ||||||
|  |             gst_buffer_push_u16(c->vm, buffer, ret.index); | ||||||
|  |             gst_buffer_push_i32(c->vm, buffer, x.data.integer); | ||||||
|  |         } else { | ||||||
|  |             gst_buffer_push_u16(c->vm, buffer, GST_OP_I64); | ||||||
|  |             gst_buffer_push_u16(c->vm, buffer, ret.index); | ||||||
|  |             gst_buffer_push_i64(c->vm, buffer, x.data.integer); | ||||||
|         } |         } | ||||||
|     } else { |     } else { | ||||||
|         c_error(c, "expected boolean, nil, or number type"); |         c_error(c, "expected boolean, nil, or number type"); | ||||||
| @@ -743,7 +743,8 @@ static Slot compile_quote(GstCompiler *c, FormOptions opts, const GstValue *form | |||||||
|     GstValue x = form[1]; |     GstValue x = form[1]; | ||||||
|     if (x.type == GST_NIL || |     if (x.type == GST_NIL || | ||||||
|             x.type == GST_BOOLEAN || |             x.type == GST_BOOLEAN || | ||||||
|             x.type == GST_NUMBER) { |             x.type == GST_REAL || | ||||||
|  |             x.type == GST_INTEGER) { | ||||||
|         return compile_nonref_type(c, opts, x); |         return compile_nonref_type(c, opts, x); | ||||||
|     } |     } | ||||||
|     if (opts.resultUnused) return nil_slot(); |     if (opts.resultUnused) return nil_slot(); | ||||||
| @@ -1007,7 +1008,8 @@ static Slot compile_value(GstCompiler *c, FormOptions opts, GstValue x) { | |||||||
|     switch (x.type) { |     switch (x.type) { | ||||||
|         case GST_NIL: |         case GST_NIL: | ||||||
|         case GST_BOOLEAN: |         case GST_BOOLEAN: | ||||||
|         case GST_NUMBER: |         case GST_REAL: | ||||||
|  |         case GST_INTEGER: | ||||||
|             return compile_nonref_type(c, opts, x); |             return compile_nonref_type(c, opts, x); | ||||||
|         case GST_STRING: |         case GST_STRING: | ||||||
|             return compile_symbol(c, opts, x); |             return compile_symbol(c, opts, x); | ||||||
|   | |||||||
| @@ -94,21 +94,6 @@ void gst_dasm(FILE * out, uint16_t *byteCode, uint32_t len) { | |||||||
|             default: |             default: | ||||||
|                 current += dasm_fixed_op(out, current, "unknown", 0); |                 current += dasm_fixed_op(out, current, "unknown", 0); | ||||||
|                 break; |                 break; | ||||||
|             case GST_OP_ADD: |  | ||||||
|                 current += dasm_fixed_op(out, current, "add", 3); |  | ||||||
|                 break; |  | ||||||
|             case GST_OP_SUB: |  | ||||||
|                 current += dasm_fixed_op(out, current, "sub", 3); |  | ||||||
|                 break;       |  | ||||||
|             case GST_OP_MUL: |  | ||||||
|                 current += dasm_fixed_op(out, current, "mul", 3); |  | ||||||
|                 break;       |  | ||||||
|             case GST_OP_DIV: |  | ||||||
|                 current += dasm_fixed_op(out, current, "div", 3); |  | ||||||
|                 break; |  | ||||||
|             case GST_OP_NOT: |  | ||||||
|                 current += dasm_fixed_op(out, current, "not", 2); |  | ||||||
|                 break; |  | ||||||
|             case GST_OP_FLS: |             case GST_OP_FLS: | ||||||
|                 current += dasm_fixed_op(out, current, "loadFalse", 1); |                 current += dasm_fixed_op(out, current, "loadFalse", 1); | ||||||
|                 break; |                 break; | ||||||
| @@ -174,15 +159,6 @@ void gst_dasm(FILE * out, uint16_t *byteCode, uint32_t len) { | |||||||
|                 dasm_print_literal(out, current[2]); |                 dasm_print_literal(out, current[2]); | ||||||
|                 current += 3; |                 current += 3; | ||||||
|                 break; |                 break; | ||||||
|             case GST_OP_EQL: |  | ||||||
|                 current += dasm_fixed_op(out, current, "equals", 3); |  | ||||||
|                 break; |  | ||||||
|             case GST_OP_LTN: |  | ||||||
|                 current += dasm_fixed_op(out, current, "lessThan", 3); |  | ||||||
|                 break; |  | ||||||
|             case GST_OP_LTE: |  | ||||||
|                 current += dasm_fixed_op(out, current, "lessThanEquals", 3); |  | ||||||
|                 break; |  | ||||||
|             case GST_OP_ARR: |             case GST_OP_ARR: | ||||||
|                 current += dasm_varg_op(out, current, "array", 1); |                 current += dasm_varg_op(out, current, "array", 1); | ||||||
|                 break; |                 break; | ||||||
|   | |||||||
| @@ -88,10 +88,7 @@ void gst_mark_value(Gst *vm, GstValue x) { | |||||||
|  * the main function for doing the garbage collection mark phase. */ |  * the main function for doing the garbage collection mark phase. */ | ||||||
| void gst_mark(Gst *vm, GstValueUnion x, GstType type) { | void gst_mark(Gst *vm, GstValueUnion x, GstType type) { | ||||||
|     switch (type) { |     switch (type) { | ||||||
|         case GST_NIL: |         default:  | ||||||
|         case GST_BOOLEAN: |  | ||||||
|         case GST_NUMBER: |  | ||||||
|         case GST_CFUNCTION: |  | ||||||
|             break; |             break; | ||||||
|  |  | ||||||
|         case GST_STRING: |         case GST_STRING: | ||||||
|   | |||||||
							
								
								
									
										41
									
								
								core/parse.c
									
									
									
									
									
								
							
							
						
						
									
										41
									
								
								core/parse.c
									
									
									
									
									
								
							| @@ -184,10 +184,10 @@ static double exp10(int power) { | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Read a number from a string. Returns if successfuly | /* Read a real from a string. Returns if successfuly | ||||||
|  * parsed a number from the enitre input string. |  * parsed a real from the enitre input string. | ||||||
|  * If returned 1, output is int ret.*/ |  * If returned 1, output is int ret.*/ | ||||||
| static int read_number(const uint8_t *string, const uint8_t *end, double *ret, int forceInt) { | static int read_real(const uint8_t *string, const uint8_t *end, double *ret, int forceInt) { | ||||||
|     int sign = 1, x = 0; |     int sign = 1, x = 0; | ||||||
|     double accum = 0, exp = 1, place = 1; |     double accum = 0, exp = 1, place = 1; | ||||||
|     /* Check the sign */ |     /* Check the sign */ | ||||||
| @@ -205,7 +205,7 @@ static int read_number(const uint8_t *string, const uint8_t *end, double *ret, i | |||||||
|             /* Read the exponent */ |             /* Read the exponent */ | ||||||
|             ++string; |             ++string; | ||||||
|             if (string >= end) return 0; |             if (string >= end) return 0; | ||||||
|             if (!read_number(string, end, &exp, 1)) |             if (!read_real(string, end, &exp, 1)) | ||||||
|                 return 0; |                 return 0; | ||||||
|             exp = exp10(exp); |             exp = exp10(exp); | ||||||
|             break; |             break; | ||||||
| @@ -227,6 +227,27 @@ static int read_number(const uint8_t *string, const uint8_t *end, double *ret, i | |||||||
|     return 1; |     return 1; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static int read_integer(const uint8_t *string, const uint8_t *end, int64_t *ret) { | ||||||
|  |     int sign = 1, x = 0; | ||||||
|  |     int64_t accum = 0; | ||||||
|  |     if (*string == '-') { | ||||||
|  |         sign = -1; | ||||||
|  |         ++string; | ||||||
|  |     } else if (*string == '+') { | ||||||
|  |         ++string; | ||||||
|  |     } | ||||||
|  |     if (string >= end) return 0; | ||||||
|  |     while (string < end) { | ||||||
|  |         x = *string; | ||||||
|  |         if (x < '0' || x > '9') return 0; | ||||||
|  |         x -= '0'; | ||||||
|  |         accum = accum * 10 + x; | ||||||
|  |         ++string; | ||||||
|  |     } | ||||||
|  |     *ret = accum * sign; | ||||||
|  |     return 1; | ||||||
|  | } | ||||||
|  |  | ||||||
| /* Checks if a string slice is equal to a string constant */ | /* Checks if a string slice is equal to a string constant */ | ||||||
| static int check_str_const(const char *ref, const uint8_t *start, const uint8_t *end) { | static int check_str_const(const char *ref, const uint8_t *start, const uint8_t *end) { | ||||||
|     while (*ref && start < end) { |     while (*ref && start < end) { | ||||||
| @@ -240,12 +261,16 @@ static int check_str_const(const char *ref, const uint8_t *start, const uint8_t | |||||||
| /* Build from the token buffer */ | /* Build from the token buffer */ | ||||||
| static GstValue build_token(GstParser *p, GstBuffer *buf) { | static GstValue build_token(GstParser *p, GstBuffer *buf) { | ||||||
|     GstValue x; |     GstValue x; | ||||||
|     GstNumber number; |     GstReal real; | ||||||
|  |     GstInteger integer; | ||||||
|     uint8_t *data = buf->data; |     uint8_t *data = buf->data; | ||||||
|     uint8_t *back = data + buf->count; |     uint8_t *back = data + buf->count; | ||||||
|     if (read_number(data, back, &number, 0)) { |     if (read_integer(data, back, &integer)) { | ||||||
|         x.type = GST_NUMBER; |         x.type = GST_INTEGER; | ||||||
|         x.data.number = number; |         x.data.integer = integer; | ||||||
|  |     } else if (read_real(data, back, &real, 0)) { | ||||||
|  |         x.type = GST_REAL; | ||||||
|  |         x.data.real = real; | ||||||
|     } else if (check_str_const("nil", data, back)) { |     } else if (check_str_const("nil", data, back)) { | ||||||
|         x.type = GST_NIL; |         x.type = GST_NIL; | ||||||
|         x.data.boolean = 0; |         x.data.boolean = 0; | ||||||
|   | |||||||
| @@ -50,6 +50,7 @@ | |||||||
|  * Byte 215: LUdata  - [value meta][u32 length]*[u8... bytes] |  * Byte 215: LUdata  - [value meta][u32 length]*[u8... bytes] | ||||||
|  * Byte 216: CFunc   - [u32 length]*[u8... idstring] |  * Byte 216: CFunc   - [u32 length]*[u8... idstring] | ||||||
|  * Byte 217: Ref     - [u32 id] |  * Byte 217: Ref     - [u32 id] | ||||||
|  |  * Byte 218: Integer - [i64 value] | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| /* Error at buffer end */ | /* Error at buffer end */ | ||||||
| @@ -76,7 +77,7 @@ static uint16_t bytes2u16(const uint8_t *bytes) { | |||||||
| } | } | ||||||
|  |  | ||||||
| /* Read 8 bytes as a double */ | /* Read 8 bytes as a double */ | ||||||
| static uint32_t bytes2dbl(const uint8_t *bytes) { | static double bytes2dbl(const uint8_t *bytes) { | ||||||
|     union { |     union { | ||||||
|         uint8_t bytes[8]; |         uint8_t bytes[8]; | ||||||
|         double dbl; |         double dbl; | ||||||
| @@ -85,6 +86,16 @@ static uint32_t bytes2dbl(const uint8_t *bytes) { | |||||||
|     return u.dbl; |     return u.dbl; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /* Read 8 bytes as a integer */ | ||||||
|  | static int64_t bytes2int(const uint8_t *bytes) { | ||||||
|  |     union { | ||||||
|  |         uint8_t bytes[8]; | ||||||
|  |         int64_t i; | ||||||
|  |     } u; | ||||||
|  |     gst_memcpy(u.bytes, bytes, 8 * sizeof(uint8_t)); | ||||||
|  |     return u.i; | ||||||
|  | } | ||||||
|  |  | ||||||
| /* Read a string and turn it into a gst value. Returns | /* Read a string and turn it into a gst value. Returns | ||||||
|  * an error message if there is an error message during |  * an error message if there is an error message during | ||||||
|  * deserialization. If successful, the resulting value is |  * deserialization. If successful, the resulting value is | ||||||
| @@ -116,14 +127,15 @@ static const char *gst_deserialize_impl( | |||||||
| #define read_u32(out) do{deser_datacheck(4); (out)=bytes2u32(data); data += 4; }while(0) | #define read_u32(out) do{deser_datacheck(4); (out)=bytes2u32(data); data += 4; }while(0) | ||||||
| #define read_u16(out) do{deser_datacheck(2); (out)=bytes2u16(data); data += 2; }while(0) | #define read_u16(out) do{deser_datacheck(2); (out)=bytes2u16(data); data += 2; }while(0) | ||||||
| #define read_dbl(out) do{deser_datacheck(8); (out)=bytes2dbl(data); data += 8; }while(0) | #define read_dbl(out) do{deser_datacheck(8); (out)=bytes2dbl(data); data += 8; }while(0) | ||||||
|  | #define read_i64(out) do{deser_datacheck(8); (out)=bytes2int(data); data += 8; }while(0) | ||||||
|  |  | ||||||
|     /* Check enough buffer left to read one byte */ |     /* Check enough buffer left to read one byte */ | ||||||
|     if (data >= end) deser_error(UEB); |     if (data >= end) deser_error(UEB); | ||||||
|  |  | ||||||
|     /* Small integer */ |     /* Small integer */ | ||||||
|     if (*data < 201) { |     if (*data < 201) { | ||||||
|         ret.type = GST_NUMBER; |         ret.type = GST_INTEGER; | ||||||
|         ret.data.number = *data - 100;  |         ret.data.integer = *data - 100;  | ||||||
|         *newData = data + 1; |         *newData = data + 1; | ||||||
|         *out = ret; |         *out = ret; | ||||||
|         return NULL; |         return NULL; | ||||||
| @@ -150,8 +162,8 @@ static const char *gst_deserialize_impl( | |||||||
|             break; |             break; | ||||||
|  |  | ||||||
|         case 204: /* Long number (double) */ |         case 204: /* Long number (double) */ | ||||||
|             ret.type = GST_NUMBER;  |             ret.type = GST_REAL;  | ||||||
|             read_dbl(ret.data.number); |             read_dbl(ret.data.real); | ||||||
|             break; |             break; | ||||||
|  |  | ||||||
|         case 205: /* String */ |         case 205: /* String */ | ||||||
| @@ -410,6 +422,11 @@ static const char *gst_deserialize_impl( | |||||||
|             deser_assert(visited->count > length, "invalid reference"); |             deser_assert(visited->count > length, "invalid reference"); | ||||||
|             ret = visited->data[length]; |             ret = visited->data[length]; | ||||||
|             break; |             break; | ||||||
|  |  | ||||||
|  |         case 218: /* Integer */ | ||||||
|  |             ret.type = GST_INTEGER; | ||||||
|  |             read_i64(ret.data.integer); | ||||||
|  |             break; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /* Handle a successful return */ |     /* Handle a successful return */ | ||||||
| @@ -435,8 +452,8 @@ const char *gst_deserialize( | |||||||
| } | } | ||||||
|      |      | ||||||
| /* Allow appending other types to buffers */ | /* Allow appending other types to buffers */ | ||||||
| BUFFER_DEFINE(number, GstNumber) | BUFFER_DEFINE(real, GstReal) | ||||||
| /*BUFFER_DEFINE(u16, uint16_t)*/ | BUFFER_DEFINE(integer, GstInteger) | ||||||
| BUFFER_DEFINE(u32, uint32_t) | BUFFER_DEFINE(u32, uint32_t) | ||||||
|  |  | ||||||
| /* Serialize a value and write to a buffer. Returns possible | /* Serialize a value and write to a buffer. Returns possible | ||||||
| @@ -455,7 +472,8 @@ const char *gst_serialize_impl( | |||||||
| #define write_byte(b) gst_buffer_push(vm, buffer, (b)) | #define write_byte(b) gst_buffer_push(vm, buffer, (b)) | ||||||
| #define write_u32(b) gst_buffer_push_u32(vm, buffer, (b)) | #define write_u32(b) gst_buffer_push_u32(vm, buffer, (b)) | ||||||
| #define write_u16(b) gst_buffer_push_u16(vm, buffer, (b)) | #define write_u16(b) gst_buffer_push_u16(vm, buffer, (b)) | ||||||
| #define write_dbl(b) gst_buffer_push_number(vm, buffer, (b)) | #define write_dbl(b) gst_buffer_push_real(vm, buffer, (b)) | ||||||
|  | #define write_int(b) gst_buffer_push_integer(vm, buffer, (b)) | ||||||
|  |  | ||||||
|     /* Check non reference types - if successful, return NULL */ |     /* Check non reference types - if successful, return NULL */ | ||||||
|     switch (x.type) { |     switch (x.type) { | ||||||
| @@ -465,17 +483,16 @@ const char *gst_serialize_impl( | |||||||
|         case GST_BOOLEAN: |         case GST_BOOLEAN: | ||||||
|             write_byte(x.data.boolean ? 202 : 203); |             write_byte(x.data.boolean ? 202 : 203); | ||||||
|             return NULL; |             return NULL; | ||||||
|         case GST_NUMBER:  |         case GST_REAL:  | ||||||
|             { |             write_byte(204); | ||||||
|                 GstNumber number = x.data.number; |             write_dbl(x.data.real); | ||||||
|                 int32_t int32Num = (int32_t) number; |             return NULL; | ||||||
|                 if (number == (GstNumber) int32Num && |         case GST_INTEGER: | ||||||
|                         int32Num <= 100 && int32Num >= -100) { |             if (x.data.integer <= 100 && x.data.integer >= -100) { | ||||||
|                     write_byte(int32Num + 100); |                 write_byte(x.data.integer + 100); | ||||||
|                 } else { |             } else { | ||||||
|                     write_byte(204); |                 write_byte(218); | ||||||
|                     write_dbl(number); |                 write_int(x.data.integer); | ||||||
|                 } |  | ||||||
|             } |             } | ||||||
|             return NULL; |             return NULL; | ||||||
|         case GST_CFUNCTION: |         case GST_CFUNCTION: | ||||||
| @@ -487,9 +504,9 @@ const char *gst_serialize_impl( | |||||||
|  |  | ||||||
|     /* Check if already seen - if so, use reference */ |     /* Check if already seen - if so, use reference */ | ||||||
|     check = gst_object_get(visited, x); |     check = gst_object_get(visited, x); | ||||||
|     if (check.type == GST_NUMBER) { |     if (check.type == GST_INTEGER) { | ||||||
|         write_byte(217); |         write_byte(217); | ||||||
|         write_u32((uint32_t) check.data.number); |         write_u32((uint32_t) check.data.integer); | ||||||
|         return NULL; |         return NULL; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -549,8 +566,8 @@ const char *gst_serialize_impl( | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     /* Record reference */ |     /* Record reference */ | ||||||
|     check.type = GST_NUMBER; |     check.type = GST_INTEGER; | ||||||
|     check.data.number = *nextId++; |     check.data.integer = *nextId++; | ||||||
|     gst_object_put(vm, visited, x, check); |     gst_object_put(vm, visited, x, check); | ||||||
|  |  | ||||||
|     /* Return success */ |     /* Return success */ | ||||||
|   | |||||||
							
								
								
									
										189
									
								
								core/stl.c
									
									
									
									
									
								
							
							
						
						
									
										189
									
								
								core/stl.c
									
									
									
									
									
								
							| @@ -27,68 +27,54 @@ | |||||||
|  |  | ||||||
| #include <gst/disasm.h> | #include <gst/disasm.h> | ||||||
|  |  | ||||||
| static const char GST_EXPECTED_NUMBER_OP[] = "expected operand to be number"; | static const char GST_EXPECTED_INTEGER[] = "expected integer"; | ||||||
| static const char GST_EXPECTED_STRING[] = "expected string"; | static const char GST_EXPECTED_STRING[] = "expected string"; | ||||||
|  |  | ||||||
| /***/ | /***/ | ||||||
| /* Arithmetic */ | /* Arithmetic */ | ||||||
| /***/ | /***/ | ||||||
|  |  | ||||||
| #define SIMPLE_ACCUM_FUNCTION(name, start, op)\ | #define MAKE_BINOP(name, op)\ | ||||||
| int gst_stl_##name(Gst* vm) {\ | GstValue gst_stl_binop_##name(GstValue lhs, GstValue rhs) {\ | ||||||
|     GstValue ret;\ |     if (lhs.type == GST_INTEGER)\ | ||||||
|     uint32_t j, count;\ |         if (rhs.type == GST_INTEGER)\ | ||||||
|     ret.type = GST_NUMBER;\ |             return gst_wrap_integer(lhs.data.integer op rhs.data.integer);\ | ||||||
|     ret.data.number = start;\ |         else if (rhs.type == GST_REAL)\ | ||||||
|     count = gst_count_args(vm);\ |             return gst_wrap_real(lhs.data.integer op rhs.data.real);\ | ||||||
|     for (j = 0; j < count; ++j) {\ |         else\ | ||||||
|         GstValue operand = gst_arg(vm, j);\ |             return gst_wrap_nil();\ | ||||||
|         if (operand.type != GST_NUMBER)\ |     else if (lhs.type == GST_REAL)\ | ||||||
|             gst_c_throwc(vm, GST_EXPECTED_NUMBER_OP);\ |         if (rhs.type == GST_INTEGER)\ | ||||||
|         ret.data.number op operand.data.number;\ |             return gst_wrap_real(lhs.data.real op rhs.data.integer);\ | ||||||
|     }\ |         else if (rhs.type == GST_REAL)\ | ||||||
|     gst_c_return(vm, ret);\ |             return gst_wrap_real(lhs.data.real op rhs.data.real);\ | ||||||
|  |         else\ | ||||||
|  |             return gst_wrap_nil();\ | ||||||
|  |     else\ | ||||||
|  |         return gst_wrap_nil();\ | ||||||
| } | } | ||||||
|  |  | ||||||
| SIMPLE_ACCUM_FUNCTION(add, 0, +=) | #define SIMPLE_ACCUM_FUNCTION(name, start, op)\ | ||||||
| SIMPLE_ACCUM_FUNCTION(mul, 1, *=) | MAKE_BINOP(name, op)\ | ||||||
|  | int gst_stl_##name(Gst* vm) {\ | ||||||
|  |     GstValue lhs, rhs;\ | ||||||
|  |     uint32_t j, count;\ | ||||||
|  |     count = gst_count_args(vm);\ | ||||||
|  |     lhs = gst_arg(vm, 0);\ | ||||||
|  |     for (j = 1; j < count; ++j) {\ | ||||||
|  |         rhs = gst_arg(vm, j);\ | ||||||
|  |         lhs = gst_stl_binop_##name(lhs, rhs);\ | ||||||
|  |     }\ | ||||||
|  |     gst_c_return(vm, lhs);\ | ||||||
|  | } | ||||||
|  |  | ||||||
|  | SIMPLE_ACCUM_FUNCTION(add, 0, +) | ||||||
|  | SIMPLE_ACCUM_FUNCTION(mul, 1, *) | ||||||
|  | SIMPLE_ACCUM_FUNCTION(sub, 0, -) | ||||||
|  | SIMPLE_ACCUM_FUNCTION(div, 1, /) | ||||||
|  |  | ||||||
| #undef SIMPLE_ACCUM_FUNCTION | #undef SIMPLE_ACCUM_FUNCTION | ||||||
|  |  | ||||||
| #define UNARY_ACCUM_FUNCTION(name, zeroval, unaryop, op)\ |  | ||||||
| int gst_stl_##name(Gst* vm) {\ |  | ||||||
|     GstValue ret;\ |  | ||||||
|     GstValue operand;\ |  | ||||||
|     uint32_t j, count;\ |  | ||||||
|     ret.type = GST_NUMBER;\ |  | ||||||
|     count = gst_count_args(vm);\ |  | ||||||
|     if (count == 0) {\ |  | ||||||
|         ret.data.number = zeroval;\ |  | ||||||
|         gst_c_return(vm, ret);\ |  | ||||||
|     }\ |  | ||||||
|     operand = gst_arg(vm, 0);\ |  | ||||||
|     if (operand.type != GST_NUMBER)\ |  | ||||||
|         gst_c_throwc(vm, GST_EXPECTED_NUMBER_OP);\ |  | ||||||
|     if (count == 1) {\ |  | ||||||
|         ret.data.number = unaryop operand.data.number;\ |  | ||||||
|         gst_c_return(vm, ret);\ |  | ||||||
|     } else {\ |  | ||||||
|         ret.data.number = operand.data.number;\ |  | ||||||
|     }\ |  | ||||||
|     for (j = 1; j < count; ++j) {\ |  | ||||||
|         operand = gst_arg(vm, j);\ |  | ||||||
|         if (operand.type != GST_NUMBER)\ |  | ||||||
|             gst_c_throwc(vm, GST_EXPECTED_NUMBER_OP);\ |  | ||||||
|         ret.data.number op operand.data.number;\ |  | ||||||
|     }\ |  | ||||||
|     gst_c_return(vm, ret);\ |  | ||||||
| } |  | ||||||
|  |  | ||||||
| UNARY_ACCUM_FUNCTION(sub, 0, -, -=) |  | ||||||
| UNARY_ACCUM_FUNCTION(div, 1, 1/, /=) |  | ||||||
|  |  | ||||||
| #undef UNARY_ACCUM_FUNCTION |  | ||||||
|  |  | ||||||
| #define COMPARE_FUNCTION(name, check)\ | #define COMPARE_FUNCTION(name, check)\ | ||||||
| int gst_stl_##name(Gst *vm) {\ | int gst_stl_##name(Gst *vm) {\ | ||||||
|     GstValue ret;\ |     GstValue ret;\ | ||||||
| @@ -131,43 +117,49 @@ int gst_stl_length(Gst *vm) { | |||||||
|         gst_c_return(vm, ret); |         gst_c_return(vm, ret); | ||||||
|     } |     } | ||||||
|     if (count == 1) { |     if (count == 1) { | ||||||
|         ret.type = GST_NUMBER; |         ret.type = GST_INTEGER; | ||||||
|         GstValue x = gst_arg(vm, 0); |         GstValue x = gst_arg(vm, 0); | ||||||
|         switch (x.type) { |         switch (x.type) { | ||||||
|         default: |         default: | ||||||
|             gst_c_throwc(vm, "cannot get length"); |             gst_c_throwc(vm, "cannot get length"); | ||||||
|         case GST_STRING: |         case GST_STRING: | ||||||
|             ret.data.number = gst_string_length(x.data.string); |             ret.data.integer = gst_string_length(x.data.string); | ||||||
|             break; |             break; | ||||||
|         case GST_ARRAY: |         case GST_ARRAY: | ||||||
|             ret.data.number = x.data.array->count; |             ret.data.integer = x.data.array->count; | ||||||
|             break; |             break; | ||||||
|         case GST_BYTEBUFFER: |         case GST_BYTEBUFFER: | ||||||
|             ret.data.number = x.data.buffer->count; |             ret.data.integer = x.data.buffer->count; | ||||||
|             break; |             break; | ||||||
|         case GST_TUPLE: |         case GST_TUPLE: | ||||||
|             ret.data.number = gst_tuple_length(x.data.tuple); |             ret.data.integer = gst_tuple_length(x.data.tuple); | ||||||
|             break; |             break; | ||||||
|         case GST_OBJECT: |         case GST_OBJECT: | ||||||
|             ret.data.number = x.data.object->count; |             ret.data.integer = x.data.object->count; | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     gst_c_return(vm, ret); |     gst_c_return(vm, ret); | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Get nth argument, not including first argument */ | /* Convert to integer */ | ||||||
| int gst_stl_select(Gst *vm) { | int gst_stl_to_int(Gst *vm) { | ||||||
|     GstValue selector; |     GstValue x = gst_arg(vm, 0); | ||||||
|     uint32_t count, n; |     if (x.type == GST_INTEGER) gst_c_return(vm, x); | ||||||
|     count = gst_count_args(vm); |     if (x.type == GST_REAL) | ||||||
|     if (count == 0) |         gst_c_return(vm, gst_wrap_integer((GstInteger) x.data.real)); | ||||||
|         gst_c_throwc(vm, "select takes at least one argument"); |     else | ||||||
|     selector = gst_arg(vm, 0); |        gst_c_throwc(vm, "expected number");  | ||||||
|     if (selector.type != GST_NUMBER) | } | ||||||
|         gst_c_throwc(vm, GST_EXPECTED_NUMBER_OP); |  | ||||||
|     n = selector.data.number; | /* Convert to integer */ | ||||||
|     gst_c_return(vm, gst_arg(vm, n + 1)); | int gst_stl_to_real(Gst *vm) { | ||||||
|  |     GstValue x = gst_arg(vm, 0); | ||||||
|  |     if (x.type == GST_REAL) gst_c_return(vm, x); | ||||||
|  |     if (x.type == GST_INTEGER) | ||||||
|  |         gst_c_return(vm, gst_wrap_real((GstReal) x.data.integer)); | ||||||
|  |     else | ||||||
|  |        gst_c_throwc(vm, "expected number");  | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Get a slice of a sequence */ | /* Get a slice of a sequence */ | ||||||
| @@ -178,7 +170,7 @@ int gst_stl_slice(Gst *vm) { | |||||||
|     const GstValue *data; |     const GstValue *data; | ||||||
|     uint32_t length; |     uint32_t length; | ||||||
|     uint32_t newlength; |     uint32_t newlength; | ||||||
|     GstNumber num; |     GstInteger num; | ||||||
|  |  | ||||||
|     /* Get data */ |     /* Get data */ | ||||||
|     x = gst_arg(vm, 0); |     x = gst_arg(vm, 0); | ||||||
| @@ -189,18 +181,18 @@ int gst_stl_slice(Gst *vm) { | |||||||
|     if (count < 2) { |     if (count < 2) { | ||||||
|         from = 0; |         from = 0; | ||||||
|     } else { |     } else { | ||||||
|         if (!gst_check_number(vm, 1, &num)) |         if (!gst_check_integer(vm, 1, &num)) | ||||||
|             gst_c_throwc(vm, GST_EXPECTED_NUMBER_OP); |             gst_c_throwc(vm, GST_EXPECTED_INTEGER); | ||||||
|         from = gst_to_index(num, length); |         from = gst_startrange(num, length); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /* Get to index */ |     /* Get to index */ | ||||||
|     if (count < 3) { |     if (count < 3) { | ||||||
|         to = length; |         to = length; | ||||||
|     } else { |     } else { | ||||||
|         if (!gst_check_number(vm, 2, &num)) |         if (!gst_check_integer(vm, 2, &num)) | ||||||
|             gst_c_throwc(vm, GST_EXPECTED_NUMBER_OP); |             gst_c_throwc(vm, GST_EXPECTED_INTEGER); | ||||||
|         to = gst_to_endrange(num, length); |         to = gst_endrange(num, length); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /* Check from bad bounds */ |     /* Check from bad bounds */ | ||||||
| @@ -232,8 +224,11 @@ int gst_stl_type(Gst *vm) { | |||||||
|     switch (x.type) { |     switch (x.type) { | ||||||
|     default: |     default: | ||||||
|         break; |         break; | ||||||
|     case GST_NUMBER: |     case GST_REAL: | ||||||
|         typestr = "number"; |         typestr = "real"; | ||||||
|  |         break; | ||||||
|  |     case GST_INTEGER: | ||||||
|  |         typestr = "integer"; | ||||||
|         break; |         break; | ||||||
|     case GST_BOOLEAN: |     case GST_BOOLEAN: | ||||||
|         typestr = "boolean"; |         typestr = "boolean"; | ||||||
| @@ -419,9 +414,9 @@ int gst_stl_ensure(Gst *vm) { | |||||||
|     GstValue cap = gst_arg(vm, 1); |     GstValue cap = gst_arg(vm, 1); | ||||||
|     if (ds.type != GST_ARRAY) |     if (ds.type != GST_ARRAY) | ||||||
|         gst_c_throwc(vm, "expected array"); |         gst_c_throwc(vm, "expected array"); | ||||||
|     if (cap.type != GST_NUMBER) |     if (cap.type != GST_INTEGER) | ||||||
|         gst_c_throwc(vm, "expected number"); |         gst_c_throwc(vm, GST_EXPECTED_INTEGER); | ||||||
|     gst_array_ensure(vm, ds.data.array, (uint32_t) cap.data.number); |     gst_array_ensure(vm, ds.data.array, (uint32_t) cap.data.integer); | ||||||
|     gst_c_return(vm, ds); |     gst_c_return(vm, ds); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -464,8 +459,8 @@ int gst_stl_tostring(Gst *vm) { | |||||||
| /* Exit */ | /* Exit */ | ||||||
| int gst_stl_exit(Gst *vm) { | int gst_stl_exit(Gst *vm) { | ||||||
|     int ret; |     int ret; | ||||||
|     GstValue exitValue = gst_arg(vm, 0); |     GstValue x = gst_arg(vm, 0); | ||||||
|     ret = (exitValue.type == GST_NUMBER) ? exitValue.data.number : 0; |     ret = x.type == GST_INTEGER ? x.data.integer : (x.type == GST_REAL ? x.data.real : 0); | ||||||
|     exit(ret); |     exit(ret); | ||||||
|     return GST_RETURN_OK; |     return GST_RETURN_OK; | ||||||
| } | } | ||||||
| @@ -532,31 +527,6 @@ int gst_stl_open(Gst *vm) { | |||||||
|     gst_c_return(vm, gst_wrap_userdata(fp)); |     gst_c_return(vm, gst_wrap_userdata(fp)); | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Write a string to a file */ |  | ||||||
| int gst_stl_write(Gst *vm) { |  | ||||||
|     GstValue f = gst_arg(vm, 0); |  | ||||||
|     FILE *f; |  | ||||||
|     if (f.type != GST_USERDATA) |  | ||||||
|         gst_c_throwc(vm, "expected file userdata"); |  | ||||||
|     f = *(FILE **)f.data.pointer |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /* Read an entire file in one go. Will be faster than sequential reads for |  | ||||||
|  * small to moderately sized files */ |  | ||||||
| int gst_stl_slurp(Gst *vm) { |  | ||||||
|     GstValue x = gst_arg(vm, 0); |  | ||||||
|     const uint8_t *fname; |  | ||||||
|     FILE *f; |  | ||||||
|     if (gst_count_args(vm) < 1 || x.type != GST_STRING) |  | ||||||
|         gst_c_throwc(vm, "expected file name"); |  | ||||||
|     fname = gst_to_string(vm, gst_arg(vm, 0)); |  | ||||||
|     f = fopen((const char *) fname, "rb"); |  | ||||||
|     if (!f) |  | ||||||
|         gst_c_throwc(vm, "could not open file for reading"); |  | ||||||
|     // TODO use fseek and like functions to read file into a buffer. |  | ||||||
|  |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /* Write a string to a file in one go. Overwrites an existing file. */ | /* Write a string to a file in one go. Overwrites an existing file. */ | ||||||
|  |  | ||||||
| /****/ | /****/ | ||||||
| @@ -595,8 +565,9 @@ static const GstModuleItem const std_module[] = { | |||||||
|     {"<=", gst_stl_lessthaneq}, |     {"<=", gst_stl_lessthaneq}, | ||||||
|     {">=", gst_stl_greaterthaneq}, |     {">=", gst_stl_greaterthaneq}, | ||||||
|     {"length", gst_stl_length}, |     {"length", gst_stl_length}, | ||||||
|  |     {"to-integer", gst_stl_to_int}, | ||||||
|  |     {"to-real", gst_stl_to_real}, | ||||||
|     {"type", gst_stl_type}, |     {"type", gst_stl_type}, | ||||||
|     {"select", gst_stl_select}, |  | ||||||
|     {"slice", gst_stl_slice}, |     {"slice", gst_stl_slice}, | ||||||
|     {"array", gst_stl_array}, |     {"array", gst_stl_array}, | ||||||
|     {"tuple", gst_stl_tuple}, |     {"tuple", gst_stl_tuple}, | ||||||
|   | |||||||
							
								
								
									
										58
									
								
								core/util.c
									
									
									
									
									
								
							
							
						
						
									
										58
									
								
								core/util.c
									
									
									
									
									
								
							| @@ -51,7 +51,8 @@ int gst_check_##NAME(Gst *vm, uint32_t i, TYPE (*out)) {\ | |||||||
|     return 1;\ |     return 1;\ | ||||||
| }\ | }\ | ||||||
|  |  | ||||||
| GST_WRAP_DEFINE(number, GstNumber, GST_NUMBER, number) | GST_WRAP_DEFINE(real, GstReal, GST_REAL, real) | ||||||
|  | GST_WRAP_DEFINE(integer, GstInteger, GST_INTEGER, integer) | ||||||
| GST_WRAP_DEFINE(boolean, int, GST_BOOLEAN, boolean) | GST_WRAP_DEFINE(boolean, int, GST_BOOLEAN, boolean) | ||||||
| GST_WRAP_DEFINE(string, const uint8_t *, GST_STRING, string) | GST_WRAP_DEFINE(string, const uint8_t *, GST_STRING, string) | ||||||
| GST_WRAP_DEFINE(array, GstArray *, GST_ARRAY, array) | GST_WRAP_DEFINE(array, GstArray *, GST_ARRAY, array) | ||||||
| @@ -166,41 +167,26 @@ int gst_hashtable_view(GstValue tab, const GstValue **data, uint32_t *cap) { | |||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Allow negative indexing to get from end of array like structure */ | GstReal gst_integer_to_real(GstInteger x) { | ||||||
| /* This probably isn't very fast - look at Lua conversion function. |     return (GstReal) x; | ||||||
|  * I would like to keep this standard C for as long as possible, though. */ |  | ||||||
| int32_t gst_to_index(GstNumber raw, int64_t len) { |  | ||||||
|     int32_t toInt = raw; |  | ||||||
|     if ((GstNumber) toInt == raw) { |  | ||||||
|         /* We were able to convert */ |  | ||||||
|         if (toInt < 0 && len > 0) {  |  | ||||||
|             /* Index from end */ |  | ||||||
|             if (toInt < -len) return -1;     |  | ||||||
|             return len + toInt; |  | ||||||
|         } else {     |  | ||||||
|             /* Normal indexing */ |  | ||||||
|             if (toInt >= len) return -1; |  | ||||||
|             return toInt; |  | ||||||
|         } |  | ||||||
|     } else { |  | ||||||
|         return -1; |  | ||||||
|     } |  | ||||||
| } | } | ||||||
|  |  | ||||||
| int32_t gst_to_endrange(GstNumber raw, int64_t len) { | GstInteger gst_real_to_integer(GstReal x) { | ||||||
|     int32_t toInt = raw; |     return (GstInteger) x; | ||||||
|     if ((GstNumber) toInt == raw) { | } | ||||||
|         /* We were able to convert */ |  | ||||||
|         if (toInt < 0 && len > 0) {  | GstInteger gst_startrange(GstInteger raw, uint32_t len) { | ||||||
|             /* Index from end */ |     if (raw > len) | ||||||
|             if (toInt < -len - 1) return -1;     |         return -1; | ||||||
|             return len + toInt + 1; |     if (raw < 0) | ||||||
|         } else {     |         return len + raw; | ||||||
|             /* Normal indexing */ |     return raw; | ||||||
|             if (toInt >= len) return -1; | } | ||||||
|             return toInt; |  | ||||||
|         } | GstInteger gst_endrange(GstInteger raw, uint32_t len) { | ||||||
|     } else { |     if (raw > len) | ||||||
|         return -1; |         return -1; | ||||||
|     } |     if (raw < 0) | ||||||
|  |         return len + raw + 1; | ||||||
|  |     return raw; | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										127
									
								
								core/value.c
									
									
									
									
									
								
							
							
						
						
									
										127
									
								
								core/value.c
									
									
									
									
									
								
							| @@ -31,13 +31,18 @@ int gst_truthy(GstValue v) { | |||||||
| /* Temporary buffer size */ | /* Temporary buffer size */ | ||||||
| #define GST_BUFSIZE 36 | #define GST_BUFSIZE 36 | ||||||
|  |  | ||||||
| static const uint8_t *number_to_string(Gst *vm, GstNumber x) { | static const uint8_t *real_to_string(Gst *vm, GstReal x) { | ||||||
|     uint8_t buf[GST_BUFSIZE]; |     uint8_t buf[GST_BUFSIZE]; | ||||||
|     /* TODO - not depend on stdio */ |  | ||||||
|     int count = snprintf((char *) buf, GST_BUFSIZE, "%.21g", x); |     int count = snprintf((char *) buf, GST_BUFSIZE, "%.21g", x); | ||||||
|     return gst_string_b(vm, buf, (uint32_t) count); |     return gst_string_b(vm, buf, (uint32_t) count); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static const uint8_t *integer_to_string(Gst *vm, GstInteger x) { | ||||||
|  |     uint8_t buf[GST_BUFSIZE]; | ||||||
|  |     int count = snprintf((char *) buf, GST_BUFSIZE, "%ld", x); | ||||||
|  |     return gst_string_b(vm, buf, (uint32_t) count); | ||||||
|  | } | ||||||
|  |  | ||||||
| static const char *HEX_CHARACTERS = "0123456789abcdef"; | static const char *HEX_CHARACTERS = "0123456789abcdef"; | ||||||
| #define HEX(i) (((uint8_t *) HEX_CHARACTERS)[(i)]) | #define HEX(i) (((uint8_t *) HEX_CHARACTERS)[(i)]) | ||||||
|  |  | ||||||
| @@ -77,13 +82,14 @@ const uint8_t *gst_to_string(Gst *vm, GstValue x) { | |||||||
|     case GST_NIL: |     case GST_NIL: | ||||||
|         return gst_string_c(vm, "nil"); |         return gst_string_c(vm, "nil"); | ||||||
|     case GST_BOOLEAN: |     case GST_BOOLEAN: | ||||||
|         if (x.data.boolean) { |         if (x.data.boolean) | ||||||
|             return gst_string_c(vm, "true"); |             return gst_string_c(vm, "true"); | ||||||
|         } else { |         else | ||||||
|             return gst_string_c(vm, "false"); |             return gst_string_c(vm, "false"); | ||||||
|         } |     case GST_REAL: | ||||||
|     case GST_NUMBER: |         return real_to_string(vm, x.data.real); | ||||||
|         return number_to_string(vm, x.data.number); |     case GST_INTEGER: | ||||||
|  |         return integer_to_string(vm, x.data.integer); | ||||||
|     case GST_ARRAY: |     case GST_ARRAY: | ||||||
|         return string_description(vm, "array", x.data.pointer); |         return string_description(vm, "array", x.data.pointer); | ||||||
|     case GST_TUPLE: |     case GST_TUPLE: | ||||||
| @@ -125,8 +131,11 @@ int gst_equals(GstValue x, GstValue y) { | |||||||
|         case GST_BOOLEAN: |         case GST_BOOLEAN: | ||||||
|             result = (x.data.boolean == y.data.boolean); |             result = (x.data.boolean == y.data.boolean); | ||||||
|             break; |             break; | ||||||
|         case GST_NUMBER: |         case GST_REAL: | ||||||
|             result = (x.data.number == y.data.number); |             result = (x.data.real == y.data.real); | ||||||
|  |             break; | ||||||
|  |         case GST_INTEGER: | ||||||
|  |             result = (x.data.integer == y.data.integer); | ||||||
|             break; |             break; | ||||||
|         default: |         default: | ||||||
|             /* compare pointers */ |             /* compare pointers */ | ||||||
| @@ -147,17 +156,6 @@ uint32_t gst_hash(GstValue x) { | |||||||
|     case GST_BOOLEAN: |     case GST_BOOLEAN: | ||||||
|         hash = x.data.boolean; |         hash = x.data.boolean; | ||||||
|         break; |         break; | ||||||
|     case GST_NUMBER: |  | ||||||
|         { |  | ||||||
|             union { |  | ||||||
|                 uint32_t hash; |  | ||||||
|                 GstNumber number; |  | ||||||
|             } u; |  | ||||||
|             u.number = x.data.number; |  | ||||||
|             hash = u.hash; |  | ||||||
|         } |  | ||||||
|         break; |  | ||||||
|         /* String hashes */ |  | ||||||
|     case GST_STRING: |     case GST_STRING: | ||||||
|         hash = gst_string_hash(x.data.string); |         hash = gst_string_hash(x.data.string); | ||||||
|         break; |         break; | ||||||
| @@ -168,15 +166,7 @@ uint32_t gst_hash(GstValue x) { | |||||||
|         hash = gst_struct_hash(x.data.st); |         hash = gst_struct_hash(x.data.st); | ||||||
|         break; |         break; | ||||||
|     default: |     default: | ||||||
|         /* Cast the pointer */ |         hash = x.data.dwords[0] ^ x.data.dwords[1]; | ||||||
|         { |  | ||||||
|             union { |  | ||||||
|                 void * pointer; |  | ||||||
|                 uint32_t hash; |  | ||||||
|             } u; |  | ||||||
|             u.pointer = x.data.pointer; |  | ||||||
|             hash = u.hash; |  | ||||||
|         } |  | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
|     return hash; |     return hash; | ||||||
| @@ -196,12 +186,17 @@ int gst_compare(GstValue x, GstValue y) { | |||||||
|                 } else { |                 } else { | ||||||
|                     return x.data.boolean ? 1 : -1; |                     return x.data.boolean ? 1 : -1; | ||||||
|                 } |                 } | ||||||
|             case GST_NUMBER: |             case GST_REAL: | ||||||
|                 /* TODO: define behavior for NaN and infinties. */ |                 if (x.data.real == y.data.real) { | ||||||
|                 if (x.data.number == y.data.number) { |  | ||||||
|                     return 0; |                     return 0; | ||||||
|                 } else { |                 } else { | ||||||
|                     return x.data.number > y.data.number ? 1 : -1; |                     return x.data.real > y.data.real ? 1 : -1; | ||||||
|  |                 } | ||||||
|  |             case GST_INTEGER: | ||||||
|  |                 if (x.data.integer == y.data.integer) { | ||||||
|  |                     return 0; | ||||||
|  |                 } else { | ||||||
|  |                     return x.data.integer > y.data.integer ? 1 : -1; | ||||||
|                 } |                 } | ||||||
|             case GST_STRING: |             case GST_STRING: | ||||||
|                 return gst_string_compare(x.data.string, y.data.string); |                 return gst_string_compare(x.data.string, y.data.string); | ||||||
| @@ -236,45 +231,38 @@ int gst_compare(GstValue x, GstValue y) { | |||||||
|     return 1; |     return 1; | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Convert a number into a byte. */ |  | ||||||
| static uint8_t to_byte(GstNumber raw) { |  | ||||||
|     if (raw > 255) return 255; |  | ||||||
|     if (raw < 0) return 0; |  | ||||||
|     return (uint8_t) raw; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /* Get a value out af an associated data structure.  | /* Get a value out af an associated data structure.  | ||||||
|  * Returns possible c error message, and NULL for no error. The |  * Returns possible c error message, and NULL for no error. The | ||||||
|  * useful return value is written to out on success */ |  * useful return value is written to out on success */ | ||||||
| const char *gst_get(GstValue ds, GstValue key, GstValue *out) { | const char *gst_get(GstValue ds, GstValue key, GstValue *out) { | ||||||
|     int32_t index; |     GstInteger index; | ||||||
|     GstValue ret; |     GstValue ret; | ||||||
|     switch (ds.type) { |     switch (ds.type) { | ||||||
|     case GST_ARRAY: |     case GST_ARRAY: | ||||||
|         if (key.type != GST_NUMBER) return "expected numeric key"; |         if (key.type != GST_INTEGER) return "expected integer key"; | ||||||
|         index = gst_to_index(key.data.number, ds.data.array->count); |         index = gst_startrange(key.data.integer, ds.data.array->count); | ||||||
|         if (index == -1) return "invalid array access"; |         if (index < 0) return "invalid array access"; | ||||||
|         ret = ds.data.array->data[index]; |         ret = ds.data.array->data[index]; | ||||||
|         break; |         break; | ||||||
|     case GST_TUPLE: |     case GST_TUPLE: | ||||||
|         if (key.type != GST_NUMBER) return "expected numeric key"; |         if (key.type != GST_INTEGER) return "expected integer key"; | ||||||
|         index = gst_to_index(key.data.number, gst_tuple_length(ds.data.tuple)); |         index = gst_startrange(key.data.integer, gst_tuple_length(ds.data.tuple)); | ||||||
|         if (index < 0) return "invalid tuple access"; |         if (index < 0) return "invalid tuple access"; | ||||||
|         ret = ds.data.tuple[index]; |         ret = ds.data.tuple[index]; | ||||||
|         break; |         break; | ||||||
|     case GST_BYTEBUFFER: |     case GST_BYTEBUFFER: | ||||||
|         if (key.type != GST_NUMBER) return "expected numeric key"; |         if (key.type != GST_INTEGER) return "expected integer key"; | ||||||
|         index = gst_to_index(key.data.number, ds.data.buffer->count); |         index = gst_startrange(key.data.integer, ds.data.buffer->count); | ||||||
|         if (index == -1) return "invalid buffer access"; |         if (index < 0) return "invalid buffer access"; | ||||||
|         ret.type = GST_NUMBER; |         ret.type = GST_INTEGER; | ||||||
|         ret.data.number = ds.data.buffer->data[index]; |         ret.data.integer = ds.data.buffer->data[index]; | ||||||
|         break; |         break; | ||||||
|     case GST_STRING: |     case GST_STRING: | ||||||
|         if (key.type != GST_NUMBER) return "expected numeric key"; |         if (key.type != GST_INTEGER) return "expected integer key"; | ||||||
|         index = gst_to_index(key.data.number, gst_string_length(ds.data.string)); |         index = gst_startrange(key.data.integer, gst_string_length(ds.data.string)); | ||||||
|         if (index == -1) return "invalid string access"; |         if (index < 0) return "invalid string access"; | ||||||
|         ret.type = GST_NUMBER; |         ret.type = GST_INTEGER; | ||||||
|         ret.data.number = ds.data.string[index]; |         ret.data.integer = ds.data.string[index]; | ||||||
|         break; |         break; | ||||||
|     case GST_STRUCT: |     case GST_STRUCT: | ||||||
|         ret = gst_struct_get(ds.data.st, key); |         ret = gst_struct_get(ds.data.st, key); | ||||||
| @@ -292,20 +280,20 @@ const char *gst_get(GstValue ds, GstValue key, GstValue *out) { | |||||||
| /* Set a value in an associative data structure. Returns possible | /* Set a value in an associative data structure. Returns possible | ||||||
|  * error message, and NULL if no error. */ |  * error message, and NULL if no error. */ | ||||||
| const char *gst_set(Gst *vm, GstValue ds, GstValue key, GstValue value) { | const char *gst_set(Gst *vm, GstValue ds, GstValue key, GstValue value) { | ||||||
|     int32_t index; |     GstInteger index; | ||||||
|     switch (ds.type) { |     switch (ds.type) { | ||||||
|     case GST_ARRAY: |     case GST_ARRAY: | ||||||
|         if (key.type != GST_NUMBER) return "expected numeric key"; |         if (key.type != GST_INTEGER) return "expected integer key"; | ||||||
|         index = gst_to_index(key.data.number, ds.data.array->count); |         index = gst_startrange(key.data.integer, ds.data.array->count); | ||||||
|         if (index == -1) return "invalid array access"; |         if (index < 0) return "invalid array access"; | ||||||
|         ds.data.array->data[index] = value; |         ds.data.array->data[index] = value; | ||||||
|         break; |         break; | ||||||
|     case GST_BYTEBUFFER: |     case GST_BYTEBUFFER: | ||||||
|         if (key.type != GST_NUMBER) return "expected numeric key"; |         if (key.type != GST_INTEGER) return "expected integer key"; | ||||||
|         if (value.type != GST_NUMBER) return "expected numeric value"; |         if (value.type != GST_INTEGER) return "expected integer value"; | ||||||
|         index = gst_to_index(key.data.number, ds.data.buffer->count); |         index = gst_startrange(key.data.integer, ds.data.buffer->count); | ||||||
|         if (index == -1) return "invalid buffer access"; |         if (index < 0) return "invalid buffer access"; | ||||||
|         ds.data.buffer->data[index] = to_byte(value.data.number); |         ds.data.buffer->data[index] = (uint8_t) value.data.integer; | ||||||
|         break; |         break; | ||||||
|     case GST_OBJECT: |     case GST_OBJECT: | ||||||
|         gst_object_put(vm, ds.data.object, key, value); |         gst_object_put(vm, ds.data.object, key, value); | ||||||
| @@ -317,8 +305,8 @@ const char *gst_set(Gst *vm, GstValue ds, GstValue key, GstValue value) { | |||||||
| } | } | ||||||
|  |  | ||||||
| /* Get the length of an object. Returns errors for invalid types */ | /* Get the length of an object. Returns errors for invalid types */ | ||||||
| int gst_length(Gst *vm, GstValue x, GstValue *len) { | GstInteger gst_length(Gst *vm, GstValue x) { | ||||||
|     uint32_t length; |     GstInteger length; | ||||||
|     switch (x.type) { |     switch (x.type) { | ||||||
|         default: |         default: | ||||||
|             vm->ret = gst_string_cv(vm, "cannot get length"); |             vm->ret = gst_string_cv(vm, "cannot get length"); | ||||||
| @@ -342,9 +330,6 @@ int gst_length(Gst *vm, GstValue x, GstValue *len) { | |||||||
|             length = x.data.object->count; |             length = x.data.object->count; | ||||||
|             break; |             break; | ||||||
|     } |     } | ||||||
|     /* Normal numeric return */ |     return length; | ||||||
|     len->type = GST_NUMBER; |  | ||||||
|     len->data.number = (GstNumber) length; |  | ||||||
|     return GST_RETURN_OK; |  | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										96
									
								
								core/vm.c
									
									
									
									
									
								
							
							
						
						
									
										96
									
								
								core/vm.c
									
									
									
									
									
								
							| @@ -24,8 +24,6 @@ | |||||||
|  |  | ||||||
| static const char GST_NO_UPVALUE[] = "no upvalue"; | static const char GST_NO_UPVALUE[] = "no upvalue"; | ||||||
| static const char GST_EXPECTED_FUNCTION[] = "expected function"; | static const char GST_EXPECTED_FUNCTION[] = "expected function"; | ||||||
| static const char GST_EXPECTED_NUMBER_ROP[] = "expected right operand to be number"; |  | ||||||
| static const char GST_EXPECTED_NUMBER_LOP[] = "expected left operand to be number"; |  | ||||||
|  |  | ||||||
| /* Start running the VM from where it left off. */ | /* Start running the VM from where it left off. */ | ||||||
| int gst_continue(Gst *vm) { | int gst_continue(Gst *vm) { | ||||||
| @@ -73,8 +71,8 @@ int gst_continue(Gst *vm) { | |||||||
|             continue; |             continue; | ||||||
|  |  | ||||||
|         case GST_OP_I16: /* Load Small Integer */ |         case GST_OP_I16: /* Load Small Integer */ | ||||||
|             temp.type = GST_NUMBER; |             temp.type = GST_INTEGER; | ||||||
|             temp.data.number = ((int16_t *)(pc))[2]; |             temp.data.integer = ((int16_t *)(pc))[2]; | ||||||
|             stack[pc[1]] = temp; |             stack[pc[1]] = temp; | ||||||
|             pc += 3; |             pc += 3; | ||||||
|             continue; |             continue; | ||||||
| @@ -132,15 +130,22 @@ int gst_continue(Gst *vm) { | |||||||
|             continue; |             continue; | ||||||
|  |  | ||||||
|         case GST_OP_I32: /* Load 32 bit integer */ |         case GST_OP_I32: /* Load 32 bit integer */ | ||||||
|             temp.type = GST_NUMBER; |             temp.type = GST_INTEGER; | ||||||
|             temp.data.number = *((int32_t *)(pc + 2)); |             temp.data.integer = *((int32_t *)(pc + 2)); | ||||||
|             stack[pc[1]] = temp; |             stack[pc[1]] = temp; | ||||||
|             pc += 4; |             pc += 4; | ||||||
|             continue; |             continue; | ||||||
|  |  | ||||||
|  |         case GST_OP_I64: /* Load 64 bit integer */ | ||||||
|  |             temp.type = GST_INTEGER; | ||||||
|  |             temp.data.integer = (GstInteger) *((int64_t *)(pc + 2)); | ||||||
|  |             stack[pc[1]] = temp; | ||||||
|  |             pc += 6; | ||||||
|  |             continue; | ||||||
|  |  | ||||||
|         case GST_OP_F64: /* Load 64 bit float */ |         case GST_OP_F64: /* Load 64 bit float */ | ||||||
|             temp.type = GST_NUMBER; |             temp.type = GST_REAL; | ||||||
|             temp.data.number = (GstNumber) *((double *)(pc + 2)); |             temp.data.real = (GstReal) *((double *)(pc + 2)); | ||||||
|             stack[pc[1]] = temp; |             stack[pc[1]] = temp; | ||||||
|             pc += 6; |             pc += 6; | ||||||
|             continue; |             continue; | ||||||
| @@ -310,81 +315,6 @@ int gst_continue(Gst *vm) { | |||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
|  |  | ||||||
|         /* Faster implementations of standard functions |  | ||||||
|          * These opcodes are nto strictlyre required and can |  | ||||||
|          * be reimplemented with stanard library functions */ |  | ||||||
|  |  | ||||||
|         #define OP_BINARY_MATH(op) \ |  | ||||||
|             v1 = stack[pc[2]]; \ |  | ||||||
|             v2 = stack[pc[3]]; \ |  | ||||||
|             gst_assert(vm, v1.type == GST_NUMBER, GST_EXPECTED_NUMBER_LOP); \ |  | ||||||
|             gst_assert(vm, v2.type == GST_NUMBER, GST_EXPECTED_NUMBER_ROP); \ |  | ||||||
|             temp.type = GST_NUMBER; \ |  | ||||||
|             temp.data.number = v1.data.number op v2.data.number; \ |  | ||||||
|             stack[pc[1]] = temp; \ |  | ||||||
|             pc += 4; \ |  | ||||||
|             continue; |  | ||||||
|  |  | ||||||
|         case GST_OP_ADD: /* Addition */ |  | ||||||
|             OP_BINARY_MATH(+) |  | ||||||
|  |  | ||||||
|         case GST_OP_SUB: /* Subtraction */ |  | ||||||
|             OP_BINARY_MATH(-) |  | ||||||
|  |  | ||||||
|         case GST_OP_MUL: /* Multiplication */ |  | ||||||
|             OP_BINARY_MATH(*) |  | ||||||
|  |  | ||||||
|         case GST_OP_DIV: /* Division */ |  | ||||||
|             OP_BINARY_MATH(/) |  | ||||||
|  |  | ||||||
|         #undef OP_BINARY_MATH |  | ||||||
|  |  | ||||||
|         case GST_OP_NOT: /* Boolean unary (Boolean not) */ |  | ||||||
|             temp.type = GST_BOOLEAN; |  | ||||||
|             temp.data.boolean = !gst_truthy(stack[pc[2]]); |  | ||||||
|             stack[pc[1]] = temp; |  | ||||||
|             pc += 3; |  | ||||||
|             continue; |  | ||||||
|  |  | ||||||
|         case GST_OP_NEG: /* Unary negation */ |  | ||||||
|             v1 = stack[pc[2]]; |  | ||||||
|             gst_assert(vm, v1.type == GST_NUMBER, GST_EXPECTED_NUMBER_LOP); |  | ||||||
|             temp.type = GST_NUMBER; |  | ||||||
|             temp.data.number = -v1.data.number; |  | ||||||
|             stack[pc[1]] = temp; |  | ||||||
|             pc += 3; |  | ||||||
|             continue; |  | ||||||
|  |  | ||||||
|         case GST_OP_INV: /* Unary multiplicative inverse */ |  | ||||||
|             v1 = stack[pc[2]]; |  | ||||||
|             gst_assert(vm, v1.type == GST_NUMBER, GST_EXPECTED_NUMBER_LOP); |  | ||||||
|             temp.type = GST_NUMBER; |  | ||||||
|             temp.data.number = 1 / v1.data.number; |  | ||||||
|             stack[pc[1]] = temp; |  | ||||||
|             pc += 3; |  | ||||||
|             continue; |  | ||||||
|  |  | ||||||
|         case GST_OP_EQL: /* Equality */ |  | ||||||
|             temp.type = GST_BOOLEAN; |  | ||||||
|             temp.data.boolean = gst_equals(stack[pc[2]], stack[pc[3]]); |  | ||||||
|             stack[pc[1]] = temp; |  | ||||||
|             pc += 4; |  | ||||||
|             continue; |  | ||||||
|  |  | ||||||
|         case GST_OP_LTN: /* Less Than */ |  | ||||||
|             temp.type = GST_BOOLEAN; |  | ||||||
|             temp.data.boolean = (gst_compare(stack[pc[2]], stack[pc[3]]) == -1); |  | ||||||
|             stack[pc[1]] = temp; |  | ||||||
|             pc += 4; |  | ||||||
|             continue; |  | ||||||
|  |  | ||||||
|         case GST_OP_LTE: /* Less Than or Equal to */ |  | ||||||
|             temp.type = GST_BOOLEAN; |  | ||||||
|             temp.data.boolean = (gst_compare(stack[pc[2]], stack[pc[3]]) != 1); |  | ||||||
|             stack[pc[1]] = temp; |  | ||||||
|             pc += 4; |  | ||||||
|             continue; |  | ||||||
|  |  | ||||||
|         case GST_OP_ARR: /* Array literal */ |         case GST_OP_ARR: /* Array literal */ | ||||||
|             { |             { | ||||||
|                 uint32_t i; |                 uint32_t i; | ||||||
|   | |||||||
| @@ -83,10 +83,10 @@ | |||||||
|  |  | ||||||
| /* Macros for referencing a stack frame given a stack */ | /* Macros for referencing a stack frame given a stack */ | ||||||
| #define gst_frame_callee(s)     (*(s - 1)) | #define gst_frame_callee(s)     (*(s - 1)) | ||||||
| #define gst_frame_size(s)       ((s - 2)->data.hws[0]) | #define gst_frame_size(s)       ((s - 2)->data.words[0]) | ||||||
| #define gst_frame_prevsize(s)   ((s - 2)->data.hws[1]) | #define gst_frame_prevsize(s)   ((s - 2)->data.words[1]) | ||||||
| #define gst_frame_args(s)       ((s - 2)->data.hws[2]) | #define gst_frame_args(s)       ((s - 2)->data.words[2]) | ||||||
| #define gst_frame_ret(s)        ((s - 2)->data.hws[3]) | #define gst_frame_ret(s)        ((s - 2)->data.words[3]) | ||||||
| #define gst_frame_pc(s)         ((s - 3)->data.u16p) | #define gst_frame_pc(s)         ((s - 3)->data.u16p) | ||||||
| #define gst_frame_env(s)        ((s - 4)->data.env) | #define gst_frame_env(s)        ((s - 4)->data.env) | ||||||
|  |  | ||||||
| @@ -111,13 +111,11 @@ | |||||||
| #define GST_OUT_OF_MEMORY do { printf("out of memory\n"); exit(1); } while (0) | #define GST_OUT_OF_MEMORY do { printf("out of memory\n"); exit(1); } while (0) | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| /* Max search depth for classes. */ |  | ||||||
| #define GST_MAX_SEARCH_DEPTH 128 |  | ||||||
|  |  | ||||||
| /* Various types */ | /* Various types */ | ||||||
| typedef enum GstType { | typedef enum GstType { | ||||||
|     GST_NIL = 0, |     GST_NIL = 0, | ||||||
|     GST_NUMBER, |     GST_REAL, | ||||||
|  |     GST_INTEGER, | ||||||
|     GST_BOOLEAN, |     GST_BOOLEAN, | ||||||
|     GST_STRING, |     GST_STRING, | ||||||
|     GST_ARRAY, |     GST_ARRAY, | ||||||
| @@ -140,8 +138,9 @@ typedef struct Gst Gst; | |||||||
| typedef struct GstValue GstValue; | typedef struct GstValue GstValue; | ||||||
|  |  | ||||||
| /* All of the gst types */ | /* All of the gst types */ | ||||||
| typedef double GstNumber; | typedef double GstReal; | ||||||
| typedef uint8_t GstBoolean; | typedef int64_t GstInteger; | ||||||
|  | typedef int GstBoolean; | ||||||
| typedef struct GstFunction GstFunction; | typedef struct GstFunction GstFunction; | ||||||
| typedef struct GstArray GstArray; | typedef struct GstArray GstArray; | ||||||
| typedef struct GstBuffer GstBuffer; | typedef struct GstBuffer GstBuffer; | ||||||
| @@ -167,7 +166,8 @@ struct GstModuleItem { | |||||||
| /* Union datatype */ | /* Union datatype */ | ||||||
| union GstValueUnion { | union GstValueUnion { | ||||||
|     GstBoolean boolean; |     GstBoolean boolean; | ||||||
|     GstNumber number; |     GstReal real; | ||||||
|  |     GstInteger integer; | ||||||
|     GstArray *array; |     GstArray *array; | ||||||
|     GstBuffer *buffer; |     GstBuffer *buffer; | ||||||
|     GstObject *object; |     GstObject *object; | ||||||
| @@ -179,12 +179,13 @@ union GstValueUnion { | |||||||
|     GstFuncDef *def; |     GstFuncDef *def; | ||||||
|     const GstValue *st; |     const GstValue *st; | ||||||
|     const uint8_t *string; |     const uint8_t *string; | ||||||
|     const char *cstring; /* Alias for ease of use from c */ |  | ||||||
|     /* Indirectly used union members */ |     /* Indirectly used union members */ | ||||||
|     uint16_t *u16p; |     uint16_t *u16p; | ||||||
|     uint16_t hws[4]; |     uint32_t dwords[2]; | ||||||
|  |     uint16_t words[4]; | ||||||
|     uint8_t bytes[8]; |     uint8_t bytes[8]; | ||||||
|     void *pointer; |     void *pointer; | ||||||
|  |     const char *cstring; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| /* The general gst value type. Contains a large union and | /* The general gst value type. Contains a large union and | ||||||
| @@ -296,29 +297,20 @@ struct Gst { | |||||||
|  |  | ||||||
| /* Bytecode */ | /* Bytecode */ | ||||||
| enum GstOpCode { | enum GstOpCode { | ||||||
|     GST_OP_ADD = 0, /* Addition */ |  | ||||||
|     GST_OP_SUB,     /* Subtraction */ |  | ||||||
|     GST_OP_MUL,     /* Multiplication */ |  | ||||||
|     GST_OP_DIV,     /* Division */ |  | ||||||
|     GST_OP_NOT,     /* Boolean invert */ |  | ||||||
|     GST_OP_NEG,     /* Unary negation */  |  | ||||||
|     GST_OP_INV,     /* Unary multiplicative inverse */ |  | ||||||
|     GST_OP_FLS,     /* Load false */ |     GST_OP_FLS,     /* Load false */ | ||||||
|     GST_OP_TRU,     /* Load true */ |     GST_OP_TRU,     /* Load true */ | ||||||
|     GST_OP_NIL,     /* Load nil */ |     GST_OP_NIL,     /* Load nil */ | ||||||
|     GST_OP_I16,     /* Load 16 bit signed integer */ |  | ||||||
|     GST_OP_UPV,     /* Load upvalue */ |     GST_OP_UPV,     /* Load upvalue */ | ||||||
|     GST_OP_JIF,     /* Jump if */ |     GST_OP_JIF,     /* Jump if */ | ||||||
|     GST_OP_JMP,     /* Jump */ |     GST_OP_JMP,     /* Jump */ | ||||||
|     GST_OP_SUV,     /* Set upvalue */ |     GST_OP_SUV,     /* Set upvalue */ | ||||||
|     GST_OP_CST,     /* Load constant */ |     GST_OP_CST,     /* Load constant */ | ||||||
|  |     GST_OP_I16,     /* Load 16 bit signed integer */ | ||||||
|     GST_OP_I32,     /* Load 32 bit signed integer */ |     GST_OP_I32,     /* Load 32 bit signed integer */ | ||||||
|  |     GST_OP_I64,     /* Load 64 bit signed integer */ | ||||||
|     GST_OP_F64,     /* Load 64 bit IEEE double */ |     GST_OP_F64,     /* Load 64 bit IEEE double */ | ||||||
|     GST_OP_MOV,     /* Move value */ |     GST_OP_MOV,     /* Move value */ | ||||||
|     GST_OP_CLN,     /* Create a closure */ |     GST_OP_CLN,     /* Create a closure */ | ||||||
|     GST_OP_EQL,     /* Check equality */ |  | ||||||
|     GST_OP_LTN,     /* Check less than */ |  | ||||||
|     GST_OP_LTE,     /* Check less than or equal to */ |  | ||||||
|     GST_OP_ARR,     /* Create array */ |     GST_OP_ARR,     /* Create array */ | ||||||
|     GST_OP_DIC,     /* Create object */ |     GST_OP_DIC,     /* Create object */ | ||||||
|     GST_OP_TUP,     /* Create tuple */ |     GST_OP_TUP,     /* Create tuple */ | ||||||
| @@ -430,7 +422,7 @@ const char *gst_get(GstValue ds, GstValue key, GstValue *out); | |||||||
| const char *gst_set(Gst *vm, GstValue ds, GstValue key, GstValue value); | const char *gst_set(Gst *vm, GstValue ds, GstValue key, GstValue value); | ||||||
| const uint8_t *gst_to_string(Gst *vm, GstValue x); | const uint8_t *gst_to_string(Gst *vm, GstValue x); | ||||||
| uint32_t gst_hash(GstValue x); | uint32_t gst_hash(GstValue x); | ||||||
| int gst_length(Gst *vm, GstValue x, GstValue *len); | GstInteger gst_length(Gst *vm, GstValue x); | ||||||
|  |  | ||||||
| /****/ | /****/ | ||||||
| /* Serialization */ | /* Serialization */ | ||||||
| @@ -464,6 +456,7 @@ int gst_length(Gst *vm, GstValue x, GstValue *len); | |||||||
|  * Byte 215: LUdata  - [value meta][u32 length]*[u8... bytes] |  * Byte 215: LUdata  - [value meta][u32 length]*[u8... bytes] | ||||||
|  * Byte 216: CFunc   - [u32 length]*[u8... idstring] |  * Byte 216: CFunc   - [u32 length]*[u8... idstring] | ||||||
|  * Byte 217: Ref     - [u32 id] |  * Byte 217: Ref     - [u32 id] | ||||||
|  |  * Byte 218: Integer - [i64 value] | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| const char *gst_deserialize( | const char *gst_deserialize( | ||||||
| @@ -517,7 +510,8 @@ GstValue gst_register_get(Gst *vm, const char *name); | |||||||
|  |  | ||||||
| /* Wrap data in GstValue */ | /* Wrap data in GstValue */ | ||||||
| GstValue gst_wrap_nil(); | GstValue gst_wrap_nil(); | ||||||
| GstValue gst_wrap_number(GstNumber x); | GstValue gst_wrap_real(GstReal x); | ||||||
|  | GstValue gst_wrap_integer(GstInteger x); | ||||||
| GstValue gst_wrap_boolean(int x); | GstValue gst_wrap_boolean(int x); | ||||||
| GstValue gst_wrap_string(const uint8_t *x); | GstValue gst_wrap_string(const uint8_t *x); | ||||||
| GstValue gst_wrap_array(GstArray *x); | GstValue gst_wrap_array(GstArray *x); | ||||||
| @@ -534,7 +528,8 @@ GstValue gst_wrap_funcdef(GstFuncDef *x); | |||||||
|  |  | ||||||
| /* Check data from arguments */ | /* Check data from arguments */ | ||||||
| int gst_check_nil(Gst *vm, uint32_t i); | int gst_check_nil(Gst *vm, uint32_t i); | ||||||
| int gst_check_number(Gst *vm, uint32_t i, GstNumber (*x)); | int gst_check_real(Gst *vm, uint32_t i, GstReal (*x)); | ||||||
|  | int gst_check_integer(Gst *vm, uint32_t i, GstInteger (*x)); | ||||||
| int gst_check_boolean(Gst *vm, uint32_t i, int (*x)); | int gst_check_boolean(Gst *vm, uint32_t i, int (*x)); | ||||||
| int gst_check_string(Gst *vm, uint32_t i, const uint8_t *(*x)); | int gst_check_string(Gst *vm, uint32_t i, const uint8_t *(*x)); | ||||||
| int gst_check_array(Gst *vm, uint32_t i, GstArray *(*x)); | int gst_check_array(Gst *vm, uint32_t i, GstArray *(*x)); | ||||||
| @@ -557,7 +552,9 @@ int gst_hashtable_view(GstValue tab, const GstValue **data, uint32_t *cap); | |||||||
| /* Misc */ | /* Misc */ | ||||||
| /****/ | /****/ | ||||||
|  |  | ||||||
| int32_t gst_to_index(GstNumber raw, int64_t len); | GstReal gst_integer_to_real(GstInteger x); | ||||||
| int32_t gst_to_endrange(GstNumber raw, int64_t len); | GstInteger gst_real_to_integer(GstReal x); | ||||||
|  | GstInteger gst_startrange(GstInteger raw, uint32_t len); | ||||||
|  | GstInteger gst_endrange(GstInteger raw, uint32_t len); | ||||||
|  |  | ||||||
| #endif // GST_H_defined | #endif // GST_H_defined | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Calvin Rose
					Calvin Rose