<commit_before>#lang typed/racket/no-check

(require 
 "../configuration.rkt"
 "./generate-c.rkt"
 syntax/location
 (for-syntax racket/system)
 (for-syntax "runtime-location.rkt")
 "runtime-location.rkt")

(provide (all-defined-out))

(define (find-unused-path [suffix : String]) : Path
  (make-temporary-file (format "tmp~~a~a" suffix)))

;; Basic driver for the entire backend
(: c-backend-generate-code (Data5-Lang . -> . Path))
(define (c-backend-generate-code uil) 
  (let* ([keep-c? (c-path)]
         [c-path (or keep-c? (find-unused-path ".c"))]
         [c-path (normalize-path c-path)]
         [o-path (or (output-path) (build-path "a.out"))]
         [o-path (normalize-path o-path)])
    ;; Write the C code to a file
    (with-output-to-file c-path #:mode 'text #:exists 'replace
      (lambda ()
        (generate-c uil c-path)))

    ;; if clang-format is present and we keep c then clean up the file
    (when keep-c?
      (define clang-format? (find-executable-path "clang-format"))
      (when clang-format?
        (system* clang-format? "-i"(path->string c-path))))

    ;; Invoke the system cc compiler on the file
    (invoke-c-compiler c-path o-path)

    (unless keep-c? (delete-file c-path))
    o-path))
  
