|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T p
Length: 15551 (0x3cbf) Types: TextFile Names: »prim.c«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki └─⟦this⟧ »EUUGD11/gnu-31mar87/scheme/microcode/prim.c«
/* Hey EMACS, this is -*- C -*- code! */ /**************************************************************** * * * Copyright (c) 1984 * * Massachusetts Institute of Technology * * * * This material was developed by the Scheme project at the * * Massachusetts Institute of Technology, Department of * * Electrical Engineering and Computer Science. Permission to * * copy this software, to redistribute it, and to use it for any * * purpose is granted, subject to the following restrictions and * * understandings. * * * * 1. Any copy made of this software must include this copyright * * notice in full. * * * * 2. Users of this software agree to make their best efforts (a)* * to return to the MIT Scheme project any improvements or * * extensions that they make, so that these may be included in * * future releases; and (b) to inform MIT of noteworthy uses of * * this software. * * * * 3. All materials developed as a consequence of the use of * * this software shall duly acknowledge such use, in accordance * * with the usual standards of acknowledging credit in academic * * research. * * * * 4. MIT has made no warrantee or representation that the * * operation of this software will be error-free, and MIT is * * under no obligation to provide any services, by way of * * maintenance, update, or otherwise. * * * * 5. In conjunction with products arising from the use of this * * material, there shall be no use of the name of the * * Massachusetts Institute of Technology nor of any adaptation * * thereof in any advertising, promotional, or sales literature * * without prior written consent from MIT in each case. * * * ****************************************************************/ \f /* File: PRIM.C * * The leftovers ... primitives that don't seem to belong elsewhere */ #include "scheme.h" #include "primitive.h" #include "prims.h" /* (EQ OBJECT-1 OBJECT-2) [Primitive number 0x0D] Returns #!TRUE if the two objects have the same type code, address portion, and danger bit. Returns NIL otherwise. */ Built_In_Primitive(Prim_Eq, 2, "EQ?") { Primitive_2_Args(); if (Arg1 == Arg2) return TRUTH; Touch_In_Primitive(Arg1, Arg1); Touch_In_Primitive(Arg2, Arg2); return (Arg1 == Arg2) ? TRUTH : NIL; } /* (DANGERIZE OBJECT) [Primitive number 0x48] Returns OBJECT, but with the danger bit set. */ Built_In_Primitive(Prim_Dangerize, 1, "DANGERIZE") { Primitive_1_Arg(); return Set_Danger_Bit(Arg1); } /* (DANGEROUS_QM OBJECT) [Primitive number 0x49] Returns #!TRUE if OBJECT has the danger bit set, NIL otherwise. */ Built_In_Primitive(Prim_Dangerous_QM, 1, "DANGEROUS?") { Primitive_1_Arg(); return (Dangerous(Arg1)) ? TRUTH : NIL; } \f #ifdef COMPILE_FUTURES Built_In_Primitive(Prim_Get_Work, 1, "GET-WORK") { Pointer The_Queue, Queue_Head, Queue_Tail, Result; Primitive_1_Arg(); The_Queue = Get_Fixed_Obj_Slot(The_Work_Queue); if (The_Queue != NIL) { Queue_Head = Vector_Ref(The_Queue, CONS_CAR); Queue_Tail = Vector_Ref(The_Queue, CONS_CDR); } if ((The_Queue==NIL) || (Queue_Head==NIL)) if (Arg1 == NIL) { printf("\nNo work available, but some has been requested!\n"); Microcode_Termination(TERM_EXIT); } else { Pop_Primitive_Frame(1); Will_Push(2*STACK_ENV_EXTRA_SLOTS + 1 + CONTINUATION_SIZE); Push(NIL); /* Upon return, no hope if there is no work */ Push(Make_Non_Pointer(TC_PRIMITIVE, PC_GET_WORK)); Push(STACK_FRAME_HEADER+1); Store_Expression(NIL); Store_Return(RC_INTERNAL_APPLY); Save_Cont(); Push(Arg1); Push(STACK_FRAME_HEADER); Pushed(); longjmp(*Back_To_Eval, PRIM_APPLY); } Result = Vector_Ref(Queue_Head, CONS_CAR); Queue_Head = Vector_Ref(Queue_Head, CONS_CDR); Vector_Set(The_Queue, CONS_CAR, Queue_Head); if (Queue_Head==NIL) Vector_Set(The_Queue, CONS_CDR, NIL); return Result; } #endif /* (INITIALIZE-MICROCODE-DEBUG) [Primitive 0x108] Setup the microcode debugging utilities. */ Built_In_Primitive(Prim_Initialize_Microcode_Debug, 0, "INITIALIZE-MICROCODE-DEBUG") { Primitive_0_Args(); return NIL; } \f /* (INSERT_NON_MARKED_VECTOR TO-GC-VECTOR N FROM-GC-VECTOR) [Primitive number 0x19] This primitive performs a side-effect on the TO-GC-VECTOR. Both TO- and FROM-GC-VECTOR must be of the garbage collector type vector (i.e. vectors, strings, non-marked vectors, bignums, etc.). The FROM-GC-VECTOR is inserted in the middle of TO-GC-VECTOR, preceded by a non-marked vector header. The insertion begins at the Nth position of the vector with the non-marked header. Notice that this is really an "overwrite" rather than an insertion, since the length of the TO-GC-VECTOR does not change and the data which was formerly in the part of the vector now occupied by FROM-GC-VECTOR and its header has been lost. This primitive was added for the use of certain parts of the compiler and runtime system which need to make objects that have an internal part which is "hidden" from the garbage collector. The value returned is TO-GC-VECTOR. */ Built_In_Primitive(Prim_Insert_Non_Marked_Vector, 3, "INSERT-NON-MARKED-VECTOR!") { Pointer *To,*From; long Index,NM_Length,Length,i; Primitive_3_Args(); Arg_1_GC_Type(GC_Vector); Arg_2_Type(TC_FIXNUM); Arg_3_GC_Type(GC_Vector); Length = Vector_Length(Arg1); NM_Length = Vector_Length(Arg3); Range_Check(Index, Arg2, 0, Length-1, ERR_ARG_2_BAD_RANGE); if (Length-Index <= NM_Length) Primitive_Error(ERR_ARG_3_BAD_RANGE); From = Nth_Vector_Loc(Arg3, VECTOR_TYPE); To = Nth_Vector_Loc(Arg1, VECTOR_DATA+Index); for (i=0; i<=NM_Length; i++) *To++ = *From++; return Arg1; } \f /* (MAP_CODE_TO_ADDRESS TYPE-CODE VALUE-CODE) [Primitive number 0x93] For return codes and primitives, this returns the internal representation of the return address or primitive address given the external representation. Currently in CScheme these two are the same. In the 68000 assembly version the internal representation is an actual address in memory. */ Built_In_Primitive(Prim_Map_Code_To_Address, 2, "MAP-CODE-TO-ADDRESS") { long Code, Offset; Primitive_2_Args(); Arg_1_Type(TC_FIXNUM); Arg_2_Type(TC_FIXNUM); Code = Get_Integer(Arg1); Offset = Get_Integer(Arg2); switch (Code) { case TC_RETURN_CODE: if (Offset > MAX_RETURN_CODE) Primitive_Error(ERR_ARG_2_BAD_RANGE); break; case TC_PRIMITIVE: if (Offset > MAX_PRIMITIVE) Primitive_Error(ERR_ARG_2_BAD_RANGE); break; default: Primitive_Error(ERR_ARG_1_BAD_RANGE); } return Make_Non_Pointer(Code, Offset); } \f /* (MAP_ADDRESS_TO_CODE TYPE-CODE ADDRESS) [Primitive number 0x90] This is the inverse operation for MAP_CODE_TO_ADDRESS. Given a machine ADDRESS and a TYPE-CODE (either return code or primitive) it finds the number for the external representation for the internal address. */ Built_In_Primitive(Prim_Map_Address_To_Code, 2, "MAP-ADDRESS-TO-CODE") { long Code, Offset; Primitive_2_Args(); Arg_1_Type(TC_FIXNUM); Code = Get_Integer(Arg1); Arg_2_Type(Code); Offset = Get_Integer(Arg2); switch (Code) { case TC_RETURN_CODE: if (Offset > MAX_RETURN_CODE) Primitive_Error(ERR_ARG_2_BAD_RANGE); break; case TC_PRIMITIVE: if (Offset > MAX_PRIMITIVE) Primitive_Error(ERR_ARG_2_BAD_RANGE); break; default: Primitive_Error(ERR_ARG_1_BAD_RANGE); } return FIXNUM_0+Offset; } \f /* (MAP_PRIM_ADDRESS_TO_ARITY INTERNAL-PRIMITIVE) [Primitive number 0x96] Given the internal representation of a primitive (in CScheme the internal and external representations are the same), return the number of arguments it requires. */ Built_In_Primitive(Prim_Map_Prim_Address_To_Arity, 1, "PRIMITIVE-PROCEDURE-ARITY") { long Prim_Num; Primitive_1_Arg(); if (Type_Code(Arg1) != TC_PRIMITIVE_EXTERNAL) { Arg_1_Type(TC_PRIMITIVE); Range_Check(Prim_Num, Arg1, 0, MAX_PRIMITIVE, ERR_ARG_1_BAD_RANGE); return FIXNUM_0+Arg_Count_Table[Prim_Num]; } /* External primitives here */ Prim_Num = Get_Integer(Arg1); if (Prim_Num <= MAX_EXTERNAL_PRIMITIVE) return FIXNUM_0 + Ext_Prim_Desc[Prim_Num].arity; if (Undefined_Externals==NIL) Primitive_Error(ERR_ARG_1_BAD_RANGE); if (Prim_Num > (MAX_EXTERNAL_PRIMITIVE+ Get_Integer(User_Vector_Ref(Undefined_Externals, 0)))) Primitive_Error(ERR_ARG_1_BAD_RANGE); return NIL; } \f /* (MAKE_NON_POINTER NUMBER) [Primitive number 0xB1] Returns an (extended) fixnum with the same value as NUMBER. In the CScheme interpreter this is basically a no-op, since fixnums already store 24 bits. */ Built_In_Primitive(Prim_Make_Non_Pointer, 1, "MAKE-NON-POINTER") { long Type_Number; Primitive_1_Arg(); Arg_1_Type(TC_FIXNUM); return Arg1; } /* (NON-RESTARTABLE-EXIT) [Primitive number 0x16] Halt SCHEME, with no intention of restarting. */ Built_In_Primitive(Prim_Non_Restartable_Exit, 0, "NON-RESTARTABLE-EXIT") { Primitive_0_Args(); Microcode_Termination(TERM_HALT); } /* (NULL OBJECT) [Primitive number 0x0C] Returns #!TRUE if OBJECT is NIL. Otherwise returns NIL. This is the primitive known as NOT, NIL?, and NULL? in Scheme. */ Built_In_Primitive(Prim_Null, 1, "NULL?") { Primitive_1_Arg(); Touch_In_Primitive(Arg1, Arg1); return (Arg1 == NIL) ? TRUTH : NIL; } \f /* (PRIMITIVE-TYPE OBJECT) [Primitive number 0x10] Returns the type code of OBJECT as a number. This includes the danger bit, if it is set. The object is NOT touched first. */ Built_In_Primitive(Prim_Prim_Type, 1, "PRIMITIVE-TYPE") { Primitive_1_Arg(); return FIXNUM_0+Type_Code(Arg1); } /* (PRIMITIVE-TYPE? TYPE-CODE OBJECT) [Primitive number 0x0F] Return #!TRUE if the type code of OBJECT is TYPE-CODE, NIL otherwise. The check includes the danger bit of OBJECT. The object is NOT touched first. */ Built_In_Primitive(Prim_Prim_Type_QM, 2, "PRIMITIVE-TYPE?") { Primitive_2_Args(); Arg_1_Type(TC_FIXNUM); Touch_In_Primitive(Arg2,Arg2); if (Type_Code(Arg2) == Get_Integer(Arg1)) return TRUTH; else return NIL; } /* (PRIMITIVE_SET_TYPE TYPE-CODE OBJECT) [Primitive number 0x11] Returns a new object with TYPE-CODE and the address part of OBJECT. This is a "safe" operation in that the TYPE-CODE is compared with the existing type-code on OBJECT to make sure that the garbage collect can correctly deal with the returned value. */ Built_In_Primitive(Prim_Primitive_Set_Type, 2, "PRIMITIVE-SET-TYPE") { long New_GC_Type, New_Type; Primitive_2_Args(); Arg_1_Type(TC_FIXNUM); Range_Check(New_Type, Arg1, 0, MAX_SAFE_TYPE, ERR_ARG_1_BAD_RANGE); New_GC_Type = GC_Type_Code(New_Type); if ((GC_Type(Arg2) == New_GC_Type) || (New_GC_Type == GC_Non_Pointer)) return Make_New_Pointer(New_Type, Arg2); else Primitive_Error(ERR_ARG_1_BAD_RANGE); } \f /* (NON_MARKED_VECTOR_CONS LENGTH) [Primitive number 0x31] Creates a non-marked vector of the specified LENGTH. The contents of such a vector are not seen by the garbage collector. There are no ordinary operations which can be performed on non-marked vectors, but the SYS_VECTOR operations can be used with care. [This primitive appears to be a relic of days gone by.] */ Built_In_Primitive(Prim_Non_Marked_Vector_Cons, 1, "NON-MARKED-VECTOR-CONS") { long Length; Primitive_1_Arg(); Arg_1_Type(TC_FIXNUM); Length = Get_Integer(Arg1); Primitive_GC_If_Needed(Free+Length+1); *Free = Make_Non_Pointer(TC_MANIFEST_NM_VECTOR, Length); Free += Length+1; return Make_Pointer(TC_NON_MARKED_VECTOR, Free-(Length+1)); } Built_In_Primitive(Prim_System_Clock, 0, "SYSTEM-CLOCK") { Primitive_0_Args(); return FIXNUM_0 + System_Clock(); } Built_In_Primitive(Prim_Number_Of_Columns, 0, "NUMBER-OF-COLUMNS") { Primitive_0_Args(); return FIXNUM_0 + NColumns(); } Built_In_Primitive(Prim_Number_Of_Lines, 0, "NUMBER-OF-LINES") { Primitive_0_Args(); return FIXNUM_0 + NLines(); } Built_In_Primitive(Prim_Clear_Screen, 0, "CLEAR-SCREEN") { Primitive_0_Args(); OS_Clear_Screen(); return NIL; } Built_In_Primitive(Prim_Restartable_Exit, 0, "RESTARTABLE-EXIT") { Primitive_0_Args(); Restartable_Exit(); return TRUTH; } \f /* (PRIMITIVE_DATUM OBJECT) [Primitive number 0xB0] Returns the address part of OBJECT. */ Built_In_Primitive(Prim_Primitive_Datum, 1, "PRIMITIVE-DATUM") { Primitive_1_Arg(); return Make_New_Pointer(TC_ADDRESS, Arg1); } /* (SET_RUN_LIGHT OBJECT) [Primitive number 0xC0] On the HP9836, allows the character displayed in the lower right-hand part of the screen to be changed. In CScheme, rings the bell. Used only by GC to indicate that it has started and ended. */ Built_In_Primitive(Prim_Set_Run_Light, 1, "SET-RUN-LIGHT!") { Primitive_1_Arg(); #ifdef BELL OS_Put_C(BELL, stdout); OS_Flush_Output_Buffer(); #endif return NIL; } \f /* (UNDANGERIZE OBJECT) [Primitive number 0x47] Returns OBJECT with the danger bit cleared. This does not side-effect the object, it merely returns a new (non-dangerous) pointer to the same item. */ Built_In_Primitive(Prim_Undangerize, 1, "UNDANGERIZE") { Primitive_1_Arg(); return Clear_Danger_Bit(Arg1); } \f /* Implementation of the CELL object */ /* (MAKE-CELL CONTENTS) [Primitive number 0x61] Creates a cell with contents CONTENTS. */ Built_In_Primitive(Prim_Make_Cell, 1, "MAKE-CELL") { Primitive_1_Arg(); Primitive_GC_If_Needed(Free+1); *Free++ = Arg1; return Make_Pointer(TC_CELL, Free-1); } /* (CONTENTS CELL) [Primitive number 0x62] Returns the contents of the cell CELL. */ Built_In_Primitive(Prim_Cell_Contents, 1, "CONTENTS") { Primitive_1_Arg(); Arg_1_Type(TC_CELL); return(Vector_Ref(Arg1, CELL_CONTENTS)); } /* (CELL? OBJECT) [Primitive number 0x63] Returns #!TRUE if OBJECT has type-code CELL, otherwise returns NIL. */ Built_In_Primitive(Prim_Cell, 1,"CELL?") { Primitive_1_Arg(); Touch_In_Primitive(Arg1,Arg1); return (Type_Code(Arg1 == TC_CELL)) ? TRUTH : NIL; } /* (SET-CONTENTS! CELL VALUE) [Primitive number 0x8C] Stores VALUE as contents of CELL. Returns (bad style to count on this) the previous contents of CELL. */ Built_In_Primitive(Prim_Set_Cell_Contents, 2, "SET-CONTENTS!") { Primitive_2_Args(); Arg_1_Type(TC_CELL); Side_Effect_Impurify(Arg1, Arg2); return Swap_Pointers(Nth_Vector_Loc(Arg1, CELL_CONTENTS), Arg2); }