void libfunc_objecttotalmembers(void){ if(avm_totalactuals()!=1){ avm_error("one argument expected at 'objecttotalmembers'"); return; } avm_memcell* m =avm_getactual(0); if(m==NULL|| m->type!=table_m){ avm_error("argument of 'objecttotalmemers' must be a table"); return; } retval.type=number_m; retval.data.numVal=(int)m->data.tableVal->total; }
void execute_tablegetelem (instruction* instr){ avm_memcell* lv = avm_translate_operand(&instr->result, (avm_memcell*) 0); avm_memcell* t = avm_translate_operand(&instr->arg1, (avm_memcell*) 0); avm_memcell* i = avm_translate_operand(&instr->result, &ax); // assert(lv && &stack[N-1] >= lv && lv > &stack[top] || lv == &retval); // assert(t && stack[N-1] >= t && t > &stack[top]); assert(i); avm_memcellclear(lv); lv->type = nil_m; if(t->type != table_m) { avm_error("illegal use of type %s as table!\n", typeStrings[t->type]); executionFinished = 1; } else { avm_memcell* content = avm_tablegetelem(t->data.tableVal, i); if(content) { avm_assign(lv, content); } else { char* ts = avm_tostring(t); char* is = avm_tostring(i); avm_warning("%s[%s] not found!\n", ts, is); free(ts); free(is); } } }
void execute_call(instruction* instr){ //printf("exec_call\n"); avm_memcell* func = avm_translate_operand(&instr->result, &ax); assert(func); avm_callsaveenviroment(); switch (func->type){ case userfunc_m: { pc = func->data.funcVal; assert(pc < AVM_ENDING_PC); assert(instr[pc].opcode = funcenter_v); break; } case string_m: { avm_calllibfunc(func->data.strVal); break; } case libfunc_m: { avm_calllibfunc(func->data.strVal); break; } default: { char *s = (char*) malloc(sizeof(char)); s = avm_tostring(func); avm_error("call: cannot bind '%s' to function!"); free(s); executionFinished = 1; } } }
void avm_dec_top(void){ if(!top){ avm_error("stack overflow"); executionFinished=1; } else --top; }
void execute_tablegetelem(instruction* instr){ //printf("exec_tableget\n"); avm_memcell* lv = avm_translate_operand(&instr->result,(avm_memcell*) 0); avm_memcell* t = avm_translate_operand(&instr->arg1,(avm_memcell*) 0); avm_memcell* i = avm_translate_operand(&instr->arg2,&ax); assert(lv && (&stack[AVM_STACKSIZE-1] >= lv && lv > &stack[top] || lv == &retval)); assert(t && &stack[AVM_STACKSIZE-1] >= t && t > &stack[top]); assert(i); avm_memcellclear(lv); lv->type = nil_m; if(t->type != table_m){ avm_error("illigal use of type as table!"); } else{ avm_memcell* content = avm_tablegetelem(t->data.tableVal,i); if(content) avm_assign(lv,content); else{ char* ts = avm_tostring(t); char* is = avm_tostring(i); avm_warning("not found!"); free(ts); free(is); } } }
void execute_call (instruction* instr){ avm_memcell* func = avm_translate_operand(&instr->result, &ax); assert(func); avm_callsaveenvironment(); char* s; switch(func->type) { case userfunc_m: pc = func->data.funcVal; assert(pc < AVM_ENDING_PC); assert(code[pc].opcode == funcenter_v); break; case string_m: avm_calllibfunc(func->data.strVal); break; case libfunc_m: avm_calllibfunc(func->data.libfuncVal); break; default: s = avm_tostring(func); avm_error("call: can not bind '%s' to function!\n", s); free(s); executionFinished = 1; } }
void libfunc_strtonum(void){ unsigned n=avm_totalactuals(); avm_memcellclear(&retval); if(n==0){ avm_error("too few arguments for strtonum"); retval.type=nil_m; return; } avm_memcell* m=avm_getactual(0); if(m->type!=string_m){ avm_error("argument of strtonum must be a string"); retval.type=nil_m; return; } retval.type=number_m; retval.data.numVal=atof(m->data.strVal); }
void libfunc_typeof(void){ unsigned n = avm_totalactuals(); if(n != 1) avm_error("one argument expected in 'typeof'!"); else{ avm_memcellclear(&retval); retval.type = string_m; retval.data.strVal = strdup(typeStrings[avm_getactual(0)->type]); } }
double mod_impl(double x, double y){ if(y == 0) { avm_error("Can not mod with 0!\n"); executionFinished = 1; } else { return ((unsigned) x) % ((unsigned) y); } }
double div_impl(double x, double y){ if(y == 0) { avm_error("Can not div with 0!\n"); executionFinished = 1; } else { return x / y; } }
void execute_tablesetelem(instruction* instr){ //printf("exec_tableset\n"); avm_memcell* t = avm_translate_operand(&instr->arg1,(avm_memcell*) 0); avm_memcell* i = avm_translate_operand(&instr->arg2,&ax); avm_memcell* c = avm_translate_operand(&instr->result,&bx); assert(t && &stack[AVM_STACKSIZE-1] >= t && t > &stack[top]); assert(i && c); if(t->type != table_m) avm_error("illigal use of type as table!"); else avm_tablesetelem(t->data.tableVal, i, c); }
void libfunc_input(void){ unsigned n=avm_totalactuals(); if(n!=0){ avm_error("no argument expected at 'input'"); return ; } char* input=malloc(sizeof(char)*100); fgets(input,99,stdin); avm_memcellclear(&retval); retval.type=string_m; retval.data.strVal=input; }
void libfunc_totalarguments(void){ unsigned p_topsp = avm_get_envvalue(topsp + AVM_SAVEDTOPSP_OFFSET); avm_memcellclear(&retval); if(!p_topsp){ avm_error("'totalarguments' called outside a function!"); retval.type = nil_m; } else{ retval.type = number_m; retval.data.numVal = avm_get_envvalue(p_topsp + AVM_NUMACTUALS_OFFSET); } }
void libfunc_argument(void){ unsigned p_topsp=avm_get_envvalue(topsp+AVM_SAVEDTOPSP_OFFSET); avm_memcellclear(&retval); unsigned i; if(p_topsp>=AVM_STACKSIZE-1-programVarOffset){ avm_error("'argument' called outside of a function"); retval.type=nil_m; } unsigned n=avm_totalactuals(); if(n!=1){ avm_error("one argument expected at 'argument'"); return ; } avm_memcell* m=avm_getactual(0); if(m->type!=number_m){ avm_error("argument of 'argument' must be a number"); return; } int doubletoint=m->data.numVal; retval=stack[p_topsp+AVM_STACKENV_SIZE +1 +doubletoint]; }
void libfunc_totalarguments(void){ unsigned p_topsp=avm_get_envvalue(topsp+AVM_SAVEDTOPSP_OFFSET); avm_memcellclear(&retval); unsigned i; if(p_topsp>=AVM_STACKSIZE-1-programVarOffset){ avm_error("'totalarguments' called outside of a function"); retval.type=nil_m; } else { retval.type=number_m; retval.data.numVal=avm_get_envvalue(p_topsp+AVM_NUMACTUALS_OFFSET); } }
void execute_tablesetelem (instruction* instr){ avm_memcell* t = avm_translate_operand(&instr->result, (avm_memcell*) 0); avm_memcell* i = avm_translate_operand(&instr->arg1, &ax); avm_memcell* c = avm_translate_operand(&instr->arg2, &bx); // assert(t && &stack[N-1] >= t && t > &stack[top]); assert(i && c); if(t->type != table_m) { avm_error("illegal use of type %s as table!\n", typeStrings[t->type]); executionFinished = 1; } else { avm_tablesetelem(t->data.tableVal, i, c); } }
void avm_calllibfunc(char *id){ library_func_t f = avm_getlibraryfunc(id); if(!f){ avm_error("unsupported lib func"); executionFinished = 1; }else{ topsp = top; totalActuals = 0; (*f)(); if(!executionFinished) execute_funcexit(NULL); } return; }
void avm_calllibfunc(char* funcName){ library_func_t f = avm_getlibraryfunc(funcName); if(!f) { avm_error("unsupported lib func '%s' called!\n", funcName); executionFinished = 1; } else { topsp = top; totalActuals = 0; (*f)(); if(!executionFinished) { execute_funcexit((instruction*) 0); } } }
void execute_arithmetic (instruction* instr) { avm_memcell* lv = avm_translate_operand(instr->result,(avm_memcell*)0); avm_memcell* rv1= avm_translate_operand(instr->arg1,&ax); avm_memcell* rv2= avm_translate_operand(instr->arg2,&bx); assert(lv && ( (&stack[AVM_STACKSIZE]>= lv && &stack[top]<lv )|| lv==&retval )); assert(rv1 && rv2); if (rv1->type !=number_m || rv2->type !=number_m ) { avm_error("not a number arithmetic!\n"); executionFinished=1; } else { arithmetic_func_t op=arithmeticFuncs[instr->opcode - add_v]; avm_memcellclear(lv); lv->type = number_m; lv->data.numVal = (*op)(rv1->data.numVal,rv2->data.numVal); } //printf("DEBUG VALUE:%d\n",(int)lv->data.numVal); }
void execute_jne (instruction* instr){ assert(instr->result.type == label_a); avm_memcell* rv1 = avm_translate_operand(&instr->arg1, &ax); avm_memcell* rv2 = avm_translate_operand(&instr->arg2, &bx); unsigned char result = 0; if(rv1->type == undef_m){ rv1->type=number_m; } if(rv2->type == undef_m){ rv1->type=number_m; } if((rv1->type == undef_m)||(rv2->type == undef_m)) { avm_error("'undef' involved in equality!\n"); executionFinished = 1; } else if((rv1->type == nil_m)||(rv2->type == nil_m)) { result = (rv1->type == nil_m) && (rv2->type == nil_m); } else if((rv1->type == bool_m)||(rv2->type == bool_m)) { result = (avm_tobool(rv1) == avm_tobool(rv2)); } else if(rv1->type != rv2->type) { avm_error("%s == %s is illegal!\n", typeStrings[rv1->type], typeStrings[rv2->type]); executionFinished = 1; } else if(rv1->type == number_m) { if(rv1->data.numVal != rv2->data.numVal) { result = 1; } } else if(rv1->type == string_m) { if(strcmp(rv1->data.strVal, rv2->data.strVal) != 0) { result = 1; } } else if(rv1->type == table_m) { if(rv1->data.tableVal->total != rv2->data.tableVal->total) { result = 1; } } else if(rv1->type == userfunc_m) { // ? } else if(rv1->type == libfunc_m) { // ? } if(!executionFinished && result) { pc = instr->result.val; } }
double div_impl( double x, double y ) { if( y == 0) { avm_error("Error:Division with zero attempted.\n"); } return x/y; }
double mod_impl( double x, double y ) { if( y == 0) { avm_error("Error:Division with zero attempted.\n"); } return (( unsigned ) x ) % (( unsigned ) y ); }