;; call the host system's cc function
(: invoke-c-compiler (-> Path Path Path))
(define (invoke-c-compiler c-path o-path)
  (let* ([in   (path->string c-path)]
         [out  (path->string o-path)]
         [rt?  (runtime-path)] 
         [flags (append-flags (c-flags))])
    (let* ([keep-s? (s-path)])
      (when keep-s?
        (system (format "cc ~a -S -o ~a ~a" in (path->string keep-s?) flags))))
    (cond
      [rt? (cc/runtime out in flags #:runtime rt?)]
      [else (cc/runtime out in flags)])
    o-path))




(: cc/runtime (->* (String String String) (#:runtime Path)
                   Void))
(define (cc/runtime out in flags
                    #:runtime [rt runtime.o-path])
  (define gc
    (match (garbage-collector)
      ['Boehm
       (define gc-link-path (path->string boehm-gc.a-path))
       (match (system-type 'os)
         ['unix (string-append  gc-link-path " -pthreads")]
         ['macosx gc-link-path]
         ['windows (error 'unsupported-os)])]
      ['None  (path->string none-gc.o-path)]))
  (define rt-math
    (match (system-type 'os)
     ['unix "-lm"]
     ['macosx ""]))
  (define rt-cast-profiler
    (if (cast-profiler?)
        cast-profiler.o-path
        ""))
  (define cmd
    (format "clang -o ~a ~a ~a ~a ~a ~a ~a"
            out in rt rt-math gc rt-cast-profiler flags))
  (flush-output (current-error-port))
  (flush-output)
  (unless (system cmd)
    (error 'grift/backend-c/invoke-c-compiler
           "failed to compile with: ~a"
           cmd)))

(: append-flags : (Listof String) -> String)
(define (append-flags s)
  (if (null? s)
      (default-flags)
      ;; The loop that follows writes to a string using display
      ;; This avoids quadratic behavior of repeatedly appending strings.
      ;; This may be overkill as these strings are small in general,
      ;; but we will be deprecating this back end soon.
      (with-output-to-string
        (lambda ()
          (let loop ([s s])
            (unless (null? s)
              (display (car s))
              (display " ")
              (loop (cdr s)))
            (display (default-flags)))))))

;; C compiler warnings written with regard to clang
;; I need to check to make sure that these option will work with gcc
(define-type Opt-Warning (Parameter (Pair Boolean String)))

(define warn-format : Opt-Warning
  (make-parameter '(#f . "format")))

(define warn-int-conversion : Opt-Warning
  (make-parameter '(#f . "int-conversion")))

(define warn-unused-value : Opt-Warning
  (make-parameter '(#f . "unused-value")))
<commit_msg>fix bug in code generator<commit_after>#lang typed/racket/no-check

(require 
 "../configuration.rkt"
 "./generate-c.rkt"
 syntax/location
 (for-syntax racket/system)
 (for-syntax "runtime-location.rkt")
 "runtime-location.rkt")

(provide (all-defined-out))

(define (find-unused-path [suffix : String]) : Path
  (make-temporary-file (format "tmp~~a~a" suffix)))

;; Basic driver for the entire backend
(: c-backend-generate-code (Data5-Lang . -> . Path))
(define (c-backend-generate-code uil) 
  (let* ([keep-c? (c-path)]
         [c-path (or keep-c? (find-unused-path ".c"))]
         [c-path (normalize-path c-path)]
         [o-path (or (output-path) (build-path "a.out"))]
         [o-path (normalize-path o-path)])
    ;; Write the C code to a file
    (with-output-to-file c-path #:mode 'text #:exists 'replace
      (lambda ()
        (generate-c uil c-path)))

    ;; if clang-format is present and we keep c then clean up the file
    (when keep-c?
      (define clang-format? (find-executable-path "clang-format"))
      (when clang-format?
        (system* clang-format? "-i"(path->string c-path))))

    ;; Invoke the system cc compiler on the file
    (invoke-c-compiler c-path o-path)

    (unless keep-c? (delete-file c-path))
    o-path))
  
;; call the host system's cc function
(: invoke-c-compiler (-> Path Path Path))
(define (invoke-c-compiler c-path o-path)
  (let* ([in   (path->string c-path)]
         [out  (path->string o-path)]
         [rt?  (runtime-path)] 
         [flags (append-flags (c-flags))])
    (let* ([keep-s? (s-path)])
      (when keep-s?
        (system (format "cc ~a -S -o ~a ~a" in (path->string keep-s?) flags))))
    (cond
      [rt? (cc/runtime out in flags #:runtime rt?)]
      [else (cc/runtime out in flags)])
    o-path))




(: cc/runtime (->* (String String String) (#:runtime Path)
                   Void))
(define (cc/runtime out in flags
                    #:runtime [rt runtime.o-path])
  (define gc
    (match (garbage-collector)
      ['Boehm
       (define gc-link-path (path->string boehm-gc.a-path))
       (match (system-type 'os)
         ['unix (string-append  gc-link-path " -pthreads")]
         ['macosx gc-link-path]
         ['windows (error 'unsupported-os)])]
      ['None  (path->string none-gc.o-path)]))
  (define rt-math
    (match (system-type 'os)
     ['unix "-lm"]
     ['macosx ""]))
  (define rt-cast-profiler
    (if (cast-profiler?)
        cast-profiler.o-path
        ""))
  (define cmd
    (format "clang -o ~a ~a ~a ~a ~a ~a ~a"
            out in rt rt-math gc rt-cast-profiler flags))
  (flush-output (current-error-port))
  (flush-output)
  (unless (system cmd)
    (error 'grift/backend-c/invoke-c-compiler
           "failed to compile with: ~a"
           cmd)))

(: append-flags : (Listof String) -> String)
(define (append-flags s)
  (if (null? s)
      (default-flags)
      ;; The loop that follows writes to a string using display
      ;; This avoids quadratic behavior of repeatedly appending strings.
      ;; This may be overkill as these strings are small in general,
      ;; but we will be deprecating this back end soon.
      (with-output-to-string
        (lambda ()
          (let loop ([s s])
            (unless (null? s)
              (display (car s))
              (display " ")
              (loop (cdr s))))
          (display (default-flags))))))

;; C compiler warnings written with regard to clang
;; I need to check to make sure that these option will work with gcc
(define-type Opt-Warning (Parameter (Pair Boolean String)))

(define warn-format : Opt-Warning
  (make-parameter '(#f . "format")))

(define warn-int-conversion : Opt-Warning
  (make-parameter '(#f . "int-conversion")))

(define warn-unused-value : Opt-Warning
  (make-parameter '(#f . "unused-value")))

{'fraction_non_alphanumeric': 0.16134985499604534, 'fraction_numerical': 0.0002636435539151068, 'mean_word_length': 2.4470695138573375, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4801819', 'n_tokens_mistral': 2601, 'n_tokens_neox': 2526, 'n_words': 736}