#include "tlang.h" #include tobject_t* tobject_same(runtime_t* rt,tobject_t* l,tobject_t* r,bool* freeleftifzero) { tobject_t* out=NULL; tobject_type_t ltype=l->type; tobject_type_t rtype =r->type; if(ltype == tdict) { if(dict_haskey(l->data.dict,"eq")) { kvp_t* kvp=dict_getkvp(l->data.dict,"eq"); if(kvp->value->type == texternalmethod || kvp->value->type == tinternalmethod) { list_tobject_t ls; list_create(rt,&ls,0); list_add(&ls,r); out=tobject_call(rt->globals,kvp->value,&ls); out->count++; //ensure i dont get deleted tobject_freeifzero(l); out->count--; //set me back bitch *freeleftifzero = false; } else { if(r->type == tdict) { out = tobject_create(rt); out->type = tbool; out->data.boolean = l == r; } } }else { if(r->type == tdict) { out = tobject_create(rt); out->type = tbool; out->data.boolean = l == r; } } } if(ltype == tnumber && rtype == tnumber) { out = tobject_create(rt); out->type = tbool; out->data.boolean = l->data.number == r->data.number; } if(ltype == tbool && rtype == tbool) { out = tobject_create(rt); out->type = tbool; out->data.boolean = l->data.boolean == r->data.boolean; } if(ltype == tstring && rtype == tstring) { out = tobject_create(rt); out->type = tbool; out->data.boolean =string_sames(l->data.string,r->data.string); } if(ltype == tchar && rtype == tchar) { out = tobject_create(rt); out->type = tbool; out->data.boolean = l->data.chr == r->data.chr; } if(out == NULL) { out = tobject_bool(rt,false); } return out; } bool tobject_sameb(runtime_t* rt,tobject_t* l,tobject_t* r) { bool freeleftifzero=true; bool ret0=false; tobject_t* ret=tobject_same(rt,l,r,&freeleftifzero); ret0=tobject_tobool(ret); ret->count++; if(freeleftifzero) { tobject_freeifzero(l); } tobject_freeifzero(r); ret->count--; tobject_freeifzero(ret); return ret0; } tobject_t* tobject_create(runtime_t* rt) { tobject_t* obj =(tobject_t*)malloc(sizeof(tobject_t)); memset(obj,0,sizeof(tobject_t)); obj->count = 0; obj->type = tnull; obj->free = NULL; return obj; } void list_create(runtime_t* rt,list_tobject_t* ls,int count) { ls->rt = rt; ls->length = count; ls->capacity = count + 128; ls->items = (tobject_t**)malloc(sizeof(tobject_t*) * ls->capacity); int i; for(i=0;ilength;i++) { ls->items[i] = tobject_create(rt); ls->items[i]->count = 1; } } void list_set(list_tobject_t* a,int index,tobject_t* item) { if(index >= a->length) { index=a->length-1; } if(index==-1) { list_add(a,item); }else{ tobject_addref(item); // just in case someone sets a variable to itself tobject_rmref(a->items[index]); a->items[index] = item; } } int list_indexof(list_tobject_t* a,tobject_t* item) { int index = -1; int i; item->count++; for(i=0;ilength;i++) { bool res= tobject_sameb(a->rt,a->items[0],item); if(res) { index=i; break; } } item->count--; return index; } bool list_contains(list_tobject_t* a,tobject_t* item) { return list_indexof(a,item) > -1; } void list_remove(list_tobject_t* a,tobject_t* item) { int i= list_indexof(a,item); if(i>-1) list_rm(a,i); } void list_add(list_tobject_t* a,tobject_t* item) { tobject_addref(item); if(a->length + 1 > a->capacity) { a->capacity = a->length + 128; a->items=(tobject_t**)realloc(a->items,a->capacity * sizeof(tobject_t*)); } a->items[a->length++] = item; } tobject_t* list_at(list_tobject_t* a,int offset) { if(offsetlength) return a->items[offset]; return NULL; } void list_rm(list_tobject_t* a,int offset) { if(offsetlength) { tobject_rmref(a->items[offset]); int i; a->length--; for(i=offset;ilength;i++) { a->items[i] = a->items[i+1]; } } } void list_clear(list_tobject_t* a) { int i; for(i=0;ilength;i++) { tobject_rmref(a->items[i]); } a->length = 0; } void list_free(list_tobject_t* a) { list_clear(a); free(a->items); } tobject_t* tobject_create_array(runtime_t* rt,int count) { tobject_t* obj= tobject_create(rt); obj->type = tlist; list_create(rt,&obj->data.list,count); return obj; } tobject_t* tobject_basic(runtime_t* rt,tobject_type_t type) { tobject_t* o=tobject_create(rt); o->type = type; return o; } tobject_t* tobject_fromexternalmethod(runtime_t* rt,void* data,external_method_t method,texternalmethod_free_t free) { tobject_t* obj= tobject_create(rt); obj->type = texternalmethod; obj->data.external_method.data = data; obj->data.external_method.method = method; obj->free = free; obj->count=0; return obj; } int requiredArguments(list_string_t* str) { int i; for(i =0;icount;i++) { if(str->strings[i]->length > 0 && str->strings[i]->text[0] == '$') { return i; } } return str->count; } int optionalArgs(list_string_t* str,int argLen) { int i; for(i =0;icount;i++) { string_t* str0=str->strings[i]; if(str0->length > 2 && str0->text[0] == '$' && str0->text[1] == '$') { if(argLen < i) return argLen; return i; } } if(argLen < str->count) return argLen; return str->count; } tobject_t* tobject_call(scope_t* scope,tobject_t* func,list_tobject_t* args) { if(func->type == texternalmethod) { return func->data.external_method.method(scope->rt,func->data.external_method.data,args); } if(func->type == tinternalmethod) { //execute_internal_method tobject_t* res; scope_t* scope2=scope_begin(scope); list_string_t* strs=&func->data.internal_method.closure->data.closure_node.argNames; int argCountClosure = strs->count;//Body.Arguments.Count; int argCountCaller = args->length; if(argCountCaller < requiredArguments(strs)) { return tobject_basic(scope->rt,tnull); } int i = 0; for(;iitems[i]; char* t = string_dupp(strs->strings[i]); scope2->setvariable(scope2,string_trimstart(t,'$'),_obj); free(t); } if(i==argCountClosure-1) { //do tarray tobject_t* array= tobject_create_array(scope->rt,0); char* t = string_dupp(strs->strings[i]); scope2->setvariable(scope2,string_trimstart(t,'$'),array); free(t); for(;ilength;i++) { tobject_t* _obj=args->items[i]; list_add(&array->data.list,_obj); } } retarg_t _arg; _arg.isBreaking=false; _arg.isReturning=false; res=func->data.internal_method.closure->data.closure_node.node->execute(func->data.internal_method.closure->data.closure_node.node,scope2,&_arg); scope_end(scope2); return res; } return tobject_basic(scope->rt,tundef); } void tobject_addref(tobject_t* obj) { obj->count++; } void tobject_freeifzero(tobject_t* obj) { if(obj->count<=0) { if(obj->type == tdict) { dict_free(obj->data.dict); } if(obj->type == tlist) { list_free(&obj->data.list); } if(obj->type == tstring) { string_free(obj->data.string); } if(obj->type == tinternalmethod) { node_t* n = obj->data.internal_method.closure; node_free(n->data.closure_node.node); int i; for(i=0;idata.closure_node.argNames.count;i++) { string_free(n->data.closure_node.argNames.strings[i]); } free(n->data.closure_node.argNames.strings); node_free(n); tscope_rmref(obj->data.internal_method.scope); } if(obj->free != NULL) { obj->free(obj); } free(obj); } } void tobject_rmref(tobject_t* obj) { obj->count--; tobject_freeifzero(obj); } tobject_t* tobject_number(runtime_t* rt,double num) { tobject_t* o = tobject_create(rt); o->data.number = num; o->type = tnumber; return o; } tobject_t* tobject_charp(runtime_t* rt,const char* text) { string_t* s = string_create(); string_appendp(s,text); return tobject_string(rt,s); } tobject_t* tobject_string(runtime_t* rt,string_t* str) { tobject_t* o = tobject_create(rt); o->data.string = str; o->type = tstring; return o; } string_t* tobject_tostring(scope_t* sc,tobject_t* s) { if(s->type == tstring) { string_t* s2= string_dups(s->data.string); tobject_freeifzero(s); return s2; } if(s->type == tnumber) { string_t* s2 = string_create(); string_appendn(s2,s->data.number); tobject_freeifzero(s); return s2; } if(s->type == tchar) { string_t* s2 = string_create(); string_appendc(s2,s->data.chr); tobject_freeifzero(s); return s2; } if(s->type == tbool) { string_t* s2 = string_create(); string_appendp(s2,s->data.boolean ? "true" : "false"); tobject_freeifzero(s); return s2; } if(s->type == tnull) { string_t* s2 = string_create(); string_appendp(s2, "null"); tobject_freeifzero(s); return s2; } if(s->type == tdict) { string_t* s2 = string_create(); if(dict_haskey(s->data.dict,"toString")) { tobject_t* o2 = dict_getkvp(s->data.dict,"toString")->value; if(o2->type == texternalmethod || o2->type == tinternalmethod) { list_tobject_t o; list_create(sc->rt,&o,0); tobject_t* res=tobject_call(sc,o2,&o); list_free(&o); string_t* str=tobject_tostring(sc,res); tobject_freeifzero(o2); tobject_freeifzero(s); return str; } } tobject_freeifzero(s); return s2; } string_t* s3 = string_create(); string_appendp(s3, "undefined"); return s3; } tobject_t* tobject_bool(runtime_t* rt,bool b) { tobject_t* o = tobject_create(rt); o->data.boolean = b; o->type = tbool; return o; } tobject_t* tobject_stringp(runtime_t* rt,const char* ptr) { string_t* str=string_create(); string_appendp(str,ptr); return tobject_string(rt,str); } tobject_t* tobject_char(runtime_t* rt,char c) { tobject_t* o = tobject_create(rt); o->data.chr = c; o->type = tchar; return o; } bool tobject_tobool(tobject_t* o) { if(o->type == tbool) { return o->data.boolean; } if(o->type == tnumber) { return o->data.number != 0; } if(o->type == tchar) { return o->data.chr != 0; } if(o->type == tdict) { return true; } if(o->type == tlist) { return o->data.list.length > 0; } if(o->type == tstring) { return o->data.list.length > 0; } if(o->type == texternalmethod) { return true; } if(o->type == tinternalmethod) { return true; } if(o->type == tnull) { return false; } return false; }