/* record.c * * $Id$ * * Copyright 1990, 1991, 1992, 1993, 1994, 1995, Oliver Laumann, Berlin * Copyright 2002, 2003 Sam Hocevar , Paris * * This software was derived from Elk 1.2, which was Copyright 1987, 1988, * 1989, Nixdorf Computer AG and TELES GmbH, Berlin (Elk 1.2 has been written * by Oliver Laumann for TELES Telematic Services, Berlin, in a joint project * between TELES and Nixdorf Microprocessor Engineering, Berlin). * * Oliver Laumann, TELES GmbH, Nixdorf Computer AG and Sam Hocevar, as co- * owners or individual owners of copyright in this software, grant to any * person or company a worldwide, royalty free, license to * * i) copy this software, * ii) prepare derivative works based on this software, * iii) distribute copies of this software or derivative works, * iv) perform this software, or * v) display this software, * * provided that this notice is not removed and that neither Oliver Laumann * nor Teles nor Nixdorf are deemed to have made any representations as to * the suitability of this software for any purpose nor are held responsible * for any defects of this software. * * THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. */ #include "config.h" #include "scheme.h" #define RTD(x) ((struct S_Rtd *)POINTER(x)) #define RECORD(x) ((struct S_Record *)POINTER(x)) struct S_Rtd { Object name; Object fields; }; struct S_Record { Object rtd; Object values; }; int T_Rtd, T_Record; static Object P_Rtdp (Object x) { return TYPE(x) == T_Rtd ? True : False; } static Object P_Recordp (Object x) { return TYPE(x) == T_Record ? True : False; } static Object P_Rtd_Name (Object x) { Check_Type (x, T_Rtd); return RTD(x)->name; } static Object P_Rtd_Field_Names (Object x) { Check_Type (x, T_Rtd); return RTD(x)->fields; } static Object P_Make_Record_Type (Object name, Object fields) { Object s, ismem; GC_Node2; if (TYPE(name) == T_Symbol) name = SYMBOL(name)->name; else if (TYPE(name) != T_String) Wrong_Type_Combination (name, "string or symbol"); Check_List (fields); for (s = fields; !Nullp (s); s = Cdr (s)) { Check_Type (Car (s), T_Symbol); ismem = P_Memq (Car (s), Cdr (s)); if (Truep (ismem)) Primitive_Error ("duplicate field name"); } GC_Link2 (name, fields); s = Alloc_Object (sizeof (struct S_Rtd), T_Rtd, 0); RTD(s)->name = name; RTD(s)->fields = fields; GC_Unlink; return s; } static Object P_Record_Type (Object x) { Check_Type (x, T_Record); return RECORD(x)->rtd; } static Object P_Record_Values (Object x) { Check_Type (x, T_Record); return RECORD(x)->values; } static Object P_Make_Record (Object rtd, Object values) { Object s; GC_Node2; Check_Type (rtd, T_Rtd); Check_Type (values, T_Vector); if (VECTOR(values)->size != Fast_Length (RTD(rtd)->fields)) Primitive_Error ("wrong number of fields for record type"); GC_Link2 (rtd, values); s = Alloc_Object (sizeof (struct S_Record), T_Record, 0); RECORD(s)->rtd = rtd; RECORD(s)->values = values; GC_Unlink; return s; } static int Rtd_Eqv (Object a, Object b) { return EQ(a,b); } #define Record_Eqv Rtd_Eqv static int Rtd_Equal (Object a, Object b) { return EQ(RTD(a)->name, RTD(b)->name) && Equal (RTD(a)->fields, RTD(b)->fields); } static int Record_Equal (Object a, Object b) { return EQ(RECORD(a)->rtd, RECORD(b)->rtd) && Equal (RECORD(a)->values, RECORD(b)->values); } static int Rtd_Print (Object x, Object port, int raw, int depth, int length) { struct S_String *s = STRING(RTD(x)->name); Printf (port, "#[%.*s-record-type %lu]", s->size, s->data, POINTER(x)); return 0; } static int Record_Print (Object x, Object port, int raw, int depth, int length) { struct S_String *s = STRING(RTD(RECORD(x)->rtd)->name); Printf (port, "#[%.*s-record-type %lu]", s->size, s->data, POINTER(x)); return 0; } static int Rtd_Visit (register Object *sp, register int (*f)()) { (*f)(&RTD(*sp)->name); (*f)(&RTD(*sp)->fields); return 0; } static int Record_Visit (register Object *sp, register int (*f)()) { (*f)(&RECORD(*sp)->rtd); (*f)(&RECORD(*sp)->values); return 0; } #define Def_Prim Define_Primitive void elk_init_lib_record () { T_Rtd = Define_Type (0, "record-type", NOFUNC, sizeof (struct S_Rtd), Rtd_Eqv, Rtd_Equal, Rtd_Print, Rtd_Visit); Def_Prim (P_Rtdp, "record-type?", 1, 1, EVAL); Def_Prim (P_Rtd_Name, "record-type-name", 1, 1, EVAL); Def_Prim (P_Rtd_Field_Names, "record-type-field-names", 1, 1, EVAL); Def_Prim (P_Make_Record_Type, "make-record-type", 2, 2, EVAL); T_Record = Define_Type (0, "record", NOFUNC, sizeof (struct S_Record), Record_Eqv, Record_Equal, Record_Print, Record_Visit); Def_Prim (P_Recordp, "record?", 1, 1, EVAL); Def_Prim (P_Record_Type, "record-type-descriptor", 1, 1, EVAL); Def_Prim (P_Record_Values, "record-values", 1, 1, EVAL); Def_Prim (P_Make_Record, "make-record", 2, 2, EVAL); P_Provide (Intern ("record.la")); }