(defstruct op name cname nargs closure docs) (def (rune-alphanumeric? r) (or (rune-alphabetic? r) (rune-numeric? r))) (def (name->cname name) (let {[cname (buffer)]} (for 0 (length name) (λ (i) (let {[r (str-rune name i)]} (io-write cname (cond [(rune-alphanumeric? r) (rune-upcase r)] [(eq? r #\?) #\P] [(eq? r #\_) #\_] [else ""]))))) (io->str cname))) (defmacro (op symbol (nargs NIL) (closure NIL) (docs NIL) (:cname NIL)) (let ((name (str symbol))) `(make-op :name ,name :cname ,(str "OP_" (or cname (name->cname name))) :nargs ,nargs :closure ',closure :docs ',docs))) (def ops (vec (op loada0) (op loada1) (op loadv) (op brn) (op pop) (op call) (op tcall) (op loadg) (op loada) (op loadc) (op ret) (op dup) (op car 1 (λ (x) (car x)) {[(lst) "Return the first element of a cons cell (head of a list) or `NIL` if not available. Examples: (car NIL) ; ↳ NIL (car '(1 2 3)) ; ↳ 1 (car '(1 . 2)) ; ↳ 1" :doc-group list]}) (op cdr 1 (λ (x) (cdr x)) {[(lst) "Return the second element of a cons cell (tail of a list) or `NIL` if not available. Examples: (cdr NIL) ; ↳ NIL (cdr '(1 2 3)) ; ↳ (2 3) (cdr '(1 . 2)) ; ↳ 2" :doc-group list]}) (op closure) (op seta) (op jmp) (op loadc0) (op cons? 1 (λ (x) (cons? x)) {[(v) "Return `T` if `v` is a cons cell, `NIL` otherwise. Examples: (cons? 0) ; ↳ NIL (cons? NIL) ; ↳ NIL (cons? '(1)) ; ↳ T" :doc-group type :doc-see cons :doc-see list?]}) (op brne) (op loadt) (op load0) (op loadc1) (op aref2) (op atom? 1 (λ (x) (atom? x)) {[(v) «Return `T` if `v` is a _not_ a cons cell, `NIL` otherwise. This is the opposite of `cons?`. The term "atom" comes from the idea of being indivisible. Examples: (atom? "a") ; ↳ T (atom? NIL) ; ↳ T (atom? '(1)) ; ↳ NIL» :doc-group type]}) (op loadvoid) (op brnn) (op load1) (op < -1 (λ rest (apply < rest)) {[(v . rest) "Return `T` if the arguments are in strictly increasing order (next one is greater than the previous one). With a single argument the result is always `T`." :doc-group compare]} :cname "LT") (op add2) (op set-cdr! 2 (λ (x y) (set-cdr! x y)) {[(cell new-second) "Modify a cons cell (a list) in-place by putting `new-second` as its second element (tail of the list). Return the modified cons cell (list). Examples: (def q '(1 2 3 4 5)) (set-cdr! q '(6 7)) ; ↳ (1 6 7) q ; ↳ (1 6 7)" :doc-group list]}) (op keyargs) (op cons 2 (λ (x y) (cons x y)) {[(first second) "Return a cons cell containing two arguments. Examples: (cons 1 2) ; ↳ (1 . 2) (cons 1 '(2)) ; ↳ (1 2) (cons 1 (cons 2 (cons 3 NIL))) ; ↳ (1 2 3)" :doc-group list :doc-see cons? :doc-see list]}) (op eq? 2 (λ (x y) (eq? x y)) {[(a b) «Return `T` if `a` and `b` are the same object, `NIL` otherwise. Examples: (eq? 0.0 0) ; ↳ NIL (eq? 0 0) ; ↳ T (def a "1") (def b "1") (eq? a b) ; ↳ NIL (def a '(1)) (def b '(1)) (eq? a b) ; ↳ NIL» :doc-group compare]}) (op sym? 1 (λ (x) (sym? x)) {[(v) "Return `T` if `v` is a symbol, `NIL` otherwise." :doc-group type :doc-see sym :doc-see gensym?]}) (op not 1 (λ (x) (not x)) {[(v) "Return `T` if `v` is `NIL`, `T` otherwise." :doc-group syntax :doc-see and :doc-see or]}) (op cadr 1 (λ (x) (cadr x)) {[(lst) «Shorthand for `(car (cdr lst))`, that is, _first element of the second element_. Examples: (cadr '(1 2 3)) ; ↳ 2 (cadr '(1)) ; ↳ NIL (cadr NIL) ; ↳ NIL» :doc-group list]}) (op neg) (op nan? 1 (λ (x) (nan? x)) {[(v) "Return `T` if `v` is a floating point representation of NaN, either negative or positive, `NIL` otherwise." :doc-group number]}) (op bounda) (op num? 1 (λ (x) (num? x)) {[(v) "Return `T` if `v` is of a numerical type, `NIL` otherwise. Numerical types include floating point, fixnum, bignum, etc. Note: ironically, a NaN value is considered a number by this function since it's only testing the _type_ of the value." :doc-group type :doc-group number :doc-see nan?]}) (op fixnum? 1 (λ (x) (fixnum? x)) {[(v) "Return `T` if `v` is of a fixnum type, `NIL` otherwise." :doc-group type :doc-group number :doc-see fixnum]}) (op bound? 1 (λ (x) (bound? x)) {[(sym) "Return `T` if `sym` has a value associated with it, `NIL` otherwise. Examples: (bound? 'bound?) ; ↳ T (bound? 'doesnotcompute) ; ↳ NIL"]}) (op builtin? 1 (λ (x) (builtin? x)) {[(v) "Return `T` if `v` is a built-in function implemented in C, `NIL` otherwise. Examples: (builtin? map) ; ↳ T (builtin? macroexpand) ; ↳ NIL" :doc-group type :doc-see builtin :doc-see fn? :doc-see closure?]}) (op fn? 1 (λ (x) (fn? x)) {[(v) "Return `T` if `v` is a function, `NIL` otherwise. Examples: (fn? (void)) ; ↳ NIL (fn? map) ; ↳ T (fn? macroexpand) ; ↳ T" :doc-group type :doc-see fn :doc-see builtin? :doc-see closure?]}) (op vec? 1 (λ (x) (vec? x)) {[(v) "Return `T` if `v` is a vector, `NIL` otherwise." :doc-group type]}) (op shift) (op set-car! 2 (λ (x y) (set-car! x y)) {[(cell new-first) "Modify a cons cell (a list) in-place by putting `new-first` as its first element (head of the list). Return the modified cons cell (list). Examples: (def q '(1 2 3 4 5)) (set-car! q 0) ; ↳ (0 6 7) q ; ↳ (0 6 7)" :doc-group list]}) (op jmp.l) (op brn.l) (op box) (op eqv? 2 (λ (x y) (eqv? x y)) {[(a b) «Return `T` if both `a` and `b` are of the same value and primitive (leaf) type, `NIL` otherwise. Neither cons cell nor vector are not considered primitive types as they may define deep structures. Examples: (eqv? 0.0 0) ; ↳ NIL (eqv? 0 0) ; ↳ T (def a "1") (def b "1") (eqv? a b) ; ↳ T (def a '(1)) (def b '(1)) (eqv? a b) ; ↳ NIL» :doc-group compare]}) (op equal? 2 (λ (x y) (equal? x y)) {[(a b) «Return `T` if both `a` and `b` are of the same value. For non-leaf types (cons cell and vector), the equality test is performed throughout the whole structure of the values. Examples: (equal? 0.0 0) ; ↳ NIL (equal? 0 0) ; ↳ T (def a "1") (def b "1") (equal? a b) ; ↳ T (def a '(1)) (def b '(1)) (equal? a b) ; ↳ T» :doc-group compare]}) (op list T (λ rest rest) {[rest «Return a list constructed of the arguments. Examples: (list) ; empty list ; ↳ NIL (list 1 2.5 "a" 'b) ; ↳ (1 2.5 "a" b)» :doc-see list? :doc-see cons]}) (op apply -2 (λ rest (apply apply rest)) {[(f arg . rest) "Return the result of applying a function `f` to a list of arguments. The last argument must always be a list which gets spliced as arguments to the function. Examples: (apply + 1 2 '(3 4 5)) ; ↳ 15 (apply vec '(1 2 3)) ; ↳ #(3 4 5) (apply arr 'u8 '(3 4 5)) ; ↳ #vu8(3 4 5)"]}) (op + T (λ rest (apply + rest)) {[rest "Return sum of the arguments or `0` when none specified." :doc-group number]} :cname "ADD") (op - -1 (λ rest (apply - rest)) {[(n . rest) "Return the result of subtraction. With only one argument a negation is performed. Examples: (- 1.5) ; ↳ -1.5 (- 3 2) ; ↳ 1" :doc-group number]} :cname "SUB") (op * T (λ rest (apply * rest)) {[rest "Return product of the arguments or `1` when none specified." :doc-group number]} :cname "MUL") (op / -1 (λ rest (apply / rest)) {[(n . rest) "Return the division of the arguments. With only one argument the result of `1/x` is returned. If the result is integer-valued, it is returned as an integer. Examples: (/ 2) ; ↳ 0.5 (/ 7 2 2) ; ↳ 1.75 (/ 10 -2) ; ↳ -5 ; a fixnum (/ 6.9 1.9) ; ↳ 3.6315…" :doc-group number :doc-see div0 :doc-see div]} :cname "DIV") (op div0 2 (λ rest (apply div0 rest)) {[(a n) "Return the quotient of the truncated division `a/n`. Examples: (div0 10 3) ; ↳ 3 (div0 -10 3) ; ↳ -3 (div0 -10 -3) ; ↳ 3 (div0 10 -3) ; ↳ -3" :doc-group number :doc-see mod0 :doc-see div]}) (op = -1 (λ rest (apply = rest)) {[(n . rest) "Numerical equality test. Return `T` if all numbers are equal, `NIL` otherwise." :doc-group number :doc-group compare]} :cname "NUMEQP") (op compare 2 (λ (x y) (compare x y)) {[(a b) «Return -1 if `x` is less than `y`, 0 if equal, and `1` if `y` is greater than `x`. Examples: (compare 'a 'b) ; ↳ -1 (compare 1 1) ; ↳ 0 (compare "b" "a") ; ↳ 1» :doc-group compare]}) (op argc) (op vec T (λ rest (apply vec rest)) {[rest «Construct a vector containing the specified arguments. Examples: (vec) ; empty vector ; ↳ #() (vec 1 2.5 "a" 'b) ; ↳ #(1 2.5 "a" b)» :doc-group array :doc-see vec-alloc :doc-see arr]}) (op aset! -3 (λ rest (apply aset! rest)) {[(sequence subscripts… new-value) "Modify the sequence element specified by the subscripts and return the new value. The sequence can be an array, vector, a list. Multi-dimensional sequences of variating types are also supported. Examples: (def a '((1 #(2 (3)) 4))) (aset! a 1 'x) ; ‼ index 1 out of bounds (aset! a 0 0 'x) ; ↳ x a ; ↳ ((x #(2 (3)) 4)) (aset! a 0 1 9) ; ↳ 9 a ; ↳ ((x #(9 (3)) 4))" :doc-group arrayLines 1–500 of 631. Load more
(defstruct op name cname nargs closure docs) (def (rune-alphanumeric? r) (or (rune-alphabetic? r) (rune-numeric? r))) (def (name->cname name) (let {[cname (buffer)]} (for 0 (length name) (λ (i) (let {[r (str-rune name i)]} (io-write cname (cond [(rune-alphanumeric? r) (rune-upcase r)] [(eq? r #\?) #\P] [(eq? r #\_) #\_] [else ""]))))) (io->str cname))) (defmacro (op symbol (nargs NIL) (closure NIL) (docs NIL) (:cname NIL)) (let ((name (str symbol))) `(make-op :name ,name :cname ,(str "OP_" (or cname (name->cname name))) :nargs ,nargs :closure ',closure :docs ',docs))) (def ops (vec (op loada0) (op loada1) (op loadv) (op brn) (op pop) (op call) (op tcall) (op loadg) (op loada) (op loadc) (op ret) (op dup) (op car 1 (λ (x) (car x)) {[(lst) "Return the first element of a cons cell (head of a list) or `NIL` if not available. Examples: (car NIL) ; ↳ NIL (car '(1 2 3)) ; ↳ 1 (car '(1 . 2)) ; ↳ 1" :doc-group list]}) (op cdr 1 (λ (x) (cdr x)) {[(lst) "Return the second element of a cons cell (tail of a list) or `NIL` if not available. Examples: (cdr NIL) ; ↳ NIL (cdr '(1 2 3)) ; ↳ (2 3) (cdr '(1 . 2)) ; ↳ 2" :doc-group list]}) (op closure) (op seta) (op jmp) (op loadc0) (op cons? 1 (λ (x) (cons? x)) {[(v) "Return `T` if `v` is a cons cell, `NIL` otherwise. Examples: (cons? 0) ; ↳ NIL (cons? NIL) ; ↳ NIL (cons? '(1)) ; ↳ T" :doc-group type :doc-see cons :doc-see list?]}) (op brne) (op loadt) (op load0) (op loadc1) (op aref2) (op atom? 1 (λ (x) (atom? x)) {[(v) «Return `T` if `v` is a _not_ a cons cell, `NIL` otherwise. This is the opposite of `cons?`. The term "atom" comes from the idea of being indivisible. Examples: (atom? "a") ; ↳ T (atom? NIL) ; ↳ T (atom? '(1)) ; ↳ NIL» :doc-group type]}) (op loadvoid) (op brnn) (op load1) (op < -1 (λ rest (apply < rest)) {[(v . rest) "Return `T` if the arguments are in strictly increasing order (next one is greater than the previous one). With a single argument the result is always `T`." :doc-group compare]} :cname "LT") (op add2) (op set-cdr! 2 (λ (x y) (set-cdr! x y)) {[(cell new-second) "Modify a cons cell (a list) in-place by putting `new-second` as its second element (tail of the list). Return the modified cons cell (list). Examples: (def q '(1 2 3 4 5)) (set-cdr! q '(6 7)) ; ↳ (1 6 7) q ; ↳ (1 6 7)" :doc-group list]}) (op keyargs) (op cons 2 (λ (x y) (cons x y)) {[(first second) "Return a cons cell containing two arguments. Examples: (cons 1 2) ; ↳ (1 . 2) (cons 1 '(2)) ; ↳ (1 2) (cons 1 (cons 2 (cons 3 NIL))) ; ↳ (1 2 3)" :doc-group list :doc-see cons? :doc-see list]}) (op eq? 2 (λ (x y) (eq? x y)) {[(a b) «Return `T` if `a` and `b` are the same object, `NIL` otherwise. Examples: (eq? 0.0 0) ; ↳ NIL (eq? 0 0) ; ↳ T (def a "1") (def b "1") (eq? a b) ; ↳ NIL (def a '(1)) (def b '(1)) (eq? a b) ; ↳ NIL» :doc-group compare]}) (op sym? 1 (λ (x) (sym? x)) {[(v) "Return `T` if `v` is a symbol, `NIL` otherwise." :doc-group type :doc-see sym :doc-see gensym?]}) (op not 1 (λ (x) (not x)) {[(v) "Return `T` if `v` is `NIL`, `T` otherwise." :doc-group syntax :doc-see and :doc-see or]}) (op cadr 1 (λ (x) (cadr x)) {[(lst) «Shorthand for `(car (cdr lst))`, that is, _first element of the second element_. Examples: (cadr '(1 2 3)) ; ↳ 2 (cadr '(1)) ; ↳ NIL (cadr NIL) ; ↳ NIL» :doc-group list]}) (op neg) (op nan? 1 (λ (x) (nan? x)) {[(v) "Return `T` if `v` is a floating point representation of NaN, either negative or positive, `NIL` otherwise." :doc-group number]}) (op bounda) (op num? 1 (λ (x) (num? x)) {[(v) "Return `T` if `v` is of a numerical type, `NIL` otherwise. Numerical types include floating point, fixnum, bignum, etc. Note: ironically, a NaN value is considered a number by this function since it's only testing the _type_ of the value." :doc-group type :doc-group number :doc-see nan?]}) (op fixnum? 1 (λ (x) (fixnum? x)) {[(v) "Return `T` if `v` is of a fixnum type, `NIL` otherwise." :doc-group type :doc-group number :doc-see fixnum]}) (op bound? 1 (λ (x) (bound? x)) {[(sym) "Return `T` if `sym` has a value associated with it, `NIL` otherwise. Examples: (bound? 'bound?) ; ↳ T (bound? 'doesnotcompute) ; ↳ NIL"]}) (op builtin? 1 (λ (x) (builtin? x)) {[(v) "Return `T` if `v` is a built-in function implemented in C, `NIL` otherwise. Examples: (builtin? map) ; ↳ T (builtin? macroexpand) ; ↳ NIL" :doc-group type :doc-see builtin :doc-see fn? :doc-see closure?]}) (op fn? 1 (λ (x) (fn? x)) {[(v) "Return `T` if `v` is a function, `NIL` otherwise. Examples: (fn? (void)) ; ↳ NIL (fn? map) ; ↳ T (fn? macroexpand) ; ↳ T" :doc-group type :doc-see fn :doc-see builtin? :doc-see closure?]}) (op vec? 1 (λ (x) (vec? x)) {[(v) "Return `T` if `v` is a vector, `NIL` otherwise." :doc-group type]}) (op shift) (op set-car! 2 (λ (x y) (set-car! x y)) {[(cell new-first) "Modify a cons cell (a list) in-place by putting `new-first` as its first element (head of the list). Return the modified cons cell (list). Examples: (def q '(1 2 3 4 5)) (set-car! q 0) ; ↳ (0 6 7) q ; ↳ (0 6 7)" :doc-group list]}) (op jmp.l) (op brn.l) (op box) (op eqv? 2 (λ (x y) (eqv? x y)) {[(a b) «Return `T` if both `a` and `b` are of the same value and primitive (leaf) type, `NIL` otherwise. Neither cons cell nor vector are not considered primitive types as they may define deep structures. Examples: (eqv? 0.0 0) ; ↳ NIL (eqv? 0 0) ; ↳ T (def a "1") (def b "1") (eqv? a b) ; ↳ T (def a '(1)) (def b '(1)) (eqv? a b) ; ↳ NIL» :doc-group compare]}) (op equal? 2 (λ (x y) (equal? x y)) {[(a b) «Return `T` if both `a` and `b` are of the same value. For non-leaf types (cons cell and vector), the equality test is performed throughout the whole structure of the values. Examples: (equal? 0.0 0) ; ↳ NIL (equal? 0 0) ; ↳ T (def a "1") (def b "1") (equal? a b) ; ↳ T (def a '(1)) (def b '(1)) (equal? a b) ; ↳ T» :doc-group compare]}) (op list T (λ rest rest) {[rest «Return a list constructed of the arguments. Examples: (list) ; empty list ; ↳ NIL (list 1 2.5 "a" 'b) ; ↳ (1 2.5 "a" b)» :doc-see list? :doc-see cons]}) (op apply -2 (λ rest (apply apply rest)) {[(f arg . rest) "Return the result of applying a function `f` to a list of arguments. The last argument must always be a list which gets spliced as arguments to the function. Examples: (apply + 1 2 '(3 4 5)) ; ↳ 15 (apply vec '(1 2 3)) ; ↳ #(3 4 5) (apply arr 'u8 '(3 4 5)) ; ↳ #vu8(3 4 5)"]}) (op + T (λ rest (apply + rest)) {[rest "Return sum of the arguments or `0` when none specified." :doc-group number]} :cname "ADD") (op - -1 (λ rest (apply - rest)) {[(n . rest) "Return the result of subtraction. With only one argument a negation is performed. Examples: (- 1.5) ; ↳ -1.5 (- 3 2) ; ↳ 1" :doc-group number]} :cname "SUB") (op * T (λ rest (apply * rest)) {[rest "Return product of the arguments or `1` when none specified." :doc-group number]} :cname "MUL") (op / -1 (λ rest (apply / rest)) {[(n . rest) "Return the division of the arguments. With only one argument the result of `1/x` is returned. If the result is integer-valued, it is returned as an integer. Examples: (/ 2) ; ↳ 0.5 (/ 7 2 2) ; ↳ 1.75 (/ 10 -2) ; ↳ -5 ; a fixnum (/ 6.9 1.9) ; ↳ 3.6315…" :doc-group number :doc-see div0 :doc-see div]} :cname "DIV") (op div0 2 (λ rest (apply div0 rest)) {[(a n) "Return the quotient of the truncated division `a/n`. Examples: (div0 10 3) ; ↳ 3 (div0 -10 3) ; ↳ -3 (div0 -10 -3) ; ↳ 3 (div0 10 -3) ; ↳ -3" :doc-group number :doc-see mod0 :doc-see div]}) (op = -1 (λ rest (apply = rest)) {[(n . rest) "Numerical equality test. Return `T` if all numbers are equal, `NIL` otherwise." :doc-group number :doc-group compare]} :cname "NUMEQP") (op compare 2 (λ (x y) (compare x y)) {[(a b) «Return -1 if `x` is less than `y`, 0 if equal, and `1` if `y` is greater than `x`. Examples: (compare 'a 'b) ; ↳ -1 (compare 1 1) ; ↳ 0 (compare "b" "a") ; ↳ 1» :doc-group compare]}) (op argc) (op vec T (λ rest (apply vec rest)) {[rest «Construct a vector containing the specified arguments. Examples: (vec) ; empty vector ; ↳ #() (vec 1 2.5 "a" 'b) ; ↳ #(1 2.5 "a" b)» :doc-group array :doc-see vec-alloc :doc-see arr]}) (op aset! -3 (λ rest (apply aset! rest)) {[(sequence subscripts… new-value) "Modify the sequence element specified by the subscripts and return the new value. The sequence can be an array, vector, a list. Multi-dimensional sequences of variating types are also supported. Examples: (def a '((1 #(2 (3)) 4))) (aset! a 1 'x) ; ‼ index 1 out of bounds (aset! a 0 0 'x) ; ↳ x a ; ↳ ((x #(2 (3)) 4)) (aset! a 0 1 9) ; ↳ 9 a ; ↳ ((x #(9 (3)) 4))" :doc-group array