void Functions::toString(Aurora::NWScript::FunctionContext &ctx) { ctx.getReturn() = ""; switch (ctx.getParams()[0].getType()) { case Aurora::NWScript::kTypeInt: intToString(ctx); break; case Aurora::NWScript::kTypeFloat: floatToString(ctx); break; case Aurora::NWScript::kTypeString: ctx.getReturn() = ctx.getParams()[0]; break; case Aurora::NWScript::kTypeObject: objectToString(ctx); break; case Aurora::NWScript::kTypeVector: vectorToString(ctx); break; default: break; } }
static void como_execute(ComoFrame *frame, ComoFrame *callingframe) { size_t i; for(i = 0; i < O_AVAL(frame->code)->size; i++) { ComoOpCode *opcode = ((ComoOpCode *)(O_PTVAL(O_AVAL(frame->code)->table[i]))); switch(opcode->op_code) { default: { como_error_noreturn("Invalid OpCode got %d", opcode->op_code); } case POSTFIX_INC: { Object *value = NULL; value = mapSearchEx(frame->cf_symtab, O_SVAL(opcode->operand)->value); if(value == NULL) { como_error_noreturn("undefined variable '%s'", O_SVAL(opcode->operand)->value); } else { if(O_TYPE(value) != IS_LONG) { como_error_noreturn("unsupported value for POSTFIX_INC"); } else { long oldvalue = O_LVAL(value); O_LVAL(value) = oldvalue + 1; push(frame, newLong(oldvalue)); } } break; } case POSTFIX_DEC: { Object *value = NULL; value = mapSearchEx(frame->cf_symtab, O_SVAL(opcode->operand)->value); if(value == NULL) { como_error_noreturn("undefined variable '%s'", O_SVAL(opcode->operand)->value); } else { if(O_TYPE(value) != IS_LONG) { como_error_noreturn("unsupported value for POSTFIX_DEC"); } else { long oldvalue = O_LVAL(value); O_LVAL(value) = oldvalue - 1; push(frame, newLong(oldvalue)); } } break; } case IS_LESS_THAN: { Object *right = pop(frame); Object *left = pop(frame); assert(right); assert(left); if(objectValueIsLessThan(left, right)) { push(frame, newLong(1L)); } else { push(frame, newLong(0L)); } break; } case IADD: { Object *right = pop(frame); Object *left = pop(frame); assert(right); assert(left); if(O_TYPE(left) == IS_LONG && O_TYPE(right) == IS_LONG) { long value = O_LVAL(left) + O_LVAL(right); push(frame, newLong(value)); } else { char *left_str = objectToString(left); char *right_str = objectToString(right); Object *s1 = newString(left_str); Object *s2 = newString(right_str); Object *value = stringCat(s1, s2); push(frame, value); objectDestroy(s1); objectDestroy(s2); free(left_str); free(right_str); } break; } case IMINUS: { Object *right = pop(frame); Object *left = pop(frame); assert(right); assert(left); if(O_TYPE(left) != IS_LONG && O_TYPE(right) != IS_LONG) { como_error_noreturn("unsupported value for IMINUS"); } else { push(frame, newLong(O_LVAL(left) - O_LVAL(right))); } break; } case IS_LESS_THAN_OR_EQUAL: { Object *right = pop(frame); Object *left = pop(frame); assert(right); assert(left); if(objectValueCompare(left, right) || objectValueIsLessThan(left, right)) { push(frame, newLong(1L)); } else { push(frame, newLong(0L)); } break; } case JZ: { Object *cond = pop(frame); if(O_TYPE(cond) == IS_LONG && O_LVAL(cond) == 0) { i = (size_t)O_LVAL(opcode->operand); continue; } break; } case JMP: { i = O_LVAL(opcode->operand); continue; } case LABEL: { break; } case HALT: { break; } case IS_NOT_EQUAL: { Object *right = pop(frame); Object *left = pop(frame); if(!objectValueCompare(left, right)) { push(frame, newLong(1L)); } else { push(frame, newLong(0L)); } break; } case LOAD_CONST: { como_debug("LOAD_CONST"); push(frame, opcode->operand); break; } case STORE_NAME: { Object *value = pop(frame); mapInsertEx(frame->cf_symtab, O_SVAL(opcode->operand)->value, value); break; } /* This is where recursion was broken, don't do *ex */ case LOAD_NAME: { Object *value = NULL; value = mapSearch(frame->cf_symtab, O_SVAL(opcode->operand)->value); if(value) { goto load_name_leave; } else { value = mapSearch(global_frame->cf_symtab, O_SVAL(opcode->operand)->value); } if(value == NULL) { como_error_noreturn("undefined variable '%s'", O_SVAL(opcode->operand)->value); } load_name_leave: push(frame, value); break; } case CALL_FUNCTION: { Object *fn = pop(frame); Object *argcount = pop(frame); long i = O_LVAL(argcount); ComoFrame *fnframe; if(O_TYPE(fn) != IS_POINTER) { como_error_noreturn("name '%s' is not callable", O_SVAL(opcode->operand)->value); } fnframe = (ComoFrame *)O_PTVAL(fn); if(O_LVAL(argcount) != (long)(O_AVAL(fnframe->namedparameters)->size)) { como_error_noreturn("callable '%s' expects %ld arguments, but %ld were given", O_SVAL(opcode->operand)->value, (long)(O_AVAL(fnframe->namedparameters)->size), O_LVAL(argcount)); } //como_debug("calling '%s'", O_SVAL(opcode->operand)->value); // DOING THIS ACTUALLY DEFINES THE NAME AT RUNTIME // which could not be equal to that actual function body // declared // name = my_function // name() // that call will have "name" for value __FUNCTION__ // even though the real function is my_function // must define it at COMPILE time // mapInsertEx(fnframe->cf_symtab, "__FUNCTION__", // newString(O_SVAL(opcode->operand)->value)); while(i--) { como_debug("getting %ldth argument for function call '%s'", i, O_SVAL(opcode->operand)->value); Object *argname = O_AVAL(fnframe->namedparameters)->table[i]; Object *argvalue = pop(frame); mapInsert(fnframe->cf_symtab, O_SVAL(argname)->value, argvalue); char *argvaluestr = objectToString(argvalue); como_debug("%ldth argument: '%s' has value: %s", i, O_SVAL(argname)->value, argvaluestr); free(argvaluestr); } //ComoFrame *prev = frame; //fnframe->next = prev; como_execute(fnframe, NULL); push(frame, pop(fnframe)); //fnframe->next = NULL; break; } case IS_EQUAL: { Object *right = pop(frame); Object *left = pop(frame); push(frame, newLong((long)objectValueCompare(left, right))); break; } case ITIMES: { Object *right = pop(frame); Object *left = pop(frame); assert(right); assert(left); if(O_TYPE(right) != IS_LONG && O_TYPE(left) != IS_LONG) { como_error_noreturn("invalid operands for ITIMES"); } como_debug("ITIMES: %d, %d", O_TYPE(left), O_TYPE(right)); long value = O_LVAL(left) * O_LVAL(right); push(frame, newLong(value)); break; } case IRETURN: { /* If there wasn't a return statement found in func body* * The compiler will insert a 1 as the operand if * the AST had an expression for the return statement, * otherwise, it will be 0 * The actual value to be returned is popped from the stack */ if(! (O_LVAL(opcode->operand))) { push(frame, newLong(0L)); } return; } case IPRINT: { Object *value = pop(frame); size_t len = 0; char *sval = objectToStringLength(value, &len); fprintf(stdout, "%s\n", sval); fflush(stdout); free(sval); break; } } } }
void debug_code_to_output(FILE *fp, compiler_context *cg) { fprintf(fp, "*** BEGIN CODE ***\n"); size_t i; for(i = 0; i < cg->code.size; i++) { op_code *c = cg->code.table[i]; switch(c->inst.opcode) { case IRETURN: { char *value = objectToString(c->op1); fprintf(fp, "\tIRETURN %s\n", value); free(value); break; } case CALL_FUNCTION: { char *value = objectToString(c->op1); fprintf(fp, "\tCALL_FUNCTION %s\n", value); free(value); break; } case DEFINE_FUNCTION: { char *value = objectToString(c->op1); fprintf(fp, "\tDEFINE_FUNCTION %s\n", value); free(value); break; } case LOAD_CONST: { char *value = objectToString(c->op1); fprintf(fp, "\tLOAD_CONST %s\n", value); free(value); break; } case STORE_NAME: { char *value = objectToString(c->op1); fprintf(fp, "\tSTORE_NAME %s\n", value); free(value); break; } case LOAD_NAME: { char *value = objectToString(c->op1); fprintf(fp, "\tLOAD_NAME %s\n", value); free(value); break; } case IS_LESS_THAN: { fprintf(fp, "\tIS_LESS_THAN\n"); break; } case JZ: { char *value = objectToString(c->op1); fprintf(fp, "\tJZ %s\n", value); free(value); break; } case IPRINT: { fprintf(fp,"\tPRINT\n"); break; } case IADD: { fprintf(fp, "\tADD\n"); break; } case IMINUS: { fprintf(fp, "\tSUB\n"); break; } case IDIV: { fprintf(fp, "\tDIV\n"); break; } case ITIMES: { fprintf(fp, "\tTIMES\n"); break; } case JMP: { char *value = objectToString(c->op1); fprintf(fp, "\tJMP %s\n", value); free(value); break; } case NOP: { fprintf(fp,"\tNOP\n"); break; } case LABEL: { char *value = objectToString(c->op1); fprintf(fp, "LABEL %s\n", value); free(value); break; } case HALT: { fprintf(fp, "\tHALT\n"); break; } case IS_EQUAL: { fprintf(fp, "\tIS_EQUAL\n"); break; } case IS_GREATER_THAN: { fprintf(fp, "\tIS_GREATER_THAN\n"); break; } case IS_NOT_EQUAL: { fprintf(fp, "\tIS_NOT_EQUAL\n"); break; } case IS_GREATER_THAN_OR_EQUAL: { fprintf(fp, "\tIS_GREATER_THAN_OR_EQUAL\n"); break; } case IS_LESS_THAN_OR_EQUAL: { fprintf(fp, "\tIS_LESS_THAN_OR_EQUAL\n"); break; } case POSTFIX_INC: { fprintf(fp, "\tPOSTFIX_INC\n"); break; } case UNARY_MINUS: { fprintf(fp, "\tUNARY_MINUS\n"); break; } } } fprintf(fp, "*** END CODE ***\n"); }