2 # A big, ugly file that generates a bigger, uglier C file to generate the
3 # primitive words for accessing the variously sized bits of memory that are
4 # needed in order to talk across the FFI with C structs.
6 # TODO: Handling for types larger than a cell. See pez.c's SIZE_FUNCS macro.
8 variable funcs "" funcs !
9 variable decls "" decls !
16 variable #funcs 0 #funcs !
20 "\t*([^\t\n]+)(\t*|$)" 0 regex constant tabtok-rx
21 : tabtok ( str -- str+n word|0 )
24 dup $1 rot substr ( str word )
25 swap $2 nip + ( word str+n )
29 "\t" swap s+ "\n" s+ s+ ;
33 funcs @ swap s+ funcs ! ;
35 : add-decl ( suffix -- )
36 "{\"0" pezname @ s+ swap s+ "\", " s+ fname @ s+ "},\n" s+
37 decls @ swap s+ decls ! ;
39 : fn-prelude ( -- prelude )
40 "prim " fname @ s+ "(pez_instance *p)\n{\n" s+ ;
43 "P_" cname @ s+ "_at" s+ fname !
52 "\tRealpush(*(" s+ ctype @ s+ " *)S0);\n" s+
55 "\tS0 = *(" s+ ctype @ s+ " *)S0;\n}\n\n" s+
61 "P_" cname @ s+ "_bang" s+ fname !
69 "\t*(" s+ ctype @ s+ " *)S0 = (" s+ ctype @ s+ ")REAL0;\n" s+
70 "\tPop;\n\tRealpop;\n}\n\n" s+
74 "\t*(" s+ ctype @ s+ " *)S0 = (" s+ ctype @ s+ ")S1;\n" s+
75 "\tNpop(2);\n}\n\n" s+
80 "P_" cname @ s+ "_size" s+ fname !
85 "\tPush = sizeof(" s+ ctype @ s+ ");\n}\n\n" s+
89 "P_" cname @ s+ "s" s+ fname !
94 "\tS0 *= sizeof(" s+ ctype @ s+ ");\n}\n\n" s+
97 # If you're reading along, be careful, because it's about to get uglier.
98 : struct-member ( -- )
99 "P_" cname @ s+ "_colon" s+ fname !
102 "pez_dictword *offsetw = (pez_dictword *)p->hptr, *w;" fl
103 "pez_stackitem plus;" fl
104 "int namelen, token;" fl
105 "char *name, *buf;" fl
107 "if(!p->createstruct) {" fl
108 "\ttrouble(p, \"Tried to define struct member outside struct \"" fl
109 "\t\t\"definition\");" fl
112 "plus = (pez_stackitem)lookup(p, \"+\");" fl
114 "name = alloc(TOK_BUF_SZ);" fl
115 "token = lex(p, &p->instream, name);" fl
116 "if(token != TokWord) {" fl
117 "\ttrouble(p, \"Expected a word to follow '" pezname @ s+
121 "namelen = strlen(name);" fl
123 "// ( struct-addr -- member-addr ) The offset-adder:" fl
125 "p->hptr += Dictwordl;" fl
126 "buf = alloc(namelen + 2);" fl
127 "memcpy(buf + 1, name, namelen);" fl
128 "offsetw->wname = buf;" fl
129 "offsetw->wcode = P_nest;" fl
130 "offsetw->wnext = p->dict;" fl
131 "p->dict = offsetw;" fl
132 "if(p->createstruct->size) { // No point in adding zero." fl
133 "\tHsingle(s_lit);" fl
134 "\tHsingle(p->createstruct->size);" fl
135 "\tHsingle(plus);" fl
137 "Hsingle(s_exit);" fl
140 "// ( struct-addr -- member ) The reader:" fl
142 "buf = alloc(namelen + 3);" fl
143 "sprintf(buf + 1, \"%s@\", name);" fl
144 "w = (pez_dictword *)p->hptr;" fl
145 "p->hptr += Dictwordl;" fl
147 "w->wcode = P_nest;" fl
148 "w->wnext = p->dict;" fl
150 "if(p->createstruct->size) {" fl
151 "\tHsingle(s_lit);" fl
152 "\tHsingle(p->createstruct->size);" fl
153 "\tHsingle(plus);" fl
155 "Hsingle((pez_stackitem)lookup(p, \"" pezname @ s+ "@\"));" s+ fl
156 "Hsingle(s_exit);" fl
159 "// ( val struct-addr -- ) The writer:" fl
161 "w = (pez_dictword *)p->hptr;" fl
162 "p->hptr += Dictwordl;" fl
163 "buf = alloc(namelen + 3);" fl
164 "sprintf(buf + 1, \"%s!\", name);" fl
166 "w->wcode = P_nest;" fl
167 "w->wnext = p->dict;" fl
169 "if(p->createstruct->size) {" fl
170 "\tHsingle(s_lit);" fl
171 "\tHsingle(p->createstruct->size);" fl
172 "\tHsingle(plus);" fl
174 "Hsingle((pez_stackitem)lookup(p, \"" pezname @ s+ "!\"));" s+ fl
175 "Hsingle(s_exit);" fl
178 "// And, finally, we add the size of a " pezname @ s+
179 " to the size of the struct." s+ fl
180 "p->createstruct->size += sizeof(" ctype @ s+ ");" s+ fl
186 : plural-struct-member
187 "P_" cname @ s+ "s_colon" s+ fname !
191 "pez_dictword *w = (pez_dictword *)p->hptr;" fl
192 "pez_stackitem plus;" fl
193 "int namelen, token;" fl
194 "char *name, *buf;" fl
197 "if(!p->createstruct) {" fl
198 "\ttrouble(p, \"Tried to define struct member outside struct \"" fl
199 "\t\t\"definition\");" fl
205 "plus = (pez_stackitem)lookup(p, \"+\");" fl
208 "name = alloc(TOK_BUF_SZ);" fl
209 "token = lex(p, &p->instream, name);" fl
210 "if(token != TokWord) {" fl
211 "\ttrouble(p, \"Expected a word to follow '" pezname @ s+
215 "namelen = strlen(name);" fl
219 "p->hptr += Dictwordl;" fl
220 "buf = alloc(namelen + 2);" fl
221 "memcpy(buf + 1, name, namelen);" fl
223 "w->wcode = P_nest;" fl
224 "w->wnext = p->dict;" fl
226 "if(p->createstruct->size) { // No point in adding zero." fl
227 "\tHsingle(s_lit);" fl
228 "\tHsingle(p->createstruct->size);" fl
229 "\tHsingle(plus);" fl
231 "Hsingle(s_exit);" fl
234 "p->createstruct->size += S0 * sizeof(" ctype @ s+ ");" s+ fl
242 tabtok swap tabtok swap tabtok nip ( ctype pezname cname )
246 dup "float" strcmp 0= swap "double" strcmp 0= or floaty? !
261 : write-file ( str fn -- )
262 o_creat o_wronly or 0666 open
263 dup 0< if drop 1 "Couldn't open file!" die! then
264 >output print output> close drop ;
266 # Figures out what file has the types
268 argc 1 < if "type_names" exit then
271 : type_primitives.c ( -- fn )
272 argc 2 < if "type_primitives.c" exit then
275 types-fn o_rdonly 0 open >input
279 "/* " type_primitives.c s+ "\n" s+
280 " This file has been automatically generated as part of the Pez build\n" s+
281 " process, by typegen.pez. It defines a number of primitive functions\n" s+
282 " that help out with dealing with the variously sized types presented by\n" s+
283 " C, and including them in structs.\n" s+
285 " So editing this file is going to be unhelpful; you'd be better off\n" s+
286 " editing typegen.pez. So that Pez can be built on machines that don't\n" s+
287 " already have Pez, this file is included in the repository and with\n" s+
288 " distribution tarballs.\n" s+
291 "struct primfcn memory_primitives[] = {" s+
293 "{NULL, (pez_wordp)0}\n};" s+
294 type_primitives.c write-file
295 "Generated " print #funcs @ . "functions." puts