diff --git a/PRIMITIVES.md b/PRIMITIVES.md index 0855838..c63b6ac 100644 --- a/PRIMITIVES.md +++ b/PRIMITIVES.md @@ -97,6 +97,7 @@ added to them too. * The `numeric?` primitive will return true for ints, floats, and characters. * mathematical operations `*`, `+`, `-`, and `/`. * These work against integers, floating point numbers, or mixed operands. +* Binary operations `&` (and), `|` (or) `^` (xor) which work against integers. * (Integer) comparison operations * `<`, `<=`, `>=`, `>`, and `=`. * Other functions implemented in assembly: diff --git a/README.md b/README.md index f1ddc58..4cf68a7 100644 --- a/README.md +++ b/README.md @@ -70,6 +70,7 @@ It should be noted that we prepend a "standard library" of functions to all user * See the [Garbage Collection](GC.md) file for further details on how the GC process works, and can be inspected/modified. * Mathematical operations `+`, `-`, `*`, and `/`. * These work against integers, floating point numbers, or combination of the two. +* Binary operations `&` (and), `|` (or) `^` (xor) which work against integers. * File I/O operations: * `fopen`, `fclose`, `fread`, and `fwrite`. * Filesystem primitive: diff --git a/compiler/compiler.go b/compiler/compiler.go index 90d33e8..9ba2b99 100644 --- a/compiler/compiler.go +++ b/compiler/compiler.go @@ -55,6 +55,9 @@ var labelRemapping = map[string]string{ "<": "LT", "=": "EQUALS", "/": "DIVIDE", + "&": "AMPERSAND", + "^": "CARET", + "|": "PIPE", } // FunctionArgs records the arguments which a given defun accepts. diff --git a/compiler/template.tmpl b/compiler/template.tmpl index f3a57c2..fc5dc1d 100644 --- a/compiler/template.tmpl +++ b/compiler/template.tmpl @@ -846,6 +846,45 @@ integer_multiply: ret +;; & +FUNC fn_sys_and + call are_both_integers + jz binary_and_integer + jmp type_error ; type error +binary_and_integer: + UNTAG_REG rdi + UNTAG_REG rsi ; untag arguments + mov rax, rdi + and rax, rsi + TAG_INTEGER_REG rax + ret + +;; | +FUNC fn_sys_or + call are_both_integers + jz binary_or_integer + jmp type_error ; type error +binary_or_integer: + UNTAG_REG rdi + UNTAG_REG rsi ; untag arguments + mov rax, rdi + or rax, rsi + TAG_INTEGER_REG rax + ret + +;; ^ +FUNC fn_sys_xor + call are_both_integers + jz binary_xor_integer + jmp type_error ; type error +binary_xor_integer: + UNTAG_REG rdi + UNTAG_REG rsi ; untag arguments + mov rax, rdi + xor rax, rsi + TAG_INTEGER_REG rax + ret + ;; % FUNC fn_sys_PERCENT call are_both_integers diff --git a/inception.lisp b/inception.lisp index 1b9f531..1a6c537 100644 --- a/inception.lisp +++ b/inception.lisp @@ -305,6 +305,7 @@ (register-builtin "sys_cons" (lambda (args) (sys_cons (car args) (cadr args)))) (register-builtin "sys_divide" (lambda (args) (sys_divide (car args) (cadr args)))) (register-builtin "sys_entries" (lambda (args) (sys_entries (car args)))) + (register-builtin "sys_and" (lambda (args) (sys_and (car args) (cadr args)))) (register-builtin "sys_environment" (lambda (args) (sys_environment))) (register-builtin "sys_exit" (lambda (args) (sys_exit (car args)))) (register-builtin "sys_explode" (lambda (args) (sys_explode (car args)))) @@ -323,6 +324,7 @@ (register-builtin "sys_now" (lambda (args) (sys_now))) (register-builtin "sys_nth!" (lambda (args) (sys_nth! (car args) (cadr args) (caddr args)))) (register-builtin "sys_nth" (lambda (args) (sys_nth (car args) (cadr args)))) + (register-builtin "sys_or" (lambda (args) (sys_or (car args) (cadr args)))) (register-builtin "sys_ord" (lambda (args) (sys_ord (car args)))) (register-builtin "sys_package" (lambda (args) (sys_package (car args)))) (register-builtin "sys_packages" (lambda (args) (sys_packages ))) @@ -340,6 +342,7 @@ (register-builtin "sys_strlen" (lambda (args) (sys_strlen (car args)))) (register-builtin "sys_substr" (lambda (args) (sys_substr (car args) (cadr args) (caddr args)))) (register-builtin "sys_syscall" (lambda (args) (sys_syscall (nth args 0) (nth args 1) (nth args 2) (nth args 3) (nth args 4)(nth args 5)))) + (register-builtin "sys_xor" (lambda (args) (sys_xor (car args) (cadr args)))) ) ;; eval: where the magic happens. diff --git a/stdlib.slisp b/stdlib.slisp index 9d14ffd..41f3f29 100644 --- a/stdlib.slisp +++ b/stdlib.slisp @@ -677,6 +677,18 @@ and run BODY for side-effects. Returns nil." (sys_divide a (car b)) (sys_divide 1 (+ a 0.0)))) +(defun & (a b) + "Binary AND between two integers." + (sys_and a b)) + +(defun | (a b) + "Binary OR between two integers." + (sys_or a b)) + +(defun ^ (a b) + "Binary XOR between two integers." + (sys_xor a b)) + (defun abs (n) "Return the absolute value of N, as a positive number" (if (< n 0) (- 0 n) n))