summaryrefslogtreecommitdiff
path: root/src/runtime/omisc.r
blob: 4c11678b31c86abd811acab183025450d1485b10 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
/*
 * File: omisc.r
 *  Contents: refresh, size, tabmat, toby, to, llist
 */

"^x - create a refreshed copy of a co-expression."
/*
 * ^x - return an entry block for co-expression x from the refresh block.
 */
operator{1} ^ refresh(x)
   if !is:coexpr(x) then
       runerr(118, x)
   abstract {
      return coexpr
      }

   body {
      register struct b_coexpr *sblkp;

      /*
       * Get a new co-expression stack and initialize.
       */
      Protect(sblkp = alccoexp(), runerr(0));
      sblkp->freshblk = BlkLoc(x)->coexpr.freshblk;
      if (ChkNull(sblkp->freshblk))	/* &main cannot be refreshed */
         runerr(215, x);

      /*
       * Use refresh block to finish initializing the new co-expression.
       */
      co_init(sblkp);
      return coexpr(sblkp);
      }
end


"*x - return size of string or object x."

operator{1} * size(x)
   abstract {
      return integer
      }
   type_case x of {
      string: inline {
         return C_integer StrLen(x);
         }
      list: inline {
         return C_integer BlkLoc(x)->list.size;
         }
      table: inline {
         return C_integer BlkLoc(x)->table.size;
         }
      set: inline {
         return C_integer BlkLoc(x)->set.size;
         }
      cset: inline {
         register word i;

         i = BlkLoc(x)->cset.size;
	 if (i < 0)
	    i = cssize(&x);
         return C_integer i;
         }
      record: inline {
         return C_integer BlkLoc(x)->record.recdesc->proc.nfields;
         }
      coexpr: inline {
         return C_integer BlkLoc(x)->coexpr.size;
         }
      default: {
         /*
          * Try to convert it to a string.
          */
         if !cnv:tmp_string(x) then
            runerr(112, x);	/* no notion of size */
         inline {
	    return C_integer StrLen(x);
            }
         }
      }
end


"=x - tab(match(x)).  Reverses effects if resumed."

operator{*} = tabmat(x)
   /*
    * x must be a string.
    */
   if !cnv:string(x) then
      runerr(103, x)
   abstract {
      return string
      }

   body {
      register word l;
      register char *s1, *s2;
      C_integer i, j;
      /*
       * Make a copy of &pos.
       */
      i = k_pos;

      /*
       * Fail if &subject[&pos:0] is not of sufficient length to contain x.
       */
      j = StrLen(k_subject) - i + 1;
      if (j < StrLen(x))
         fail;

      /*
       * Get pointers to x (s1) and &subject (s2).  Compare them on a byte-wise
       *  basis and fail if s1 doesn't match s2 for *s1 characters.
       */
      s1 = StrLoc(x);
      s2 = StrLoc(k_subject) + i - 1;
      l = StrLen(x);
      while (l-- > 0) {
         if (*s1++ != *s2++)
            fail;
         }

      /*
       * Increment &pos to tab over the matched string and suspend the
       *  matched string.
       */
      l = StrLen(x);
      k_pos += l;
      suspend x;

      /*
       * tabmat has been resumed, restore &pos and fail.
       */
      if (i > StrLen(k_subject) + 1)
         runerr(205, kywd_pos);
      else
         k_pos = i;
      fail;
      }
end


"i to j by k - generate successive values."

operator{*} ... toby(from, to, by)
   /*
    * arguments must be integers.
    */
   if !cnv:C_integer(from) then
      runerr(101, from)
   if !cnv:C_integer(to) then
      runerr(101, to)
   if !cnv:C_integer(by) then
      runerr(101, by)

   abstract {
      return integer
      }

   inline {
      /*
       * by must not be zero.
       */
      if (by == 0) {
         irunerr(211, by);
         errorfail;
         }

      /*
       * Count up or down (depending on relationship of from and to) and
       *  suspend each value in sequence, failing when the limit has been
       *  exceeded.
       */
      if (by > 0)
         for ( ; from <= to; from += by) {
            suspend C_integer from;
            }
      else
         for ( ; from >= to; from += by) {
            suspend C_integer from;
            }
      fail;
      }
end


"i to j - generate successive values."

operator{*} ... to(from, to)
   /*
    * arguments must be integers.
    */
   if !cnv:C_integer(from) then
      runerr(101, from)
   if !cnv:C_integer(to) then
      runerr(101, to)

   abstract {
      return integer
      }

   inline {
      for ( ; from <= to; ++from) {
         suspend C_integer from;
         }
      fail;
      }
end


" [x1, x2, ... ] - create an explicitly specified list."

operator{1} [...] llist(elems[n])
   abstract {
      return new list(type(elems))
      }
   body {
      tended struct b_list *hp;
      register word i;
      register struct b_lelem *bp;  /* need not be tended */
      word nslots;

      nslots = n;
      if (nslots == 0)
         nslots = MinListSlots;

      /*
       * Allocate the list and a list block.
       */
      Protect(hp = alclist(n), runerr(0));
      Protect(bp = alclstb(nslots, (word)0, n), runerr(0));

      /*
       * Make the list block just allocated into the first and last blocks
       *  for the list.
       */
      hp->listhead = hp->listtail = (union block *)bp;

      /*
       * Assign each argument to a list element.
       */
      for (i = 0; i < n; i++)
         bp->lslots[i] = elems[i];

      return list(hp);
      }
end