home *** CD-ROM | disk | FTP | other *** search
/ Dream 52 / Amiga_Dream_52.iso / RiscOS / APP / DEVS / LISP / FOOLS.ZIP / Fools / doc / datatypes. next >
Text File  |  1991-10-31  |  4KB  |  143 lines

  1. extending data types
  2.  
  3. One way to add a new data type to fools' lisp is by extending
  4. existing data types -- for example, extending the number class
  5. to include characters.
  6.  
  7. The print representation of a character is #\* where * is a letter,
  8. digit, or punctuation mark.  #\space, #\newline, and #\tab represent
  9. the space, newline, and tab characters.
  10.  
  11. Often a data type will have creator and accessor routines (for example
  12. delay, force, make-environment, the-environment).  Parsing a new
  13. datatype's print representation may not be worthwhile.
  14.  
  15. The type of an object is stored as a struct.  Each new operation
  16. of the class has a field in the struct for the dispatch function.
  17. objDestroy, for example, calls all the destroy functions for an object
  18. from class to superclass order).  The first entry in the struct is
  19. the struct of the defining class (the superclass).  In this case
  20. numberClass_t is the inherited class for characters.
  21.  
  22. typedef struct charClass_s {
  23.     numberClass_t inherit;
  24.     F_INT code;
  25. } charClass_t, *charClass;
  26.  
  27. #define DEFCHAR(number, code) { number, code }
  28.  
  29. The actual object is a pointer to an instance struct which holds data
  30. specific to a character instance.  Fully encapsulating the number
  31. instance is unnecessary so the basic instance is inherited instead.
  32.  
  33. typedef struct charInst_s {
  34.     basicInst_t inherit;
  35.     char code;
  36. } charInst_t, *charInst;
  37.  
  38. Character is the class variable (a constant value used for type checking).
  39.  
  40. extern charClass_t protoChar;
  41. #define Character ((Class)&protoChar)
  42.  
  43. The class struct is initialized at compile time.  See Basic.h and
  44. Number.h for the layouts of the basic and number class and instance
  45. structs.  The destroy slot is filled with (F_VOID)NULL which means
  46. that a character instance does not need to free anything not already
  47. freed by it's superclass.
  48.  
  49. charClass_t protoChar =
  50.     DEFCHAR(DEFNUMBER(DEFBASIC(&protoNumber, charInst_t, charPrint,
  51.                    (F_VOID)NULL, charType),
  52.               charNumSet, charNum),
  53.         _charCode);
  54.  
  55. The functions objNumSet and objNum dispatch on the type of the object,
  56. so charNumSet and charNum must fit into the type restriction of objNumSet
  57. and objNum.
  58.  
  59. Whether charNumSet should check the range of val is up to you.
  60.  
  61. void charNumSet(ch, val)
  62.     Obj ch;
  63.     double val;
  64. {
  65.     int c;
  66.  
  67.     ASSERT(objIsClass(ch, Character));
  68.     c = (int)val;
  69.     if (c < 0 || c > 255 || c != (int)floor(val))
  70.         errorPrint(BadVal, "%O is not a valid character code", ch);
  71.     DATA(ch, code, charInst) = (char)c;
  72. }
  73.  
  74. double charNum(ch)
  75.     Obj ch;
  76. {
  77.     ASSERT(objIsClass(ch, Character));
  78.     return (double)DATA(ch, code, charInst);
  79. }
  80.     
  81. The printing routine is a basic function that also needs to be replaced.
  82.  
  83. static void charPrint(ch, f)
  84.     Obj ch;
  85.     FILE *f;
  86. {
  87.     char c;
  88.  
  89.     c = DATA(ch, code, charInst);
  90.     if (isprint(c))
  91.         (void)fprintf(f, "#\\%c", c);
  92.     else switch(c) {
  93.         case '\n':
  94.             (void)fputs("#\\newline", f);
  95.             break ;
  96.         case '\t':
  97.             (void)fputs("#\\tab", f);
  98.             break ;
  99.         default:
  100.             (void)fprintf(f, "#\\%.3o", c);
  101.             break ;
  102.     }
  103. }
  104.  
  105. The type function must be defined for all classes and returns a symbol
  106. corresponding to the type of the object.  objIntern returns the unique
  107. symbol representing its string argument.
  108.  
  109. static Obj charType()
  110. {
  111.     return objIntern("char");
  112. }
  113.  
  114. charCode is a generic dispatching routine.
  115.  
  116. int charCode(ch)
  117.     Obj ch;
  118. {
  119.     ASSERT(objIsClass(ch, Character));
  120.     return PROC(ch, code, charClass)(ch);
  121. }
  122.  
  123. This is the function called by charCode for Character objects:
  124.  
  125. static int _charCode(ch)
  126.     Obj ch;
  127. {
  128.     return DATA(ch, code, charInst);
  129. }
  130.  
  131. A constructor is also helpful.
  132.  
  133. Obj newChar(alloc, ch)
  134.     F_OBJ alloc;
  135.     char ch;
  136. {
  137.     Obj new;
  138.  
  139.     new = (*alloc)(Character);
  140.     DATA(new, code, charInst) = ch;
  141.     return new;
  142. }
  143.