PageRenderTime 54ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/protobuf/compile/codegen.scm

http://r6rs-protobuf.googlecode.com/
Scheme | 793 lines | 685 code | 95 blank | 13 comment | 0 complexity | c29de964aab935a0d5e5ac2e7f425626 MD5 | raw file
Possible License(s): GPL-3.0
  1. ;; codegen.scm: code generation API for r6rs-protobuf
  2. ;; Copyright (C) 2011 Julian Graham
  3. ;; r6rs-protobuf is free software: you can redistribute it and/or modify
  4. ;; it under the terms of the GNU General Public License as published by
  5. ;; the Free Software Foundation, either version 3 of the License, or
  6. ;; (at your option) any later version.
  7. ;; This program is distributed in the hope that it will be useful,
  8. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. ;; GNU General Public License for more details.
  11. ;; You should have received a copy of the GNU General Public License
  12. ;; along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. #!r6rs
  14. (library (protobuf compile codegen)
  15. (export protoc:default-naming-context
  16. protoc:make-naming-context
  17. protoc:naming-context?
  18. protoc:naming-context-enum-naming-context
  19. protoc:generate-package
  20. protoc:generate-message
  21. protoc:generate-enum
  22. protoc:generate-extension
  23. protoc:generate-builder)
  24. (import (rnrs)
  25. (protobuf compile parse)
  26. (protobuf private)
  27. (srfi :13)
  28. (srfi :14))
  29. (define-record-type (protoc:extension-naming-context
  30. protoc:make-extension-naming-context
  31. protoc:extension-naming-context?)
  32. (fields extension-name))
  33. (define-record-type (protoc:enum-naming-context
  34. protoc:make-enum-naming-context
  35. protoc:eum-naming-context?)
  36. (fields type-name constructor-name predicate-name value-name))
  37. (define-record-type (protoc:message-naming-context
  38. protoc:make-message-naming-context
  39. protoc:message-naming-context?)
  40. (fields type-name
  41. predicate-name
  42. field-accessor-name
  43. field-has-name
  44. extension-accessor-name
  45. extension-has-name
  46. writer-name
  47. reader-name))
  48. (define-record-type (protoc:builder-naming-context
  49. protoc:make-builder-naming-context
  50. protoc:builder-naming-context?)
  51. (fields type-name
  52. constructor-name
  53. predicate-name
  54. field-accessor-name
  55. field-mutator-name
  56. field-clear-name
  57. field-has-name
  58. extension-accessor-name
  59. extension-mutator-name
  60. extension-clear-name
  61. extension-has-name
  62. build-name))
  63. (define-record-type (protoc:naming-context
  64. protoc:make-naming-context
  65. protoc:naming-context?)
  66. (fields library-name
  67. enum-naming-context
  68. message-naming-context
  69. builder-naming-context
  70. extension-naming-context))
  71. (define default-package-name "protobuf.default")
  72. (define (gensym-values . vars)
  73. (apply values (syntax->datum (generate-temporaries vars))))
  74. (define (protoc:default-package-name-transformer package)
  75. (map string->symbol
  76. (string-tokenize package (char-set-complement (char-set #\.)))))
  77. (define (type-name-recursive def)
  78. (define (type-name-recursive-inner def suffix)
  79. (cond ((protoc:message-definition? def)
  80. (if (protoc:message-definition-parent def)
  81. (type-name-recursive-inner
  82. (protoc:message-definition-parent def)
  83. (string-append
  84. "-" (protoc:message-definition-name def) suffix))
  85. (string-append (protoc:message-definition-name def) suffix)))
  86. ((protoc:enum-definition? def)
  87. (if (protoc:enum-definition-parent def)
  88. (type-name-recursive-inner
  89. (protoc:enum-definition-parent def)
  90. (string-append "-" (protoc:enum-definition-name def) suffix))
  91. (string-append (protoc:enum-definition-name def) suffix)))
  92. (else (raise (make-assertion-violation)))))
  93. (type-name-recursive-inner def ""))
  94. (define protoc:default-enum-naming-context
  95. (protoc:make-enum-naming-context
  96. (lambda (enum) (string->symbol (type-name-recursive enum)))
  97. (lambda (enum)
  98. (string->symbol (string-append "make-" (type-name-recursive enum))))
  99. (lambda (enum)
  100. (string->symbol (string-append (type-name-recursive enum) "?")))
  101. (lambda (enum value)
  102. (string->symbol
  103. (string-append (type-name-recursive enum) "-"
  104. (protoc:enum-value-definition-name value))))))
  105. (define (default-message-builder-name message)
  106. (string-append (type-name-recursive message) "-builder"))
  107. (define protoc:default-message-naming-context
  108. (protoc:make-message-naming-context
  109. (lambda (message)
  110. (string->symbol (type-name-recursive message)))
  111. (lambda (message)
  112. (string->symbol
  113. (string-append (type-name-recursive message) "?")))
  114. (lambda (message field)
  115. (string->symbol
  116. (string-append (type-name-recursive message) "-"
  117. (protoc:field-definition-name field))))
  118. (lambda (message field)
  119. (string->symbol
  120. (string-append "has-" (type-name-recursive message) "-"
  121. (protoc:field-definition-name field) "?")))
  122. (lambda (message)
  123. (string->symbol
  124. (string-append (type-name-recursive message) "-extension")))
  125. (lambda (message)
  126. (string->symbol
  127. (string-append "has-" (type-name-recursive message) "-extension?")))
  128. (lambda (message)
  129. (string->symbol (string-append (type-name-recursive message) "-write")))
  130. (lambda (message)
  131. (string->symbol (string-append (type-name-recursive message) "-read")))))
  132. (define protoc:default-builder-naming-context
  133. (protoc:make-builder-naming-context
  134. (lambda (message) (string->symbol (default-message-builder-name message)))
  135. (lambda (message)
  136. (string->symbol
  137. (string-append "make-" (default-message-builder-name message))))
  138. (lambda (message)
  139. (string->symbol
  140. (string-append (default-message-builder-name message) "?")))
  141. (lambda (message field)
  142. (string->symbol
  143. (string-append (default-message-builder-name message) "-"
  144. (protoc:field-definition-name field))))
  145. (lambda (message field)
  146. (string->symbol
  147. (string-append "set-" (default-message-builder-name message) "-"
  148. (protoc:field-definition-name field) "!")))
  149. (lambda (message field)
  150. (string->symbol
  151. (string-append "clear-" (default-message-builder-name message) "-"
  152. (protoc:field-definition-name field) "!")))
  153. (lambda (message field)
  154. (string->symbol
  155. (string-append "has-" (default-message-builder-name message) "-"
  156. (protoc:field-definition-name field) "?")))
  157. (lambda (message)
  158. (string->symbol
  159. (string-append (default-message-builder-name message) "-extension")))
  160. (lambda (message)
  161. (string->symbol
  162. (string-append "set-" (default-message-builder-name message) "-"
  163. "extension!")))
  164. (lambda (message)
  165. (string->symbol
  166. (string-append "clear-" (default-message-builder-name message) "-"
  167. "extension!")))
  168. (lambda (message)
  169. (string->symbol
  170. (string-append "has-" (default-message-builder-name message) "-"
  171. "extension?")))
  172. (lambda (message)
  173. (string->symbol
  174. (string-append (default-message-builder-name message) "-build")))))
  175. (define protoc:default-extension-naming-context
  176. (protoc:make-extension-naming-context
  177. (lambda (extension field)
  178. (string->symbol
  179. (string-append (type-name-recursive
  180. (protobuf:message-field-type-descriptor-definition
  181. (protoc:type-reference-descriptor
  182. (protoc:extension-definition-target extension))))
  183. "-" (protoc:field-definition-name field))))))
  184. (define protoc:default-naming-context
  185. (protoc:make-naming-context protoc:default-package-name-transformer
  186. protoc:default-enum-naming-context
  187. protoc:default-message-naming-context
  188. protoc:default-builder-naming-context
  189. protoc:default-extension-naming-context))
  190. (define default-imports
  191. '((rnrs base) (rnrs enums) (rnrs records syntactic) (protobuf private)))
  192. (define (protoc:generate-package package naming-context)
  193. (define enum-naming-context
  194. (protoc:naming-context-enum-naming-context naming-context))
  195. (define message-naming-context
  196. (protoc:naming-context-message-naming-context naming-context))
  197. (define builder-naming-context
  198. (protoc:naming-context-builder-naming-context naming-context))
  199. (define extension-naming-context
  200. (protoc:naming-context-extension-naming-context naming-context))
  201. (define (generate-definition definition)
  202. (cond ((protoc:message-definition? definition)
  203. (append
  204. (protoc:generate-message definition naming-context)
  205. (protoc:generate-builder definition naming-context)
  206. (apply append
  207. (map generate-definition
  208. (protoc:message-definition-definitions definition)))))
  209. ((protoc:enum-definition? definition)
  210. (protoc:generate-enum definition enum-naming-context))
  211. ((protoc:extension-definition? definition)
  212. (protoc:generate-extension definition naming-context))
  213. (else '())))
  214. `(library ,((protoc:naming-context-library-name naming-context)
  215. (or (protoc:package-name package) default-package-name))
  216. (export ,@(protoc:package-exports package naming-context))
  217. (import
  218. ,@(append default-imports
  219. (map (lambda (p)
  220. ((protoc:naming-context-library-name naming-context)
  221. (or (protoc:package-name p) default-package-name)))
  222. (protoc:package-required-packages package))))
  223. ,@(let loop ((definitions
  224. (protoc:package-definitions package))
  225. (output '()))
  226. (if (or (not definitions) (null? definitions))
  227. (reverse output)
  228. (let ((definition (car definitions)))
  229. (loop (cdr definitions)
  230. (append output (generate-definition definition))))))))
  231. (define (protoc:enum-exports enum enum-naming-context)
  232. (list ((protoc:enum-naming-context-type-name enum-naming-context) enum)
  233. ((protoc:enum-naming-context-predicate-name enum-naming-context) enum)
  234. ((protoc:enum-naming-context-constructor-name enum-naming-context)
  235. enum)))
  236. (define (protoc:message-exports message message-naming-context)
  237. (define accessor-name (protoc:message-naming-context-field-accessor-name
  238. message-naming-context))
  239. (define has-name (protoc:message-naming-context-field-has-name
  240. message-naming-context))
  241. (append (list ((protoc:message-naming-context-predicate-name
  242. message-naming-context) message)
  243. ((protoc:message-naming-context-writer-name
  244. message-naming-context) message)
  245. ((protoc:message-naming-context-reader-name
  246. message-naming-context) message)
  247. ((protoc:message-naming-context-extension-accessor-name
  248. message-naming-context) message)
  249. ((protoc:message-naming-context-extension-has-name
  250. message-naming-context) message))
  251. (let loop ((fields (protoc:message-definition-fields message))
  252. (bindings (list)))
  253. (if (null? fields)
  254. (reverse bindings)
  255. (let ((f (car fields)))
  256. (loop (cdr fields)
  257. (cons (accessor-name message f)
  258. (if (eq? (protoc:field-definition-rule f)
  259. 'optional)
  260. (cons (has-name message f) bindings)
  261. bindings))))))))
  262. (define (protoc:builder-exports message builder-naming-context)
  263. (define field-accessor-name
  264. (protoc:builder-naming-context-field-accessor-name
  265. builder-naming-context))
  266. (define field-mutator-name
  267. (protoc:builder-naming-context-field-mutator-name builder-naming-context))
  268. (define field-has-name
  269. (protoc:builder-naming-context-field-has-name builder-naming-context))
  270. (define field-clear-name
  271. (protoc:builder-naming-context-field-clear-name builder-naming-context))
  272. (append (list ((protoc:builder-naming-context-constructor-name
  273. builder-naming-context) message)
  274. ((protoc:builder-naming-context-predicate-name
  275. builder-naming-context) message)
  276. ((protoc:builder-naming-context-build-name
  277. builder-naming-context) message)
  278. ((protoc:builder-naming-context-extension-accessor-name
  279. builder-naming-context) message)
  280. ((protoc:builder-naming-context-extension-mutator-name
  281. builder-naming-context) message)
  282. ((protoc:builder-naming-context-extension-has-name
  283. builder-naming-context) message)
  284. ((protoc:builder-naming-context-extension-clear-name
  285. builder-naming-context) message))
  286. (let loop ((fields (protoc:message-definition-fields message))
  287. (bindings (list)))
  288. (if (null? fields)
  289. (reverse bindings)
  290. (let ((field (car fields)))
  291. (if (eq? (protoc:field-definition-rule field) 'repeated)
  292. (loop (cdr fields)
  293. (append (list (field-accessor-name message field)
  294. (field-mutator-name message field)
  295. (field-clear-name message field))))
  296. (loop (cdr fields)
  297. (append (list (field-accessor-name message field)
  298. (field-mutator-name message field)
  299. (field-has-name message field)
  300. (field-clear-name message field))
  301. bindings))))))))
  302. (define (protoc:extension-exports extension extension-naming-context)
  303. (define extension-name
  304. (protoc:extension-naming-context-extension-name
  305. extension-naming-context))
  306. (map (lambda (field) (extension-name extension field))
  307. (protoc:extension-definition-fields extension)))
  308. (define (protoc:package-exports package naming-context)
  309. (define enum-naming-context
  310. (protoc:naming-context-enum-naming-context naming-context))
  311. (define message-naming-context
  312. (protoc:naming-context-message-naming-context naming-context))
  313. (define builder-naming-context
  314. (protoc:naming-context-builder-naming-context naming-context))
  315. (define extension-naming-context
  316. (protoc:naming-context-extension-naming-context naming-context))
  317. (define (generate-export definition)
  318. (cond ((protoc:message-definition? definition)
  319. (append
  320. (protoc:message-exports definition message-naming-context)
  321. (protoc:builder-exports definition builder-naming-context)
  322. (apply append
  323. (map generate-export
  324. (protoc:message-definition-definitions definition)))))
  325. ((protoc:enum-definition? definition)
  326. (protoc:enum-exports definition enum-naming-context))
  327. ((protoc:extension-definition? definition)
  328. (protoc:extension-exports definition extension-naming-context))
  329. (else '())))
  330. (let loop ((definitions (protoc:package-definitions package))
  331. (output '()))
  332. (if (or (not definitions) (null? definitions))
  333. (reverse output)
  334. (let ((definition (car definitions)))
  335. (loop (cdr definitions)
  336. (append output (generate-export definition)))))))
  337. (define (protoc:generate-enum enum enum-naming-context)
  338. (define enum-predicate-name
  339. (protoc:enum-naming-context-predicate-name enum-naming-context))
  340. (define enum-type-name
  341. (protoc:enum-naming-context-type-name enum-naming-context))
  342. (define enum-constructor-name
  343. (protoc:enum-naming-context-constructor-name enum-naming-context))
  344. (define enum-value-name
  345. (protoc:enum-naming-context-value-name enum-naming-context))
  346. (let-values (((e0 e1) (gensym-values 'e0 'e1)))
  347. (let ((values (map (lambda (value) (enum-value-name enum value))
  348. (protoc:enum-definition-values enum))))
  349. `((define-enumeration ,(enum-type-name enum)
  350. ,values ,(enum-constructor-name enum))
  351. (define ,e1 (make-enumeration ,(list 'quote values)))
  352. (define (,(enum-predicate-name enum) ,e0)
  353. (enum-set-member? ,e0 ,e1))))))
  354. (define (protoc:generate-message message naming-context)
  355. (define message-naming-context
  356. (protoc:naming-context-message-naming-context naming-context))
  357. (define builder-naming-context
  358. (protoc:naming-context-builder-naming-context naming-context))
  359. (define message-type-name
  360. (protoc:message-naming-context-type-name message-naming-context))
  361. (define builder-constructor-name
  362. (protoc:builder-naming-context-constructor-name builder-naming-context))
  363. (define field-accessor-name
  364. (protoc:message-naming-context-field-accessor-name
  365. message-naming-context))
  366. (define field-has-name
  367. (protoc:message-naming-context-field-has-name message-naming-context))
  368. (define extension-accessor-name
  369. (protoc:message-naming-context-extension-accessor-name
  370. message-naming-context))
  371. (define extension-has-name
  372. (protoc:message-naming-context-extension-has-name message-naming-context))
  373. (define message-writer-name
  374. (protoc:message-naming-context-writer-name message-naming-context))
  375. (define message-reader-name
  376. (protoc:message-naming-context-reader-name message-naming-context))
  377. (define (generate-field-has-predicate message field)
  378. (let-values (((m0) (gensym-values 'm0)))
  379. `(define (,(field-has-name message field) ,m0)
  380. (protobuf:field-has-value?
  381. (protobuf:message-field
  382. ,m0 ,(protoc:field-definition-ordinal field))))))
  383. (let-values (((e0 e1 w0 w1 r0) (gensym-values 'e0 'e1 'w0 'w1 'r0)))
  384. `((define-record-type ,(message-type-name message)
  385. (fields ,@(let ((fields (protoc:message-definition-fields message)))
  386. (if fields
  387. (map (lambda (field)
  388. (list 'immutable
  389. (string->symbol
  390. (protoc:field-definition-name field))
  391. (field-accessor-name message field)))
  392. fields)
  393. '())))
  394. (opaque #t)
  395. (parent protobuf:message)
  396. (sealed #t))
  397. ,@(let loop ((fields (protoc:message-definition-fields message))
  398. (bindings (list)))
  399. (if (null? fields)
  400. (reverse bindings)
  401. (let ((f (car fields)))
  402. (if (eq? (protoc:field-definition-rule f) 'optional)
  403. (loop (cdr fields)
  404. (cons (generate-field-has-predicate message f)
  405. bindings))
  406. (loop (cdr fields) bindings)))))
  407. (define (,(extension-accessor-name message) ,e0 ,e1)
  408. (protobuf:message-extension ,e0 ,(message-type-name message) ,e1))
  409. (define (,(extension-has-name message) ,e0 ,e1)
  410. (protobuf:message-has-extension?
  411. ,e0 ,(message-type-name message) ,e1))
  412. (define (,(message-writer-name message) ,w0 ,w1)
  413. (protobuf:message-write ,w0 ,w1))
  414. (define (,(message-reader-name message) ,r0)
  415. (protobuf:message-read (,(builder-constructor-name message)) ,r0)))))
  416. (define (calc-field-default field enum-naming-context)
  417. (define enum-type-name
  418. (protoc:enum-naming-context-type-name enum-naming-context))
  419. (define enum-value-name
  420. (protoc:enum-naming-context-value-name enum-naming-context))
  421. (define (find-enum-value enum value-name)
  422. (find (lambda (value)
  423. (equal? (protoc:enum-value-definition-name value) value-name))
  424. (protoc:enum-definition-values enum)))
  425. (define (option-default? option)
  426. (eq? (protoc:option-declaration-name option) 'default))
  427. (define options (protoc:field-definition-options field))
  428. (define type-descriptor
  429. (protoc:type-reference-descriptor (protoc:field-definition-type field)))
  430. (cond ((eq? (protoc:field-definition-rule field) 'repeated) (quote '()))
  431. ((and options (find option-default? options)) =>
  432. (lambda (option)
  433. (let ((value (protoc:option-declaration-value option)))
  434. (cond ((protobuf:enum-field-type-descriptor? type-descriptor)
  435. (let* ((enum
  436. (protobuf:enum-field-type-descriptor-definition
  437. type-descriptor))
  438. (enum-value (find-enum-value enum value)))
  439. (if (not enum-value)
  440. (raise (condition
  441. (make-assertion-violation)
  442. (make-message-condition
  443. "Incompatible default value"))))
  444. (list (enum-type-name enum)
  445. (enum-value-name enum enum-value))))
  446. ((protobuf:field-type-descriptor-predicate type-descriptor)
  447. value)
  448. (list 'quote value)
  449. (else (raise (condition
  450. (make-assertion-violation)
  451. (make-message-condition
  452. "Incompatible default value"))))))))
  453. (else (if (protobuf:enum-field-type-descriptor? type-descriptor)
  454. (let* ((enum (protobuf:enum-field-type-descriptor-definition
  455. type-descriptor))
  456. (value (car (protoc:enum-definition-values enum))))
  457. (list (enum-type-name enum) (enum-value-name enum value)))
  458. (protobuf:field-type-descriptor-default type-descriptor)))))
  459. (define (type-reference->type-descriptor-expr type-ref naming-context)
  460. (define builder-naming-context
  461. (protoc:naming-context-builder-naming-context naming-context))
  462. (define enum-naming-context
  463. (protoc:naming-context-enum-naming-context naming-context))
  464. (define message-naming-context
  465. (protoc:naming-context-message-naming-context naming-context))
  466. (define builder-constructor-name
  467. (protoc:builder-naming-context-constructor-name builder-naming-context))
  468. (define enum-predicate-name
  469. (protoc:enum-naming-context-predicate-name enum-naming-context))
  470. (define message-predicate-name
  471. (protoc:message-naming-context-predicate-name message-naming-context))
  472. (define p0 (gensym-values 'p0))
  473. (define (message-field-type-descriptor-expr descriptor)
  474. `(protobuf:make-message-field-type-descriptor
  475. ,(protobuf:field-type-descriptor-name descriptor)
  476. ,(list 'quote (protobuf:field-type-descriptor-wire-type descriptor))
  477. protobuf:write-message
  478. (lambda (,p0)
  479. (protobuf:message-read
  480. (,(builder-constructor-name
  481. (protobuf:message-field-type-descriptor-definition descriptor)))
  482. ,p0))
  483. ,(message-predicate-name
  484. (protobuf:message-field-type-descriptor-definition descriptor))
  485. ,(protobuf:field-type-descriptor-default descriptor)))
  486. (define (enum-field-type-descriptor-expr descriptor)
  487. `(protobuf:make-enum-field-type-descriptor
  488. ,(protobuf:field-type-descriptor-name descriptor)
  489. ,(list 'quote (protobuf:field-type-descriptor-wire-type descriptor))
  490. protobuf:write-varint
  491. protobuf:read-varint
  492. ,(enum-predicate-name
  493. (protobuf:enum-field-type-descriptor-definition descriptor))
  494. ,(protobuf:field-type-descriptor-default descriptor)))
  495. (let ((descriptor (protoc:type-reference-descriptor type-ref)))
  496. (cond
  497. ((eq? descriptor protobuf:field-type-double)
  498. 'protobuf:field-type-double)
  499. ((eq? descriptor protobuf:field-type-float)
  500. 'protobuf:field-type-float)
  501. ((eq? descriptor protobuf:field-type-int32)
  502. 'protobuf:field-type-int32)
  503. ((eq? descriptor protobuf:field-type-int64)
  504. 'protobuf:field-type-int64)
  505. ((eq? descriptor protobuf:field-type-uint32)
  506. 'protobuf:field-type-uint32)
  507. ((eq? descriptor protobuf:field-type-uint64)
  508. 'protobuf:field-type-uint64)
  509. ((eq? descriptor protobuf:field-type-sint32)
  510. 'protobuf:field-type-sint32)
  511. ((eq? descriptor protobuf:field-type-sint64)
  512. 'protobuf:field-type-sint64)
  513. ((eq? descriptor protobuf:field-type-fixed32)
  514. 'protobuf:field-type-fixed32)
  515. ((eq? descriptor protobuf:field-type-fixed64)
  516. 'protobuf:field-type-sfixed32)
  517. ((eq? descriptor protobuf:field-type-sfixed32)
  518. 'protobuf:field-type-sfixed32)
  519. ((eq? descriptor protobuf:field-type-sfixed64)
  520. 'protobuf:field-type-sfixed64)
  521. ((eq? descriptor protobuf:field-type-bool)
  522. 'protobuf:field-type-bool)
  523. ((eq? descriptor protobuf:field-type-string)
  524. 'protobuf:field-type-string)
  525. ((eq? descriptor protobuf:field-type-bytes)
  526. 'protobuf:field-type-bytes)
  527. ;; It must be a user-defined type
  528. ((protobuf:message-field-type-descriptor? descriptor)
  529. (message-field-type-descriptor-expr descriptor))
  530. ((protobuf:enum-field-type-descriptor? descriptor)
  531. (enum-field-type-descriptor-expr descriptor))
  532. (else (raise (make-assertion-violation))))))
  533. (define (protoc:generate-extension extension naming-context)
  534. (define builder-naming-context
  535. (protoc:naming-context-builder-naming-context naming-context))
  536. (define enum-naming-context
  537. (protoc:naming-context-enum-naming-context naming-context))
  538. (define extension-naming-context
  539. (protoc:naming-context-extension-naming-context naming-context))
  540. (define builder-constructor-name
  541. (protoc:builder-naming-context-constructor-name builder-naming-context))
  542. (define extension-name
  543. (protoc:extension-naming-context-extension-name extension-naming-context))
  544. (define (define-extension extension-field)
  545. `(define ,(extension-name extension extension-field)
  546. (protobuf:make-extension-field-descriptor
  547. ,(protoc:field-definition-ordinal extension-field)
  548. ,(protoc:field-definition-name extension-field)
  549. ,(type-reference->type-descriptor-expr
  550. (protoc:field-definition-type extension-field) naming-context)
  551. ,(eq? (protoc:field-definition-rule extension-field) 'repeated)
  552. ,(eq? (protoc:field-definition-rule extension-field) 'required)
  553. ,(calc-field-default extension-field enum-naming-context))))
  554. (define (make-extension-registrar prototype-binding)
  555. (lambda (extension-field)
  556. `(protobuf:register-extension
  557. ,prototype-binding ,(extension-name extension extension-field))))
  558. (let ((fields (protoc:extension-definition-fields extension)))
  559. (append
  560. (if (null? fields)
  561. '()
  562. (let-values (((e0) (gensym-values 'e0)))
  563. `((let ((,e0 (,(builder-constructor-name
  564. (protobuf:message-field-type-descriptor-definition
  565. (protoc:type-reference-descriptor
  566. (protoc:extension-definition-target
  567. extension)))))))
  568. ,@(map (make-extension-registrar e0) fields)))))
  569. (map define-extension fields))))
  570. (define (protoc:generate-builder message naming-context)
  571. (define enum-naming-context
  572. (protoc:naming-context-enum-naming-context naming-context))
  573. (define message-naming-context
  574. (protoc:naming-context-message-naming-context naming-context))
  575. (define builder-naming-context
  576. (protoc:naming-context-builder-naming-context naming-context))
  577. (define message-type-name
  578. (protoc:message-naming-context-type-name message-naming-context))
  579. (define message-predicate-name
  580. (protoc:message-naming-context-predicate-name message-naming-context))
  581. (define builder-type-name
  582. (protoc:builder-naming-context-type-name builder-naming-context))
  583. (define builder-constructor-name
  584. (protoc:builder-naming-context-constructor-name builder-naming-context))
  585. (define builder-predicate-name
  586. (protoc:builder-naming-context-predicate-name builder-naming-context))
  587. (define builder-build-name
  588. (protoc:builder-naming-context-build-name builder-naming-context))
  589. (define field-accessor-name
  590. (protoc:builder-naming-context-field-accessor-name
  591. builder-naming-context))
  592. (define field-mutator-name
  593. (protoc:builder-naming-context-field-mutator-name builder-naming-context))
  594. (define field-has-name
  595. (protoc:builder-naming-context-field-has-name builder-naming-context))
  596. (define field-clear-name
  597. (protoc:builder-naming-context-field-clear-name builder-naming-context))
  598. (define extension-accessor-name
  599. (protoc:builder-naming-context-extension-accessor-name
  600. builder-naming-context))
  601. (define extension-mutator-name
  602. (protoc:builder-naming-context-extension-mutator-name
  603. builder-naming-context))
  604. (define extension-has-name
  605. (protoc:builder-naming-context-extension-has-name builder-naming-context))
  606. (define extension-clear-name
  607. (protoc:builder-naming-context-extension-clear-name
  608. builder-naming-context))
  609. (define field-internal-mutators
  610. (make-hashtable (lambda (f) (protoc:field-definition-ordinal f))
  611. (lambda (f1 f2)
  612. (eqv? (protoc:field-definition-ordinal f1)
  613. (protoc:field-definition-ordinal f2)))))
  614. (define (generate-field-clear message field)
  615. (let-values (((b0) (gensym-values 'b0)))
  616. `(define (,(field-clear-name message field) ,b0)
  617. (protobuf:clear-field!
  618. (protobuf:message-builder-field
  619. ,b0 ,(protoc:field-definition-ordinal field)))
  620. (,(hashtable-ref field-internal-mutators field #f) ,b0
  621. ,(calc-field-default field enum-naming-context)))))
  622. (define (generate-field-has-predicate message field)
  623. (let-values (((b0) (gensym-values 'b0)))
  624. `(define (,(field-has-name message field) ,b0)
  625. (protobuf:field-has-value?
  626. (protobuf:message-builder-field
  627. ,b0 ,(protoc:field-definition-ordinal field))))))
  628. (define (generate-field-mutator message field)
  629. (let-values (((b0 b1) (gensym-values 'b0 'b1)))
  630. `(define (,(field-mutator-name message field) ,b0 ,b1)
  631. (protobuf:set-field-value!
  632. (protobuf:message-builder-field
  633. ,b0 ,(protoc:field-definition-ordinal field)) ,b1)
  634. (,(hashtable-ref field-internal-mutators field #f) ,b0 ,b1))))
  635. (let-values (((b0 b1 b2 b3) (gensym-values 'b0 'b1 'b2 'b3)))
  636. (let ((fields (protoc:message-definition-fields message)))
  637. `((define-record-type (,(builder-type-name message)
  638. ,(builder-constructor-name message)
  639. ,(builder-predicate-name message))
  640. (fields
  641. ,@(map (lambda (field)
  642. (let-values (((m0) (gensym-values 'm0)))
  643. (hashtable-set! field-internal-mutators field m0)
  644. (let ((name (protoc:field-definition-name field)))
  645. (list 'mutable
  646. (string->symbol name)
  647. (field-accessor-name message field)
  648. m0))))
  649. fields))
  650. (parent protobuf:message-builder)
  651. (protocol
  652. (lambda (,b1)
  653. (lambda ()
  654. (define ,b2
  655. (list ,@(map (lambda (field)
  656. `(protobuf:make-field-descriptor
  657. ,(protoc:field-definition-ordinal field)
  658. ,(protoc:field-definition-name field)
  659. ,(type-reference->type-descriptor-expr
  660. (protoc:field-definition-type field)
  661. naming-context)
  662. ,(eq? (protoc:field-definition-rule field)
  663. 'repeated)
  664. ,(eq? (protoc:field-definition-rule field)
  665. 'required)
  666. ,(calc-field-default
  667. field enum-naming-context)))
  668. fields)))
  669. (let ((,b3 (,b1 ,(message-type-name message) ,b2)))
  670. (apply ,b3 (map protobuf:field-descriptor-default ,b2))))))
  671. (sealed #t))
  672. ,@(let loop ((fields fields)
  673. (bindings (list)))
  674. (if (null? fields)
  675. bindings
  676. (let ((f (car fields)))
  677. (if (eq? (protoc:field-definition-rule f) 'repeated)
  678. (loop (cdr fields)
  679. (append (list (generate-field-mutator message f)
  680. (generate-field-clear message f))
  681. bindings))
  682. (loop (cdr fields)
  683. (append
  684. (list (generate-field-mutator message f)
  685. (generate-field-has-predicate message f)
  686. (generate-field-clear message f))
  687. bindings))))))
  688. (define (,(extension-accessor-name message) ,b0 ,b1)
  689. (protobuf:message-builder-extension ,b0 ,b1))
  690. (define (,(extension-mutator-name message) ,b0 ,b1 ,b2)
  691. (protobuf:set-message-builder-extension! ,b0 ,b1 ,b2))
  692. (define (,(extension-has-name message) ,b0 ,b1)
  693. (protobuf:message-builder-has-extension? ,b0 ,b1))
  694. (define (,(extension-clear-name message) ,b0 ,b1)
  695. (protobuf:clear-message-builder-extension! ,b0 ,b1))
  696. (define (,(builder-build-name message) ,b0)
  697. (protobuf:message-builder-build ,b0))))))
  698. )