(define impc:ir:compiler:modulo
(lambda (ast types . hint?)
;(print 'modulo: 'ast: ast 'hint: hint?)
(let* ((type-hint (let ((value (assoc-strcmp (cl:find-if symbol? (cdr ast)) types)))
(if value
(cdr value)
(if (null? hint?)
'()
(car hint?)))))
(a (if (null? type-hint)
(impc:ir:compiler (cadr ast) types)
(impc:ir:compiler (cadr ast) types type-hint)))
(aval (impc:ir:gname))
(b (if (null? type-hint)
(impc:ir:compiler (caddr ast) types)
(impc:ir:compiler (caddr ast) types type-hint)))
(bval (impc:ir:gname))
(os (make-string 0))
(type (if (null? type-hint)
(cadr aval)
(impc:ir:get-type-str type-hint))))
;; sanity check
(if (not (and (impc:ir:number? (cadr aval))
(impc:ir:number? (cadr bval))))
(impc:compiler:print-type-conflict-error (cadr aval) (cadr bval) ast))
(emit a os)
(emit b os)
;(print (car aval) '>> (car bval) '>> type)
;; do llvm float constant check
(if (= *impc:ir:fp32* (impc:ir:get-type-from-str type))
(begin (if (number? (cadr ast)) (set-car! aval (llvm:convert-float (car aval))))
(if (number? (caddr ast)) (set-car! bval (llvm:convert-float (car bval))))))
;; do llvm double constant check
(if (= *impc:ir:fp64* (impc:ir:get-type-from-str type))
(begin (if (number? (cadr ast)) (set-car! aval (number->string (* 1.0 (cadr ast)))))
(if (number? (caddr ast)) (set-car! bval (number->string (* 1.0 (caddr ast)))))))