Beispiel #1
0
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;          
            }
        }
    }
}
Beispiel #4
0
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;
}