diff --git a/crossfire/codegen.template b/crossfire/codegen.template index 79831fd..4f3240e 100644 --- a/crossfire/codegen.template +++ b/crossfire/codegen.template @@ -34,12 +34,15 @@ typedef struct { int main() { char buf [ @(* 20 (vector-length pattern)) ]; - @(for/list ([num (in-naturals)] [cset (in-vector pattern)]) - @list{size_t @(format "i~a" num) ; - vartype @(format "v~a" num) ; + @(for/list ([num (in-naturals)] [iset-pos (in-vector pp-start)]) + @list{size_t @(format "i~a" num) = @(car iset-pos) ; + vartype @(format "v~a" num) = @(cdr iset-pos) ; }) - @(for/list ([num (in-naturals)] [cset (in-vector pattern)]) + + goto l_inner; + + @(for/list ([num (in-naturals)] [iset (in-vector pattern)]) (define iter (format "i~a" num)) (define viter (format "v~a" num)) (define iset (format "iset~a" num)) @@ -55,10 +58,22 @@ int main() { (string-join (for/list ([i (in-range (vector-length pattern))]) c-type-fmt) " ")) l_inner: + @(define (end-conditionals) + (add-between + (for/list ([num (in-naturals)] [iset-pos (in-vector pp-end)]) + (define iter (format "i~a" num)) + (define viter (format "v~a" num)) + @list{ @iter >= @(car iset-pos) && @viter >= @(cdr iset-pos) }) + " && ")) + + if ( @end-conditionals[] ) { + goto l_end; + } + ssize_t res = snprintf(buf, sizeof(buf), @(format "\"~a\\n\"" fmt), @vs ); fwrite(buf, res, 1, stdout); - @(for/list ([cset (in-vector pattern)]) "}}") + @(for/list ([iset (in-vector pattern)]) "}}") l_end: return 0; } diff --git a/crossfire/main.rkt b/crossfire/main.rkt index cf1c9fe..2232d79 100644 --- a/crossfire/main.rkt +++ b/crossfire/main.rkt @@ -37,6 +37,9 @@ ;; manifest.rkt processing +;; Iset is a listof Interval +;; Interval is a (cons start end) and represents [start, end) + (define (make-iset) '()) (define (iset-add iset start end) @@ -71,18 +74,30 @@ (for/sum ([ival (in-list iset)]) (- (cdr ival) (car ival)))) +;; IsetPos is a (cons inum ival) +;; inum - the interval number within the iset +;; ival - the actual input value + ;; converts a position of [0, iset-count) to 2 values ;; - iset interval number ;; - actual value within the interval +;; allows going up to iset-count to support upper exclusive bounds of intervals (define (pos->iset-pos iset pos) - (when (empty? iset) - (error "iset-pos out of range")) - (match-define (cons (cons fs fe) r) iset) - (define delta (- fe fs)) - (if (< pos delta) - (values 0 (+ fs pos)) - (let-values ([(inum val) (pos->iset-pos r (- pos delta))]) - (values (add1 inum) val)))) + (define (helper iset pos) + (match-define (cons (cons fs fe) r) iset) + (define delta (- fe fs)) + (if (< pos delta) + (cons 0 (+ fs pos)) + (match-let ([(cons inum val) (helper r (- pos delta))]) + (cons (add1 inum) val)))) + (define cnt (iset-count iset)) + (cond + [(> pos cnt) (error "iset-pos out of range" iset pos)] + [(= pos cnt) + ;; support interval exclusive upper bound + (match-define (cons inum ival) (helper iset (sub1 pos))) + (cons inum (add1 ival))] + [else (helper iset pos)])) (define (char->iset ch) (define cp (char->integer ch)) @@ -145,31 +160,32 @@ ;; pattern processing +;; a PatternPos is a vector of IsetPos + (define (pattern-count pattern) (for/fold ([sum 1]) ([p (in-vector pattern)]) (* sum (iset-count p)))) -;; design recipe violations follow -;; (sorry) -;; (i wanted this to be fast so i try to avoid spamming the heap) -; (define (pattern-generate pattern out-port) -; (define len (vector-length pattern)) -; (define gen (make-bytes len)) -; (define (output gen) -; (write-bytes gen out-port) -; (printf "\n")) -; (define (permute i gen) -; (cond [(= i len) (output gen)] -; [else -; (for ([chr (in-set (vector-ref pattern i))]) -; (bytes-set! gen i chr) -; (permute (add1 i) gen))])) -; (permute 0 gen)) +(define (pattern-start pattern) + (for/vector ([iset (in-vector pattern)]) + (pos->iset-pos iset 0))) + +(define (pattern-end pattern) + (for/vector ([iset (in-vector pattern)]) + (pos->iset-pos iset (iset-count iset)))) + +;; there used to be a racket implementation of the input generator but it majorly violated the +;; design recipe and got obsoleted by the template C version (which is intended to be more portable +;; and faster) ;; ok gamer move time (define-runtime-path codegen-template "codegen.template") -(define (pattern-codegen pattern) - (eval-template `(file ,(path->string codegen-template)) (hash 'pattern pattern))) +(define (pattern-codegen pattern pp-start pp-end) + (eval-template + `(file ,(path->string codegen-template)) + (hash 'pattern pattern + 'pp-start pp-start + 'pp-end pp-end))) (define-values [name mode command pattern] (parse-manifest @@ -178,6 +194,5 @@ (command ("meme")) (pattern "test?d?a?a?s")))) -; (pattern-generate pattern (current-output-port)) -; (displayln (pattern-count pattern)) -(pattern-codegen pattern) +(pattern-codegen pattern (pattern-start pattern) (pattern-end pattern)) +(printf "// total: ~a\n" (pattern-count pattern))