Object os_listdir() { Object list = list_new(10); Object path = arg_take_str_obj("listdir"); #ifdef _WIN32 WIN32_FIND_DATA Find_file_data; Object _path = obj_add(path, string_new("\\*.*")); HANDLE h_find = FindFirstFile(GET_STR(_path), &Find_file_data); if (h_find == INVALID_HANDLE_VALUE) { tm_raise("%s is not a directory", path); } do { if (strcmp(Find_file_data.cFileName, "..")==0 || strcmp(Find_file_data.cFileName, ".") == 0) { continue; } if (Find_file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { // do nothing. } Object file = string_new(Find_file_data.cFileName); obj_append(list, file); } while (FindNextFile(h_find, &Find_file_data)); FindClose(h_find); #else tm_raise("listdir not implemented in posix."); #endif return list; }
TmFrame* push_frame(Object fnc) { /* make extra space for self in method call */ Object *top = tm->frame->top + 2; tm->frame ++ ; TmFrame* f = tm->frame; /* check oprand stack */ if (top >= tm->stack + STACK_SIZE) { pop_frame(); tm_raise("tm_eval: stack overflow"); } /* check frame stack*/ if (tm->frame >= tm->frames + FRAMES_COUNT-1) { pop_frame(); tm_raise("tm_eval: frame overflow"); } f->pc = GET_FUNCTION(fnc)->code; f->locals = top; f->maxlocals = get_function_max_locals(GET_FUNCTION(fnc)); f->stack = f->locals + f->maxlocals; f->top = f->stack; f->fnc = fnc; // clear local variables int i;for(i = 0; i < f->maxlocals; i++) { f->locals[i] = NONE_OBJECT; } *(f->top) = NONE_OBJECT; f->jmp = NULL; return f; }
long _get_file_rest_len( FILE* fp){ if( fp == NULL ){ tm_raise("stream_read: can not open stream"); } long cur = ftell(fp); fseek(fp, 0, SEEK_END); long file_size = ftell(fp) - cur; fseek(fp, cur, SEEK_SET); if( file_size > MAX_FILE_SIZE ){ tm_raise("stream_read: file too large"); } return file_size; }
void tm_set( tm_obj self, tm_obj k, tm_obj v){ switch( self.type ){ case TM_LST: { if( TM_NUM != k.type){ tm_raise("tm_set(), expect a number but see @", _tm_type(k)); } int n = get_num(k); list_set( get_list(self), n, v); }return; case TM_DCT: dict_set( get_dict(self), k, v);return; } tm_raise(" tm_set: @[@] = @", self, k, v ); }
tm_obj tm_mod( tm_obj a, tm_obj b){ if( a.type == b.type && a.type == TM_NUM){ return number_new((long)get_num(a) % (long)get_num(b) ); } tm_raise("tm_mod: can not mod @ and @", a,b ); return obj_none; }
tm_obj tm_div( tm_obj a, tm_obj b){ if( a.type == b.type && a.type == TM_NUM){ return number_new( get_num(a) / get_num(b) ); } tm_raise("tm_div: can not div @ and @", a,b ); return obj_none; }
int tm_eq(tm_obj a, tm_obj b){ if( a.type != b.type ) return 0; switch( a.type ){ case TM_NUM: return get_num(a) == get_num(b); case TM_STR: { char* sa = get_str(a); char* sb = get_str(b); return sa == sb || ( get_str_len(a) == get_str_len(b) && strncmp(sa, sb, get_str_len(a)) == 0 ); } case TM_LST: { if( get_list(a) == get_list(b)) return 1; int i; int len = get_list(a)->len; tm_obj* nodes1 = get_list(a)->nodes; tm_obj* nodes2 = get_list(b)->nodes; for(i = 0; i < len; i++){ if( !tm_eq(nodes1[i], nodes2[i]) ){ return 0; } } return 1; } case TM_NON:return 1; default: tm_raise("tm_eq(): not supported type %d", a.type); } return 0; }
Object obj_add(Object a, Object b) { if (TM_TYPE(a) == TM_TYPE(b)) { switch (TM_TYPE(a)) { case TYPE_NUM: GET_NUM(a) += GET_NUM(b); return a; case TYPE_STR: { char* sa = GET_STR(a); char* sb = GET_STR(b); int la = GET_STR_LEN(a); int lb = GET_STR_LEN(b); if (la == 0) {return b; } if (lb == 0) {return a; } int len = la + lb; Object des = string_alloc(NULL, len); char*s = GET_STR(des); memcpy(s, sa, la); memcpy(s + la, sb, lb); return des; } case TYPE_LIST: { return list_add(GET_LIST(a), GET_LIST(b)); } } } tm_raise("obj_add: can not add %o and %o", (a), (b)); return NONE_OBJECT; }
int obj_equals(Object a, Object b){ if(TM_TYPE(a) != TM_TYPE(b)) return 0; switch(TM_TYPE(a)){ case TYPE_NUM:return GET_NUM(a) == GET_NUM(b); case TYPE_STR: { String* s1 = GET_STR_OBJ(a); String* s2 = GET_STR_OBJ(b); return s1->value == s2->value || (s1->len == s2->len && strncmp(s1->value, s2->value, s1->len) == 0); } case TYPE_LIST: { if(GET_LIST(a) == GET_LIST(b)) return 1; int i; int len = GET_LIST(a)->len; Object* nodes1 = GET_LIST(a)->nodes; Object* nodes2 = GET_LIST(b)->nodes; for(i = 0; i < len; i++){ if(!obj_equals(nodes1[i], nodes2[i]) ){ return 0; } } return 1; } case TYPE_NONE:return 1; case TYPE_DICT:return GET_DICT(a) == GET_DICT(b); case TYPE_FUNCTION: return GET_FUNCTION(a) == GET_FUNCTION(b); default: { const char* ltype = tm_type(a.type); const char* rtype = tm_type(b.type); tm_raise("equals(): not supported type %d:%s and %d:%s", TM_TYPE(a), ltype, TM_TYPE(b), rtype); } } return 0; }
Object obj_mul(Object a, Object b) { if (a.type == b.type && a.type == TYPE_NUM) { GET_NUM(a) *= GET_NUM(b); return a; } if (a.type == TYPE_NUM && b.type == TYPE_STR) { Object temp = a; a = b; b = temp; } if (a.type == TYPE_STR && b.type == TYPE_NUM) { int len = GET_STR_LEN(a); Object des; if (len == 0) return a; int times = (int) GET_NUM(b); if (times <= 0) return sz_to_string(""); if (times == 1) return a; des = string_alloc(NULL, len * times); char* s = GET_STR(des); int i; for (i = 0; i < times; i++) { strncpy(s, GET_STR(a), len); s += len; } return des; } tm_raise("obj_mul: can not multiply %o and %o", a, b); return NONE_OBJECT; }
tm_obj tm_add( tm_obj a, tm_obj b){ if( a.type == b.type ){ switch( a.type ){ case TM_NUM: get_num(a) += get_num(b); return a; case TM_STR: { char* sa = get_str(a); char* sb = get_str(b); int la = get_str_len(a); int lb = get_str_len(b); if( la == 0){ return b; } if( lb == 0){ return a; } int len = la + lb; tm_obj des = str_new(NULL, len); char*s = get_str(des); memcpy(s, sa, la); memcpy(s + la, sb, lb); return des; } case TM_LST: { return list_join(get_list(a), get_list(b) ); } } } tm_raise("tm_add: can not add %t and %t", (a),(b)); return obj_none; }
Object obj_get(Object self, Object k) { Object v; switch (TM_TYPE(self)) { case TYPE_STR: { DictNode* node; if (TM_TYPE(k) == TYPE_NUM) { double d = GET_NUM(k); int n = d; if (n < 0) { n += GET_STR_LEN(self); } if (n >= GET_STR_LEN(self) || n < 0) tm_raise("String_get: index overflow ,len=%d,index=%d, str=%o", GET_STR_LEN(self), n, self); return string_chr(0xff & GET_STR(self)[n]); } else if ((node = dict_get_node(GET_DICT(tm->str_proto), k)) != NULL) { return method_new(node->val, self); } break; } case TYPE_LIST:{ DictNode* node; if (TM_TYPE(k) == TYPE_NUM) { return list_get(GET_LIST(self), GET_NUM(k)); } else if ((node = dict_get_node(GET_DICT(tm->list_proto), k))!=NULL) { return method_new(node->val, self); } break; } case TYPE_DICT:{ DictNode* node; node = dict_get_node(GET_DICT(self), k); if (node != NULL) { return node->val; } else if ((node = dict_get_node(GET_DICT(tm->dict_proto), k))!=NULL) { return method_new(node->val, self); } break; } case TYPE_FUNCTION: return get_func_attr(GET_FUNCTION(self), k); case TYPE_DATA: return GET_DATA(self)->get(GET_DATA(self), k); } tm_raise("keyError %o", k); return NONE_OBJECT; }
tm_obj tm_sub( tm_obj a, tm_obj b){ if( a.type == b.type ){ if( a.type == TM_NUM){ return tm_number(a.value.num - b.value.num); } } tm_raise("tm_sub: can not sub @ and @", a, b); }
tm_obj _load(char* fname){ FILE* fp = fopen(fname, "rb"); if( fp == NULL ){ tm_raise("load: can not open file \"@\"", str_new(fname, strlen(fname))); return obj_none; } long len = _get_file_rest_len(fp); if(len > MAX_FILE_SIZE ){ tm_raise("load: file too big to load, size = @", number_new(len)); return obj_none; } tm_obj text = str_new(NULL, len); char* s = get_str(text); fread(s, len, 1, fp); fclose(fp); return text; }
Object obj_neg(Object o) { if (o.type == TYPE_NUM) { GET_NUM(o) = -GET_NUM(o); return o; } tm_raise("obj_neg: can not handle %o", o); return NONE_OBJECT; }
tm_obj tm_neg(tm_obj o){ if( o.type == TM_NUM){ get_num(o) = -get_num(o); return o; } tm_raise("tm_neg: can not handle @", o); return obj_none; }
Object obj_div(Object a, Object b) { if (a.type == b.type && a.type == TYPE_NUM) { GET_NUM(a) /= GET_NUM(b); return a; } tm_raise("obj_div: can not divide %o and %o", a, b); return NONE_OBJECT; }
Object obj_mod(Object a, Object b) { if (a.type == b.type && a.type == TYPE_NUM) { return tm_number((long) GET_NUM(a) % (long) GET_NUM(b)); } else if (a.type == TYPE_STR) { Object *__mod__ = get_builtin("__mod__"); if (__mod__ == NULL) { tm_raise("__mod__ is not defined"); } else { arg_start(); arg_push(a); arg_push(b); return call_function(*__mod__); } } tm_raise("obj_mod: can not module %o and %o", a, b); return NONE_OBJECT; }
tm_obj stream_close(tm_obj params){ tm_obj fp_ = get_arg( params, 0, TM_STREAM); FILE* fp = get_stream(fp_); if( fp == NULL ){ tm_raise("stream_close: file is not open"); } fclose(fp); return obj_none; }
Object os_chdir() { const char* sz_func = "chdir"; char *path = arg_take_sz(sz_func); int r = chdir(path); if (r != 0) { tm_raise("%s: -- fatal error, can not chdir(\"%s\")", sz_func, path); } return NONE_OBJECT; }
tm_obj tm_get(tm_obj self, tm_obj k){ tm_obj v; switch( self.type){ case TM_STR:{ if( k.type == TM_NUM ){ int n = get_num(k); if (n < 0) n += get_str_len(self); if( n >= get_str_len(self) || n < 0) tm_raise("tm_get: index overflow"); //tm_printf("str = @, len = @, index = @\n", self,number_new(get_str_len(self)), k); unsigned char c = get_str(self)[n]; //printf("c = %d\n", c); return __chars__[c]; }else if( dict_iget( get_dict(str_class), k , &v) ){ return method_new(v, self); } } case TM_LST: { if( k.type == TM_NUM ){ return list_get( self.value.list, get_num(k)); }else if( dict_iget(get_dict(list_class), k, &v) ){ return method_new( v, self); } break; } case TM_DCT: if( dict_iget( get_dict(self), k, &v)){ return v; }else if(dict_iget(get_dict(dict_class), k, &v)){ return method_new( v, self); } break; case TM_FNC: /* if( k.type == TM_STR && strequals(get_str(k), "code")){ return get_func( self )->code; }*/ break; } // tm_printf_only_type("@", self); // cprintln(self); tm_raise("tm_get: keyError @, self = @ ", _tm_type(k), _tm_type(self) ); return obj_none; }
Object iter_new(Object collections) { switch(TM_TYPE(collections)) { case TYPE_LIST: return list_iter_new(collections); case TYPE_DICT: return dict_iter_new(collections); case TYPE_STR: return string_iter_new(collections); case TYPE_DATA: return collections; default: tm_raise("iter_new(): can not create a iterator of %o", collections); } return NONE_OBJECT; }
Object obj_sub(Object a, Object b) { if (a.type == b.type) { if (a.type == TYPE_NUM) { GET_NUM(a) -= GET_NUM(b); return a; } } tm_raise("obj_sub: can not substract %o and %o", a, b); return NONE_OBJECT; }
tm_obj _tm_save(char*fname, tm_obj content){ FILE* fp = fopen(fname, "wb"); if( fp == NULL ){ tm_raise("tm_save : can not save to file @" , fname ); } char* txt = get_str( content ); int len = get_str_len( content ); fwrite(txt, len, 1, fp); fclose(fp); }
Object tm_get_global(Object globals, char *key) { Object okey = string_new(key); DictNode* node = dict_get_node(GET_DICT(globals), okey); if (node == NULL) { node = dict_get_node(GET_DICT(tm->builtins), okey); if (node == NULL) { tm_raise("NameError: name %o is not defined", okey); } } return node->val; }
// func Object tm_str(Object a) Object tm_str(Object a) { char buf[100]; memset(buf, 0, sizeof(buf)); switch (TM_TYPE(a)) { case TYPE_STR: return a; case TYPE_NUM: { char s[20]; double v = GET_NUM(a); number_format(s, a); return string_new(s); } case TYPE_LIST: { Object str = string_new(""); str = string_append_char(str, '['); int i, l = LIST_LEN(a); for (i = 0; i < l; i++) { Object obj = GET_LIST(a)->nodes[i]; /* reference to self in list */ if (obj_equals(a, obj)) { str = string_append_sz(str, "[...]"); } else if (obj.type == TYPE_STR) { str = string_append_char(str, '"'); str = string_append_obj(str, obj); str = string_append_char(str, '"'); } else { str = string_append_obj(str, obj); } if (i != l - 1) { str = string_append_char(str, ','); } } str = string_append_char(str, ']'); return str; } case TYPE_DICT: sprintf(buf, "<dict at %p>", GET_DICT(a)); return string_new(buf); case TYPE_FUNCTION: function_format(buf, a); return string_new(buf); case TYPE_NONE: return sz_to_string("None"); case TYPE_DATA: return GET_DATA(a)->str(GET_DATA(a)); default: tm_raise("str: not supported type %d", a.type); } return string_alloc("", 0); }
void obj_del(Object self, Object k) { switch(TM_TYPE(self)) { case TYPE_DICT:{ dict_del(GET_DICT(self), k); break; } case TYPE_LIST:{ list_del(GET_LIST(self), k); break; } default: tm_raise("obj_del: not supported type %s", tm_type(self.type)); } }
int tm_len(Object o) { int len = -1; switch (TM_TYPE(o)) { case TYPE_STR: len = GET_STR_LEN(o); case TYPE_LIST: len = LIST_LEN(o); case TYPE_DICT: len = DICT_LEN(o); } if (len < 0) { tm_raise("tm_len: %o has no attribute len", o); } return len; }
Object os_getcwd() { const char* sz_func = "getcwd"; char buf[1025]; char* r = getcwd(buf, 1024); if (r == NULL) { char *msg; switch (errno) { case EINVAL: msg = "The size of argument is 0";break; case ERANGE: msg = "The size argument is greater than 0, but is smaller than the length of the pathname +1.";break; case EACCES: msg = "Read or search permission was denied for a component of the pathname.";break; case ENOMEM: msg = "Insufficient storage space is available.";break; } tm_raise("%s: error -- %s", sz_func, msg); } return string_new(buf); }
void obj_set(Object self, Object k, Object v) { // gc_mark_single(k); // used between gc scan // gc_mark_single(v); // only need to mark single. switch (TM_TYPE(self)) { case TYPE_LIST: { tm_assert_type(k, TYPE_NUM, "obj_set"); double d = GET_NUM(k); tm_assert_int(d, "list_set"); list_set(GET_LIST(self), (int)d, v); } return; case TYPE_DICT: dict_set0(GET_DICT(self), k, v); return; } tm_raise("obj_set: Self %o, Key %o, Val %o", self, k, v); }