diff --git a/kaitai/expr.rkt b/kaitai/expr.rkt index 16b19a4..0063c80 100644 --- a/kaitai/expr.rkt +++ b/kaitai/expr.rkt @@ -93,8 +93,10 @@ [(string) $1] [(boolean) $1] [(identifier) $1] + [(lbracket rbracket) '(array)] [(lbracket apply-args rbracket) (cons 'array $2)] [(exp dot identifier) (list 'get $1 $3)] + [(exp lparen rparen) `(apply ,$1)] [(exp lparen apply-args rparen) `(apply ,$1 ,@$3)] [(exp * exp) (list '* $1 $3)] [(exp / exp) (list '/ $1 $3)] @@ -142,12 +144,20 @@ ;; - (apply func args ...): applies a function ;; - (array args ...): constructs array ;; - (get obj attr): references an attribute on an object +;; +;; stuff that cannot be constructed in user code +;; - (get-builtin obj attr): get a built-in attribute (magic stuff that's hidden from the user) +;; ;; primitive types: boolean, number, string, symbol (identifier) +;; +;; known issues: you can't do eg 5.to_s it has to be (5).to_s +;; i don't believe this breaks spec but idk +;; also i have no idea how to fix it ; (define test2 "true and 'a' != 'b' ? -1 + ~bits : ('hello' + 'world').substring(2, 3)") ;; => '(if (and #t (!= "a" "b")) ;; (+ -1 (~ bits)) ;; (apply (get (+ "hello" "world") substring) 2 3)) -; (let ([input (open-input-string test2)]) +; (let ([input (open-input-string "awoo . to_s([1, 2,3])")]) ; (kaitai-parser (lambda () (kaitai-lexer input)))) diff --git a/kaitai/main.rkt b/kaitai/main.rkt index d5e78b0..e7fef58 100644 --- a/kaitai/main.rkt +++ b/kaitai/main.rkt @@ -1,11 +1,11 @@ #lang racket/base -(require (for-syntax racket/base racket/list racket/match racket/pretty +(require (for-syntax racket/base racket/list racket/match racket/pretty racket/set "expr.rkt")) (provide (rename-out [kaitai:module-begin #%module-begin]) (except-out (all-from-out racket/base) #%module-begin)) -;; builtin types +(define-for-syntax kaitai:reserved (set '_io '_parent '_root)) ;; utility to concat symbol stuff (define-for-syntax (sym+ . args) @@ -25,9 +25,32 @@ ;; helper for types meta lookup (define-for-syntax (get-id-seq top given-id) (define id-sym (get-id top given-id)) + (when (set-member? kaitai:reserved (string->symbol id-sym)) + (raise-syntax-error #f "reserved id" id-sym)) (define seq (hash-ref top "seq" (make-rse "form must have a seq element"))) (values id-sym seq)) +;; everything is an object (uwu) +;; besides kaitai-expr-lang accessible things each object also has a magic secret node with its +;; implicit properties +;; magic properties: +;; - start: Nat +;; - length: Nat +;; +;; let the base type be KaitaiType. everything is KaitaiType and all KaitaiTypes have the above +;; magic properties +;; user-defined types extend KaitaiType +;; primitive types also extend KaitaiType, besides having the kaitai-builtin functions available +;; but evaluating a primitive object directly results in the value of the object +;; eg: if example is bound to the integer 5 +;; - '(get example to_s): "5" +;; - 'example: 5 +;; - '(get-builtin example start): some integer +;; some magic functions will evaluate the function applied to its object whether you actually apply +;; or not (eg to_s) because kaitai is really wacky about this and doesn't require parens if it takes +;; no arguments (even though it does, there's an implicit object argument) +;; so '(get example to_s) is equivalent to '(apply (get example to_s)) + ;; idk yet (define-for-syntax (kaitai:process-ty defn [given-id #f]) (define (primitive-size prim-ty) @@ -42,34 +65,39 @@ (for ([(name subty) (in-hash (hash-ref defn "types" (hash)))]) (kaitai:process-ty subty name)) - (struct context [io-pos] #:transparent) + (struct context [code io-pos] #:transparent) - (for/fold ([ctx (context 0)]) ([seq (in-list seqs)]) - ; (printf "seq: ~a\n" seq) + (define ctx + (for/fold ([ctx (context (hash) 0)]) ([seq (in-list seqs)]) + ; (printf "seq: ~a\n" seq) - (define seq-id (hash-ref seq "id" (make-rse "seq item has no id"))) + (define seq-id (hash-ref seq "id" (make-rse "seq item has no id"))) - ;; each seq element has an implicit dependency on the last seq's end position - ;; (the first seq depends on the parent element's start position) - ;; additionally each seq has a length expression calculated from its type + ;; each seq element has an implicit dependency on the last seq's end position + ;; (the first seq depends on the parent element's start position) + ;; additionally each seq has a length expression calculated from its type - (define size-expr - (cond [(hash-has-key? seq "size") (kexpr:parse (hash-ref seq "size"))] - [(hash-has-key? seq "type") (primitive-size (hash-ref seq "type"))] - [else (raise-syntax-error #f "seq has unsolvable size" seq)])) + (define size-expr + (cond [(hash-has-key? seq "size") (kexpr:parse (hash-ref seq "size"))] + [(hash-has-key? seq "type") (primitive-size (hash-ref seq "type"))] + [else (raise-syntax-error #f "seq has unsolvable size" seq)])) - (define next-pos `(+ ,(context-io-pos ctx) ,size-expr)) + (define pos (context-io-pos ctx)) + (define next-pos `(+ ,pos ,size-expr)) + (printf "~a: ~a to ~a\n" seq-id pos next-pos) + (define next-code + (hash-set (context-code ctx) seq-id + #`(read-io #,pos #,next-pos))) - (printf "~a: ~a to ~a\n" seq-id (context-io-pos ctx) next-pos) + (context next-code next-pos))) - (context next-pos)) - - (void)) + #`(define #,(string->symbol id) + #,(for/hash ([(id code) (context-code ctx)]) + (values (string->symbol id) #`(lambda () #,code))))) ;; top level process (define-for-syntax (kaitai:process defn) - (kaitai:process-ty defn) - (void)) + (kaitai:process-ty defn)) ;; runtime lib @@ -88,7 +116,8 @@ (define-syntax (kaitai:module-begin stx) (define body (second (syntax-e stx))) - (kaitai:process (syntax->datum body)) + (define top-level (kaitai:process (syntax->datum body))) + (pretty-write (syntax->datum top-level)) #`(#%module-begin (module+ main (kaitai:uwu))))