509 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			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;
 | |
| } |