tlang-c/libtlang/src/tobject.c

509 lines
13 KiB
C

#include "tlang.h"
#include <stdlib.h>
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;i<ls->length;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;i<a->length;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(offset<a->length) return a->items[offset];
return NULL;
}
void list_rm(list_tobject_t* a,int offset)
{
if(offset<a->length)
{
tobject_rmref(a->items[offset]);
int i;
a->length--;
for(i=offset;i<a->length;i++)
{
a->items[i] = a->items[i+1];
}
}
}
void list_clear(list_tobject_t* a)
{
int i;
for(i=0;i<a->length;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;i<str->count;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;i<str->count;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(func->data.internal_method.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(;i<optionalArgs(strs,argCountCaller);i++)
{
tobject_t* _obj=args->items[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(;i<args->length;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;i<n->data.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;
}