More integer_type conversions

This commit is contained in:
justin 2016-03-15 10:15:47 -04:00
parent d0efac2035
commit 33b56d24ea
2 changed files with 83 additions and 32 deletions

View file

@ -208,6 +208,8 @@ typedef long tag_type;
* 0x01 - integer (in progress) * 0x01 - integer (in progress)
* 0x10 - char * 0x10 - char
*/ */
// TODO: does this break negative numbers (IE, overwrite sign bit in 2's comp?)? may need a more sophisticated scheme to handle 31-bit numbers. also, ideally want to use 63 bits on a 64-bit system
#define obj_is_int(x) ((unsigned long)(x) & (unsigned long)1) #define obj_is_int(x) ((unsigned long)(x) & (unsigned long)1)
#define obj_obj2int(x) ((int)(x)>>1) #define obj_obj2int(x) ((int)(x)>>1)
#define obj_int2obj(c) ((void *)((((int)c)<<1) | 1)) #define obj_int2obj(c) ((void *)((((int)c)<<1) | 1))

113
runtime.c
View file

@ -949,17 +949,23 @@ object Cyc_vector_set(void *data, object v, object k, object obj) {
} }
object Cyc_vector_ref(void *data, object v, object k) { object Cyc_vector_ref(void *data, object v, object k) {
int idx;
if (nullp(v) || is_value_type(v) || ((list)v)->tag != vector_tag) { if (nullp(v) || is_value_type(v) || ((list)v)->tag != vector_tag) {
Cyc_rt_raise_msg(data, "vector-ref - invalid parameter, expected vector\n"); Cyc_rt_raise_msg(data, "vector-ref - invalid parameter, expected vector\n");
} }
if (nullp(k) || is_value_type(k) || ((list)k)->tag != integer_tag) { if ((!obj_is_int(k)) && (nullp(k) || is_value_type(k) || ((list)k)->tag != integer_tag)) {
Cyc_rt_raise_msg(data, "vector-ref - invalid parameter, expected integer\n"); Cyc_rt_raise_msg(data, "vector-ref - invalid parameter, expected integer\n");
} }
if (integer_value(k) < 0 || integer_value(k) >= ((vector)v)->num_elt) { if (obj_is_int(k)) {
Cyc_rt_raise2(data, "vector-ref - invalid index", k); idx = obj_obj2int(k);
} else {
idx = integer_value(k);
}
if (idx < 0 || idx >= ((vector)v)->num_elt) {
Cyc_rt_raise2(data, "vector-ref - invalid index", obj_int2obj(idx));
} }
return ((vector)v)->elts[((integer_type *)k)->value]; return ((vector)v)->elts[idx];
} }
integer_type Cyc_vector_length(void *data, object v) { integer_type Cyc_vector_length(void *data, object v) {
@ -981,10 +987,30 @@ integer_type Cyc_length(void *data, object l){
return len; return len;
} }
object Cyc_vector_length2(void *data, object v) {
if (!nullp(v) && !is_value_type(v) && ((list)v)->tag == vector_tag) {
return obj_int2obj(((vector)v)->num_elt);
}
Cyc_rt_raise_msg(data, "vector-length - invalid parameter, expected vector\n"); }
object Cyc_length2(void *data, object l){
int len = 0;
while(!nullp(l)){
if (is_value_type(l) || ((list)l)->tag != cons_tag){
Cyc_rt_raise_msg(data, "length - invalid parameter, expected list\n");
}
l = cdr(l);
len++;
}
return obj_int2obj(len);
}
object Cyc_number2string(void *data, object cont, object n) { object Cyc_number2string(void *data, object cont, object n) {
char buffer[1024]; char buffer[1024];
Cyc_check_num(data, n); Cyc_check_num(data, n);
if (type_of(n) == integer_tag) { if (obj_is_int(n)) {
snprintf(buffer, 1024, "%d", obj_obj2int(n));
}else if (type_of(n) == integer_tag) {
snprintf(buffer, 1024, "%d", ((integer_type *)n)->value); snprintf(buffer, 1024, "%d", ((integer_type *)n)->value);
} else if (type_of(n) == double_tag) { } else if (type_of(n) == double_tag) {
snprintf(buffer, 1024, "%f", ((double_type *)n)->value); snprintf(buffer, 1024, "%f", ((double_type *)n)->value);
@ -1015,12 +1041,12 @@ object Cyc_string2symbol(void *data, object str) {
object Cyc_list2string(void *data, object cont, object lst){ object Cyc_list2string(void *data, object cont, object lst){
char *buf; char *buf;
int i = 0; int i = 0;
integer_type len; object len;
Cyc_check_cons_or_nil(data, lst); Cyc_check_cons_or_nil(data, lst);
len = Cyc_length(data, lst); // Inefficient, walks whole list len = Cyc_length2(data, lst); // Inefficient, walks whole list
buf = alloca(sizeof(char) * (len.value + 1)); buf = alloca(sizeof(char) * (obj_obj2int(len) + 1));
while(!nullp(lst)){ while(!nullp(lst)){
buf[i++] = obj_obj2char(car(lst)); buf[i++] = obj_obj2char(car(lst));
lst = cdr(lst); lst = cdr(lst);
@ -1032,6 +1058,7 @@ object Cyc_list2string(void *data, object cont, object lst){
return_closcall1(data, cont, &str);} return_closcall1(data, cont, &str);}
} }
// TODO: need new versions of string->number that handle int value types
common_type Cyc_string2number2(void *data, int argc, object str, ...) common_type Cyc_string2number2(void *data, int argc, object str, ...)
{ {
object base = nil; object base = nil;
@ -1138,6 +1165,13 @@ integer_type Cyc_string_cmp(void *data, object str1, object str2) {
} }
} }
object Cyc_string_cmp2(void *data, object str1, object str2) {
Cyc_check_str(data, str1);
Cyc_check_str(data, str2);
return obj_int2obj( strcmp(((string_type *)str1)->str,
((string_type *)str2)->str) );
}
#define Cyc_string_append_va_list(data, argc) { \ #define Cyc_string_append_va_list(data, argc) { \
int i = 0, total_len = 1; \ int i = 0, total_len = 1; \
int *len = alloca(sizeof(int) * argc); \ int *len = alloca(sizeof(int) * argc); \
@ -1185,6 +1219,11 @@ integer_type Cyc_string_length(void *data, object str) {
{ make_int(len, strlen(string_str(str))); { make_int(len, strlen(string_str(str)));
return len; }} return len; }}
object Cyc_string_length2(void *data, object str) {
Cyc_check_obj(data, string_tag, str);
Cyc_check_str(data, str);
return obj_int2obj(strlen(string_str(str))); }
object Cyc_string_set(void *data, object str, object k, object chr) { object Cyc_string_set(void *data, object str, object k, object chr) {
char *raw; char *raw;
int idx, len; int idx, len;
@ -1197,7 +1236,7 @@ object Cyc_string_set(void *data, object str, object k, object chr) {
} }
raw = string_str(str); raw = string_str(str);
idx = integer_value(k), idx = obj_is_int(k) ? obj_obj2int(k) : integer_value(k),
len = strlen(raw); len = strlen(raw);
Cyc_check_bounds(data, "string-set!", len, idx); Cyc_check_bounds(data, "string-set!", len, idx);
@ -1213,7 +1252,7 @@ object Cyc_string_ref(void *data, object str, object k) {
Cyc_check_int(data, k); Cyc_check_int(data, k);
raw = string_str(str); raw = string_str(str);
idx = integer_value(k), idx = obj_is_int(k) ? obj_obj2int(k) : integer_value(k),
len = strlen(raw); len = strlen(raw);
if (idx < 0 || idx >= len) { if (idx < 0 || idx >= len) {
@ -1232,8 +1271,8 @@ object Cyc_substring(void *data, object cont, object str, object start, object e
Cyc_check_int(data, end); Cyc_check_int(data, end);
raw = string_str(str); raw = string_str(str);
s = integer_value(start), s = obj_is_int(start) ? obj_obj2int(start) : integer_value(start),
e = integer_value(end), e = obj_is_int(end) ? obj_obj2int(end) : integer_value(end),
len = strlen(raw); len = strlen(raw);
if (s > e) { if (s > e) {
@ -1317,7 +1356,7 @@ object Cyc_make_vector(void *data, object cont, object len, object fill) {
((vector)v)->hdr.mark = gc_color_red; ((vector)v)->hdr.mark = gc_color_red;
((vector)v)->hdr.grayed = 0; ((vector)v)->hdr.grayed = 0;
((vector)v)->tag = vector_tag; ((vector)v)->tag = vector_tag;
((vector)v)->num_elt = ((integer_type *)len)->value; ((vector)v)->num_elt = obj_is_int(len) ? obj_obj2int(len) : ((integer_type *)len)->value;
((vector)v)->elts = ((vector)v)->elts =
(((vector)v)->num_elt > 0) ? (((vector)v)->num_elt > 0) ?
(object *)alloca(sizeof(object) * ((vector)v)->num_elt) : (object *)alloca(sizeof(object) * ((vector)v)->num_elt) :
@ -1330,17 +1369,17 @@ object Cyc_make_vector(void *data, object cont, object len, object fill) {
object Cyc_list2vector(void *data, object cont, object l) { object Cyc_list2vector(void *data, object cont, object l) {
object v = nil; object v = nil;
integer_type len; object len;
object lst = l; object lst = l;
int i = 0; int i = 0;
Cyc_check_cons_or_nil(data, l); Cyc_check_cons_or_nil(data, l);
len = Cyc_length(data, l); len = Cyc_length2(data, l);
v = alloca(sizeof(vector_type)); v = alloca(sizeof(vector_type));
((vector)v)->hdr.mark = gc_color_red; ((vector)v)->hdr.mark = gc_color_red;
((vector)v)->hdr.grayed = 0; ((vector)v)->hdr.grayed = 0;
((vector)v)->tag = vector_tag; ((vector)v)->tag = vector_tag;
((vector)v)->num_elt = len.value; ((vector)v)->num_elt = obj_obj2int(len);
((vector)v)->elts = ((vector)v)->elts =
(((vector)v)->num_elt > 0) ? (((vector)v)->num_elt > 0) ?
(object *)alloca(sizeof(object) * ((vector)v)->num_elt) : (object *)alloca(sizeof(object) * ((vector)v)->num_elt) :
@ -1362,19 +1401,27 @@ integer_type Cyc_system(object cmd) {
} }
} }
object Cyc_system2(object cmd) {
if (nullp(cmd) || is_value_type(cmd) || type_of(cmd) != string_tag) {
return obj_int2obj(-1);
}
return obj_int2obj(system(((string_type *)cmd)->str));
}
integer_type Cyc_char2integer(object chr){ integer_type Cyc_char2integer(object chr){
make_int(n, obj_obj2char(chr)); make_int(n, obj_obj2char(chr));
return n; return n;
} }
object Cyc_char2integer2(object chr){
return obj_int2obj(obj_obj2char(chr));
}
object Cyc_integer2char(void *data, object n){ object Cyc_integer2char(void *data, object n){
int val = 0; int val = 0;
Cyc_check_int(data, n); Cyc_check_int(data, n);
if (!nullp(n)) { val = (obj_is_int(n) ? obj_obj2int(n) : integer_value(n));
val = ((integer_type *) n)->value;
}
return obj_char2obj(val); return obj_char2obj(val);
} }
@ -1392,6 +1439,7 @@ object __halt(object obj) {
return nil; return nil;
} }
// TODO: support for integer value types
#define declare_num_op(FUNC, FUNC_OP, FUNC_APPLY, OP, DIV) \ #define declare_num_op(FUNC, FUNC_OP, FUNC_APPLY, OP, DIV) \
common_type FUNC_OP(void *data, object x, object y) { \ common_type FUNC_OP(void *data, object x, object y) { \
common_type s; \ common_type s; \
@ -1981,12 +2029,12 @@ void _string_91cmp(void *data, object cont, object args) {
{ integer_type cmp = Cyc_string_cmp(data, car(args), cadr(args)); { integer_type cmp = Cyc_string_cmp(data, car(args), cadr(args));
return_closcall1(data, cont, &cmp);}} return_closcall1(data, cont, &cmp);}}
void _string_91append(void *data, object cont, object args) { void _string_91append(void *data, object cont, object args) {
integer_type argc = Cyc_length(data, args); object argc = Cyc_length2(data, args);
dispatch(data, argc.value, (function_type)dispatch_string_91append, cont, cont, args); } dispatch(data, obj_obj2int(argc), (function_type)dispatch_string_91append, cont, cont, args); }
void _make_91vector(void *data, object cont, object args) { void _make_91vector(void *data, object cont, object args) {
Cyc_check_num_args(data, "make-vector", 1, args); Cyc_check_num_args(data, "make-vector", 1, args);
{ integer_type argc = Cyc_length(data, args); { object argc = Cyc_length2(data, args);
if (argc.value >= 2) { if (obj_obj2int(argc) >= 2) {
Cyc_make_vector(data, cont, car(args), cadr(args));} Cyc_make_vector(data, cont, car(args), cadr(args));}
else { else {
Cyc_make_vector(data, cont, car(args), boolean_f);}}} Cyc_make_vector(data, cont, car(args), boolean_f);}}}
@ -2053,12 +2101,12 @@ void _Cyc_91write_91char(void *data, object cont, object args) {
return_closcall1(data, cont, Cyc_write_char(data, car(args), cadr(args)));} return_closcall1(data, cont, Cyc_write_char(data, car(args), cadr(args)));}
void _Cyc_91write(void *data, object cont, object args) { void _Cyc_91write(void *data, object cont, object args) {
Cyc_check_num_args(data, "write", 1, args); Cyc_check_num_args(data, "write", 1, args);
{ integer_type argc = Cyc_length(data, args); { object argc = Cyc_length2(data, args);
dispatch(data, argc.value, (function_type)dispatch_write_va, cont, cont, args); }} dispatch(data, obj_obj2int(argc), (function_type)dispatch_write_va, cont, cont, args); }}
void _display(void *data, object cont, object args) { void _display(void *data, object cont, object args) {
Cyc_check_num_args(data, "display", 1, args); Cyc_check_num_args(data, "display", 1, args);
{ integer_type argc = Cyc_length(data, args); { object argc = Cyc_length2(data, args);
dispatch(data, argc.value, (function_type)dispatch_display_va, cont, cont, args); }} dispatch(data, obj_obj2int(argc), (function_type)dispatch_display_va, cont, cont, args); }}
void _call_95cc(void *data, object cont, object args){ void _call_95cc(void *data, object cont, object args){
Cyc_check_num_args(data, "call/cc", 1, args); Cyc_check_num_args(data, "call/cc", 1, args);
if (eq(boolean_f, Cyc_is_procedure(data, car(args)))) { if (eq(boolean_f, Cyc_is_procedure(data, car(args)))) {
@ -2074,6 +2122,7 @@ void _call_95cc(void *data, object cont, object args){
*/ */
object apply(void *data, object cont, object func, object args){ object apply(void *data, object cont, object func, object args){
common_type buf; common_type buf;
object count;
//printf("DEBUG apply: "); //printf("DEBUG apply: ");
//Cyc_display(args); //Cyc_display(args);
@ -2097,10 +2146,10 @@ object apply(void *data, object cont, object func, object args){
case closure3_tag: case closure3_tag:
case closure4_tag: case closure4_tag:
case closureN_tag: case closureN_tag:
buf.integer_t = Cyc_length(data, args); count = Cyc_length2(data, args);
// TODO: validate number of args provided: // TODO: validate number of args provided:
Cyc_check_num_args(data, "<procedure>", ((closure)func)->num_args, args); // TODO: could be more efficient, eg: cyc_length(args) is called twice. Cyc_check_num_args(data, "<procedure>", ((closure)func)->num_args, args); // TODO: could be more efficient, eg: cyc_length(args) is called twice.
dispatch(data, buf.integer_t.value, ((closure)func)->fn, func, cont, args); dispatch(data, obj_obj2int(count), ((closure)func)->fn, func, cont, args);
break; break;
case cons_tag: case cons_tag:
@ -2866,8 +2915,8 @@ object Cyc_thread_sleep(void *data, object timeout)
{ {
struct timespec tim; struct timespec tim;
long value; long value;
Cyc_check_num(data, timeout); Cyc_check_int(data, timeout);
value = ((integer_type *)timeout)->value; value = (obj_is_int(timeout) ? obj_obj2int(timeout) : integer_value(timeout));
tim.tv_sec = value / 1000; tim.tv_sec = value / 1000;
tim.tv_nsec = (value % 1000) * NANOSECONDS_PER_MILLISECOND; tim.tv_nsec = (value % 1000) * NANOSECONDS_PER_MILLISECOND;
nanosleep(&tim, NULL); nanosleep(&tim, NULL);