records.red 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. module records; % A record package for RLISP using MSTRUCT.
  2. % Author: Bruce Florman.
  3. % Copyright: (c) 1989 The RAND Corporation. All rights reserved.
  4. % Revision History:
  5. % 01/26/89 BAF -- Added this file header.
  6. % Sat Apr 24 12:38:32 1993 - Remove non-RLISP'88 functions (first,
  7. % etc.).
  8. % BothTimes Load MSTRUCT;
  9. %-----------------------------------------------------------------------
  10. % RECORD Declaration
  11. %-----------------------------------------------------------------------
  12. Expr PROCEDURE RecordStat();
  13. % RECORD <struct-name>
  14. % { /* <annotation> */ }
  15. % { WITH <field> := <expression> { , <field> := <expression> }... }
  16. % { HAS <option> { , <option> }... } ;
  17. begin scalar f, stat;
  18. f := FlagP('HAS,'DELIM);
  19. Flag('(HAS),'DELIM);
  20. stat := Errorset('(RecordStat1),NIL,nil);
  21. if not f then RemFlag('(HAS),'DELIM);
  22. if errorp stat THEN while cursym!* neq '!*SEMICOL!* do scan()
  23. else return car stat
  24. end;
  25. expr procedure recordstat1();
  26. begin scalar structname, annotation, fields, options;
  27. structname := Scan();
  28. if not idp structname then symerr('RECORD, T);
  29. if eqcar(scan(), '!*COMMENT!*) then
  30. <<annotation := cadr cursym!*; Scan()>>;
  31. if cursym!* eq 'WITH then fields := remcomma xread nil;
  32. if cursym!* eq 'HAS then options := remcomma xread NIL;
  33. if cursym!* eq '!*SEMICOL!* then
  34. return {'RECORD, structname, annotation, fields, options}
  35. else symerr('RECORD, T)
  36. END;
  37. Put('RECORD,'STAT,'RecordStat);
  38. expr procedure formrecord(u, vars, mode);
  39. apply(form_function, cdr u)
  40. where form_function =
  41. function(lambda(record_name, annotation, fields, options);
  42. begin scalar structspec, fieldspecs, constructor, form;
  43. structspec := Form_structure_specification(record_name, options);
  44. fieldspecs := Form_field_specifications(fields);
  45. constructor := Cdr Atsoc('CONSTRUCTOR,
  46. Get_defstruct_options structspec);
  47. form := {NIL};
  48. tconc(form, 'PROGN);
  49. if constructor then
  50. << tconc(form,
  51. {'put, mkquote constructor,
  52. '(QUOTE FORMFN),
  53. '(QUOTE FORM_RECORD_CONSTRUCTOR)});
  54. put(constructor, 'FORMFN, 'FORM_RECORD_CONSTRUCTOR) >>;
  55. if annotation then
  56. tconc(form, {'PUT, mkquote record_name,
  57. '(QUOTE ANNOTATION),
  58. annotation});
  59. tconc(form, 'DEFSTRUCT . structspec . fieldspecs);
  60. return Car form
  61. end);
  62. Put('RECORD, 'FORMFN, 'FormRecord);
  63. expr procedure tconc(ptr,elem);
  64. % ACONC with pointer to end of list. Ptr is (list . last CDR of
  65. % list). Returns updated Ptr. Ptr should be initialized to
  66. % (NIL . NIL) before calling the first time.
  67. <<elem := list elem;
  68. if not pairp ptr then elem . elem
  69. else if null cdr ptr then rplaca(rplacd(ptr,elem),elem)
  70. else <<rplacd(cdr ptr,elem); rplacd(ptr,elem)>>>>;
  71. expr procedure Form_structure_specification(record_name, options);
  72. append(defaults,
  73. for each entry in options
  74. collect if atom entry then entry
  75. else if eqcar(entry, 'NO) and length entry=2 then
  76. {cadr entry, NIL}
  77. else if car entry eq 'EQUAL and length entry=3 then
  78. {cadr entry, caddr entry}
  79. else error(0, {"Bad RECORD option:", entry}))
  80. where defaults = {record_name,{'CONSTRUCTOR, record_name},
  81. 'predicate};
  82. expr procedure form_field_specifications field_list;
  83. for each entry in field_list
  84. join
  85. if eqcar(entry, 'SETQ)
  86. then {{cadr(entry), form1(caddr entry, NIL, 'SYMBOLIC)}}
  87. else nil;
  88. expr procedure form_record_constructor(u, vars, mode);
  89. begin scalar constructor, arglist;
  90. constructor := car u;
  91. arglist := {NIL};
  92. for each arg in cdr u
  93. do if eqcar(arg, 'SETQ) then
  94. << tconc(arglist, cadr arg);
  95. tconc(arglist, form1(caddr arg, vars, mode)) >>
  96. else rederr {arg, "is not a proper initialization form for",
  97. constructor};
  98. return constructor . car arglist;
  99. end;
  100. endmodule;
  101. end;