/compiler/utils.rkt

http://github.com/masm/sines · Racket · 134 lines · 118 code · 14 blank · 2 comment · 22 complexity · b94efcd35e45a6d243e0d7fa9b50040b MD5 · raw file

  1. #lang scheme/base
  2. (require
  3. scheme/base
  4. scheme/match
  5. "syntax.rkt"
  6. (prefix-in s: "syntax2.rkt")
  7. (prefix-in l: "../private/library.ss"))
  8. (define (dispatch-lambda/arity->lambda op arity)
  9. (or (ormap (lambda (proc)
  10. (match proc
  11. [(s:lambda args rest-arg body loc)
  12. (and (or (= (length args) arity)
  13. (and rest-arg
  14. (< (length args) arity)))
  15. proc)]))
  16. (dispatch-lambda-stx-procs op))
  17. (error 'dispatch-lambda/arity->lambda "missing a proc of arity ~S" arity)))
  18. (require "deserialize.rkt")
  19. (define (app->let-node loc proc args)
  20. (define (fn ids rest-id args)
  21. (cond [(null? ids)
  22. (cond [rest-id (list (cons (list rest-id)
  23. (s:app (s:global-ref (sines-variable-id l:list)) args)))]
  24. [(null? args) '()]
  25. [else (error "too many arguments" loc)])]
  26. [(null? args) (error "too few arguments" loc)]
  27. [else (cons (cons (list (car ids)) (car args))
  28. (fn (cdr ids) rest-id (cdr args)))]))
  29. (match proc
  30. [(s:lambda ids rest-id body)
  31. (let ([pairs (fn ids rest-id args)])
  32. (s:let-values (map car pairs) (map cdr pairs) body loc))]
  33. [(s:dispatch-lambda)
  34. (app->let-node loc (dispatch-lambda/arity->lambda proc (length args)) args)]
  35. [_ (error "contraction app->let-node: not matched" proc)]))
  36. ;; TODO: this should also rename the inner bindings, not just the outside lambda proc
  37. (define (app->let-node/rename loc proc args)
  38. (define (fn ids rest-id args)
  39. (cond [(null? ids)
  40. (cond [rest-id (list (cons (list rest-id)
  41. (s:app (s:global-ref (sines-variable-id l:list)) args)))]
  42. [(null? args) '()]
  43. [else (error "too many arguments" loc)])]
  44. [(null? args) (error "too few arguments" loc)]
  45. [else (cons (cons (list (car ids)) (car args))
  46. (fn (cdr ids) rest-id (cdr args)))]))
  47. (match proc
  48. [(s:lambda)
  49. (match (alpha-renamed-lexicals #:full? #f proc)
  50. [(s:lambda ids rest-id body)
  51. (let ([pairs (fn ids rest-id args)])
  52. (values (s:let-values (map car pairs) (map cdr pairs) body loc)))])]
  53. [(s:dispatch-lambda)
  54. (app->let-node loc (dispatch-lambda/arity->lambda proc (length args)) args)]
  55. [_ (error "contraction app->let-node: not matched" proc)]))
  56. (provide dispatch-lambda/arity->lambda
  57. app->let-node app->let-node/rename)
  58. (define next-in-seq
  59. (let ([c 0])
  60. (lambda ()
  61. (set! c (add1 c))
  62. c)))
  63. (define (lexical-id-clone id)
  64. (make-id (id-name id) (next-in-seq)))
  65. (define (new-lexical-id [name (gensym)])
  66. (make-id name (next-in-seq)))
  67. (define (new-global-id [base "g"])
  68. (make-module-id (gensym base) #f))
  69. (provide lexical-id-clone
  70. new-lexical-id
  71. new-global-id)
  72. ;;;
  73. (define (alpha-renamed-lexicals node #:full? error-if-not-exist?)
  74. (let ([hash (make-hasheq)])
  75. (define maybe-renamed
  76. (if error-if-not-exist?
  77. (lambda (id)
  78. (cond [(hash-ref hash id (lambda () #f))]
  79. [else (error 'alpha-renamed-lexicals "unknown lexical id ~A" id)]))
  80. (lambda (id)
  81. (cond [(hash-ref hash id (lambda () #f))]
  82. [else id]))))
  83. (define (extend-hash! ids)
  84. (for-each (lambda (id)
  85. (cond [(hash-ref hash id (lambda () #f)) => (lambda (_) (error 'alpha-renamed-lexicals "duplicate lexical id ~A" id))])
  86. (hash-set! hash id (lexical-id-clone id)))
  87. ids))
  88. (let loop ([node node])
  89. (match node
  90. [(or (s:literal) (s:global-ref)) node]
  91. [(s:lexical-ref id loc) (s:lexical-ref (maybe-renamed id) loc)]
  92. [(s:primapp transformer args loc) (s:primapp transformer (map loop args) loc)]
  93. [(s:app op args loc) (s:app (loop op) (map loop args) loc)]
  94. [(s:begin body loc) (s:begin (map loop body) loc)]
  95. [(s:define-values ids value loc) (s:define-values ids (loop value) loc)]
  96. [(s:if test then else loc) (s:if (loop test) (loop then) (loop else) loc)]
  97. [(s:lambda ids rest-id body loc)
  98. (extend-hash! (if rest-id (cons rest-id ids) ids))
  99. (s:lambda (map maybe-renamed ids)
  100. (and rest-id (maybe-renamed rest-id))
  101. (loop body) loc)]
  102. [(s:dispatch-lambda procs loc) (s:dispatch-lambda (map loop procs) loc)]
  103. [(s:let-values ids vals body loc)
  104. (let ([vals (map loop vals)])
  105. (extend-hash! (apply append ids))
  106. (s:let-values (map (lambda (ids) (map maybe-renamed ids)) ids)
  107. vals
  108. (loop body)
  109. loc))]
  110. [(s:fix ids procs body loc)
  111. (extend-hash! ids)
  112. (s:fix (map maybe-renamed ids) (map loop procs) (loop body) loc)]
  113. [(s:loop ids vals body loc)
  114. (let ([vals (map loop vals)])
  115. (extend-hash! ids)
  116. (s:loop (map maybe-renamed ids) vals (loop body) loc))]
  117. [(s:iterate args loc) (s:iterate (map loop args) loc)]
  118. [(s:program body loc) (s:program (map loop body) loc)]
  119. [_ (error 'alpha-renamed-lexicals "not matched" node)]))))
  120. (provide alpha-renamed-lexicals)