#lang racket/base (require (for-syntax racket/base "transformer.rkt" "fixture.rkt" "compile.rkt" "debug.rkt" syntax/parse)) (provide (all-defined-out)) (define-syntax (define-honu-operator/syntax stx) (syntax-parse stx [(_ name precedence associativity binary-function) (syntax/loc stx (define-syntax name (make-honu-operator precedence associativity binary-function #f #f)))] [(_ name precedence associativity binary-function unary-function postfix?) (syntax/loc stx (define-syntax name (make-honu-operator precedence associativity binary-function unary-function postfix?)))])) (define-syntax (define-honu-fixture stx) (syntax-parse stx [(_ name transformer) #'(define-syntax name (make-fixture transformer))])) (define-syntax-rule (define-binary-operator name precedence associativity operator) (define-honu-operator/syntax name precedence associativity ;; binary (lambda (left right) (with-syntax ([left left] [right right]) (racket-syntax (operator left right)))))) (define-syntax-rule (define-unary+binary-operator name precedence associativity operator) (define-honu-operator/syntax name precedence associativity ;; binary (lambda (left right) (with-syntax ([left left] [right right]) (racket-syntax (operator left right)))) ;; unary (lambda (arg) (with-syntax ([arg arg]) (racket-syntax (operator arg)))) ;; binary operators should not be able to be postfix #f)) (define-syntax-rule (define-unary-operator name precedence postfix? operator) ;; associativity dont matter for unary (define-honu-operator/syntax name precedence 'left #f ;; unary (lambda (argument) (with-syntax ([argument argument]) (racket-syntax (operator argument)))) postfix?)) (define-honu-operator/syntax honu-flow 0.001 'left (lambda (left right) (with-syntax ([left left] [right right]) (racket-syntax (right left))))) (begin-for-syntax (define-syntax-rule (mutator change) (lambda (left right) (with-syntax ([left left] [right (change left right)]) (racket-syntax (set! left right)))))) ;; Traditional assignment operator (define-honu-operator/syntax honu-equal 0.0001 'left (let ([plain-mutate (mutator (lambda (left right) right))]) (lambda (left right) (define mutate (syntax-property left 'assign)) (if mutate (mutate right) (plain-mutate left right))))) ;; Define an assignment operator that uses the current value in its operation ;; a -= 2 ;; is the same ;; a = a - 2 ;; and turns into ;; (set! a (- a 2)) ;; ;; a.x -= 2 ;; turns into ;; (honu-struct-set! a x (- (dot a x) 2)) ;; where (dot a x) is field lookup of x inside a (define-syntax-rule (define-honu-operator-= name operation) (define-honu-operator/syntax name 0.0001 'left (let () (define (do-it left right) (with-syntax ([left left] [right right]) #'(operation left right))) (define plain-mutate (mutator do-it)) (lambda (left right) (define mutate (syntax-property left 'assign)) (if mutate (mutate (do-it left right)) (plain-mutate left right)))))) ;; Operators that mutate the left hand side (define-honu-operator-= honu-+= +) (define-honu-operator-= honu--= -) (define-honu-operator-= honu-*= *) (define-honu-operator-= honu-/= /) (define-unary+binary-operator honu-+ 1 'left +) (define-unary+binary-operator honu-- 1 'left -) (define-binary-operator honu-* 2 'left *) (define-binary-operator honu-/ 2 'left /) (define-binary-operator honu-^ 2 'right expt) (define-binary-operator honu-< 0.9 'left <) (define-binary-operator honu-<= 0.9 'left <=) (define-binary-operator honu-> 0.9 'left >) (define-binary-operator honu->= 0.9 'left >=) ;; (define-binary-operator honu-= 0.9 'left =) (define-binary-operator honu-and 0.5 'left and) (define-binary-operator honu-or 0.5 'left or) (define-binary-operator honu-cons 0.1 'right cons) (define-binary-operator honu-map 0.09 'left map) (define-binary-operator honu-string=? 1 'left string=?) (define-binary-operator honu-modulo 2 'left modulo) (define-binary-operator honu-to 0.001 'left (lambda (left right) (for/list ([i (in-range left right)]) i))) (define-unary-operator honu-not 0.7 #f not) (define-binary-operator honu-== 1 'left equal?) (define-binary-operator honu-not-equal 1 'left (lambda (left right) (not (equal? left right)))) (define-honu-operator/syntax honu-=> 0.00001 'left (lambda (left right) (when (not (identifier? left)) (raise-syntax-error '=> "expected an identifier" left)) (with-syntax ([left left] [right right]) (racket-syntax (lambda (left) right)))))