void SkyPoint::nutate(const KSNumbers *num) { double cosRA, sinRA, cosDec, sinDec, tanDec; double cosOb, sinOb; RA.SinCos( sinRA, cosRA ); Dec.SinCos( sinDec, cosDec ); num->obliquity()->SinCos( sinOb, cosOb ); //Step 2: Nutation if ( fabs( Dec.Degrees() ) < 80.0 ) { //approximate method tanDec = sinDec/cosDec; double dRA = num->dEcLong()*( cosOb + sinOb*sinRA*tanDec ) - num->dObliq()*cosRA*tanDec; double dDec = num->dEcLong()*( sinOb*cosRA ) + num->dObliq()*sinRA; RA.setD( RA.Degrees() + dRA ); Dec.setD( Dec.Degrees() + dDec ); } else { //exact method dms EcLong, EcLat; findEcliptic( num->obliquity(), EcLong, EcLat ); //Add dEcLong to the Ecliptic Longitude dms newLong( EcLong.Degrees() + num->dEcLong() ); setFromEcliptic( num->obliquity(), newLong, EcLat ); } }
static void como_compile(ast_node* p, ComoFrame *frame) { assert(p); switch(p->type) { default: printf("%s(): invalid node type(%d)\n", __func__, p->type); exit(1); break; case AST_NODE_TYPE_STRING: arrayPushEx(frame->code, newPointer((void *)create_op(LOAD_CONST, newString(p->u1.string_value.value)))); break; case AST_NODE_TYPE_PRINT: como_compile(p->u1.print_node.expr, frame); arrayPushEx(frame->code, newPointer((void *)create_op(IPRINT, NULL))); break; case AST_NODE_TYPE_NUMBER: arrayPushEx(frame->code, newPointer((void *)create_op(LOAD_CONST, newLong((long)p->u1.number_value)))); break; case AST_NODE_TYPE_ID: arrayPushEx(frame->code, newPointer((void *)create_op(LOAD_NAME, newString(p->u1.string_value.value)))); break; case AST_NODE_TYPE_RET: if(p->u1.return_node.expr != NULL) { como_compile(p->u1.return_node.expr, frame); arrayPushEx(frame->code, newPointer((void *)create_op(IRETURN, newLong(1L)))); } else { arrayPushEx(frame->code, newPointer((void *)create_op(IRETURN, newLong(0L)))); } break; case AST_NODE_TYPE_STATEMENT_LIST: { size_t i; for(i = 0; i < p->u1.statements_node.count; i++) { ast_node* stmt = p->u1.statements_node.statement_list[i]; como_compile(stmt, frame); } } break; case AST_NODE_TYPE_WHILE: { Object *l = newLong((long)(O_AVAL(frame->code)->size)); arrayPushEx(frame->code, newPointer((void *)create_op(LABEL, l))); Object *l2 = newLong(0); como_compile(p->u1.while_node.condition, frame); arrayPushEx(frame->code, newPointer((void *)create_op(JZ, l2))); como_compile(p->u1.while_node.body, frame); arrayPushEx(frame->code, newPointer((void *)create_op(JMP, newLong(O_LVAL(l))))); Object *l3 = newLong((long)(O_AVAL(frame->code)->size)); arrayPushEx(frame->code, newPointer((void *)create_op(LABEL, l3))); O_LVAL(l2) = O_LVAL(l3); } break; case AST_NODE_TYPE_FOR: { Object *l = newLong((long)(O_AVAL(frame->code)->size)); arrayPushEx(frame->code, newPointer((void *)create_op(LABEL, l))); Object *l2 = newLong(0); como_compile(p->u1.for_node.initialization, frame); como_compile(p->u1.for_node.condition, frame); arrayPushEx(frame->code, newPointer((void *)create_op(JZ, l2))); Object *l4 = newLong((long)(O_AVAL(frame->code)->size)); /* label for the body */ arrayPushEx(frame->code, newPointer((void *)create_op(LABEL, l4))); como_compile(p->u1.for_node.body, frame); como_compile(p->u1.for_node.final_expression, frame); como_compile(p->u1.for_node.condition, frame); arrayPushEx(frame->code, newPointer((void *)create_op(JZ, l2))); arrayPushEx(frame->code, newPointer((void *)create_op(JMP, newLong(O_LVAL(l4))))); Object *l3 = newLong((long)(O_AVAL(frame->code)->size)); arrayPushEx(frame->code, newPointer((void *)create_op(LABEL, l3))); O_LVAL(l2) = O_LVAL(l3); } break; case AST_NODE_TYPE_IF: { Object *l2 = newLong(0); Object *l4 = newLong(0); como_compile(p->u1.if_node.condition, frame); arrayPushEx(frame->code, newPointer((void *)create_op(JZ, l2))); como_compile(p->u1.if_node.b1, frame); arrayPushEx(frame->code, newPointer((void *)create_op(JMP, l4))); Object *l3 = newLong((long)(O_AVAL(frame->code)->size)); arrayPushEx(frame->code, newPointer((void *)create_op(LABEL, l3))); if(p->u1.if_node.b2 != NULL) { como_compile(p->u1.if_node.b2, frame); } O_LVAL(l2) = O_LVAL(l3); O_LVAL(l4) = (long)(O_AVAL(frame->code)->size); arrayPushEx(frame->code, newPointer((void *)create_op(LABEL, newLong((long)(O_AVAL(frame->code)->size))))); } break; case AST_NODE_TYPE_FUNC_DECL: { const char *name = p->u1.function_node.name; Object *func_decl = newArray(4); Object *func_decl_parameters = newArray(2); ComoFrame *func_decl_frame = create_frame(func_decl); func_decl_frame->namedparameters = func_decl_parameters; if(frame->filename != NULL) { func_decl_frame->filename = copyObject(frame->filename); } else { func_decl_frame->filename = newString("<unknown>"); } size_t i; ast_node_statements *parameters = &p->u1.function_node .parameter_list->u1 .statements_node; for(i = 0; i < parameters->count; i++) { arrayPushEx(func_decl_parameters, newString( AST_NODE_AS_ID( parameters->statement_list[i] ) ) ); } arrayPushEx(func_decl_frame->code, newPointer((void *)create_op(LOAD_CONST, newString(name)))); arrayPushEx(func_decl_frame->code, newPointer((void *)create_op(STORE_NAME, newString("__FUNCTION__")))); como_compile(p->u1.function_node.body, func_decl_frame); Array *temp = O_AVAL(func_decl_frame->code); Object *temp2 = temp->table[temp->size - 1]; ComoOpCode *opcode = (ComoOpCode *)(O_PTVAL(temp2)); if(opcode->op_code != IRETURN) { //como_debug("automatically inserting IRETURN for function %s", name); arrayPushEx(func_decl_frame->code, newPointer( (void *)create_op(LOAD_CONST, newLong(0L)))); arrayPushEx(func_decl_frame->code, newPointer( (void *)create_op(IRETURN, newLong(1L)))); } mapInsertEx(global_frame->cf_symtab, name, newPointer( (void *)func_decl_frame)); break; } case AST_NODE_TYPE_CALL: { const char *name = p->u1.call_node.id->u1.id_node.name; const long argcount = (long)p->u1 .call_node .arguments->u1 .statements_node .count; como_compile(p->u1.call_node.arguments, frame); arrayPushEx(frame->code, newPointer( (void *)create_op(LOAD_CONST, newLong(argcount)))); arrayPushEx(frame->code, newPointer( (void *)create_op(LOAD_NAME, newString(name)))); arrayPushEx(frame->code, newPointer( (void *)create_op(CALL_FUNCTION, newString(name)))); break; } case AST_NODE_TYPE_POSTFIX: { Object *name = newString(AST_NODE_AS_ID(p->u1.postfix_node.expr)); switch(p->u1.postfix_node.type) { case AST_POSTFIX_OP_INC: arrayPushEx(frame->code, newPointer( (void *)create_op(POSTFIX_INC, name))); break; case AST_POSTFIX_OP_DEC: arrayPushEx(frame->code, newPointer( (void *)create_op(POSTFIX_DEC, name))); break; } break; } case AST_NODE_TYPE_UNARY_OP: { switch(p->u1.unary_node.type) { case AST_UNARY_OP_MINUS: como_compile(p->u1.unary_node.expr, frame); arrayPushEx(frame->code, newPointer( (void *)create_op(UNARY_MINUS, NULL))); break; } } break; case AST_NODE_TYPE_BIN_OP: { if(p->u1.binary_node.type != AST_BINARY_OP_ASSIGN) { como_compile(p->u1.binary_node.left, frame); como_compile(p->u1.binary_node.right, frame); } switch(p->u1.binary_node.type) { case AST_BINARY_OP_REM: arrayPushEx(frame->code, newPointer( (void *)create_op(IREM, NULL))); break; case AST_BINARY_OP_LTE: arrayPushEx(frame->code, newPointer( (void *)create_op(IS_LESS_THAN_OR_EQUAL, NULL))); break; case AST_BINARY_OP_GTE: arrayPushEx(frame->code, newPointer( (void *)create_op(IS_GREATER_THAN_OR_EQUAL, NULL))); break; case AST_BINARY_OP_LT: arrayPushEx(frame->code, newPointer( (void *)create_op(IS_LESS_THAN, NULL))); break; case AST_BINARY_OP_GT: arrayPushEx(frame->code, newPointer( (void *)create_op(IS_GREATER_THAN, NULL))); break; case AST_BINARY_OP_CMP: arrayPushEx(frame->code, newPointer( (void *)create_op(IS_EQUAL, NULL))); break; case AST_BINARY_OP_NEQ: arrayPushEx(frame->code, newPointer( (void *)create_op(IS_NOT_EQUAL, NULL))); break; case AST_BINARY_OP_MINUS: arrayPushEx(frame->code, newPointer( (void *)create_op(IMINUS, NULL))); break; case AST_BINARY_OP_DIV: arrayPushEx(frame->code, newPointer( (void *)create_op(IDIV, NULL))); break; case AST_BINARY_OP_ADD: arrayPushEx(frame->code, newPointer( (void *)create_op(IADD, NULL))); break; case AST_BINARY_OP_TIMES: arrayPushEx(frame->code, newPointer( (void *)create_op(ITIMES, NULL))); break; case AST_BINARY_OP_ASSIGN: como_compile(p->u1.binary_node.right, frame); arrayPushEx(frame->code, newPointer( (void *)create_op(STORE_NAME, newString( p->u1.binary_node.left->u1.id_node.name)))); break; } } 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; } } } }
int main(void) { gcinit(); stackinit(); while(1) { char buffer[80]; ssize_t bytes_read = raw_input("calc> ", buffer, sizeof(buffer)); if(bytes_read == EOF) { return 0; } else { Buffer p; buffer_init(&p, buffer, bytes_read); size_t i = 0; while(p.pos != p.end) { if(IS_DIGIT(*p.pos)) { int num = *p.pos - '0'; stackpush(newLong(num)); printf("PUSH %d\n", num); } else if(IS_OPERATOR(*p.pos)) { if(pstack.stacksize < 2) { fprintf(stderr, "operator '%c' takes 2 args\n", *p.pos); goto finally; } else { Object* op2 = stackpop(); Object* op1 = stackpop(); if(*p.pos == '+') { printf("POP %ld\n", O_LVAL(op2)); printf("POP %ld\n", O_LVAL(op1)); long result; result = O_LVAL(op1) + O_LVAL(op2); Object *retval = newLong(result); printf("ADD\n"); stackpush(retval); printf("PUSH %ld\n", result); } else if(*p.pos == '-') { long result; result = O_LVAL(op1) - O_LVAL(op2); Object *retval = newLong(result); stackpush(retval); } } } else if (IS_WHITE(*p.pos)) { goto out; } else { fprintf(stderr, "Invalid token %c\n", *p.pos); goto finally; } out: p.pos++; i++; } if(pstack.stacksize == 1) { Object *top = stackpop(); objectEcho(top); } else { printf("To many values: %zu", pstack.stacksize); } finally: gcterm(); gcinit(); stackinit(); printf("\n"); } } return 0; }