diff --git a/module/language/elisp/README b/module/language/elisp/README index 0cd0efd19..e7da303b3 100644 --- a/module/language/elisp/README +++ b/module/language/elisp/README @@ -13,6 +13,7 @@ Already implemented: * while * let, let* * lambda expressions, function calls using list notation + * some built-ins (mainly numbers/arithmetic) Especially still missing: * other progX forms, will be done in macros @@ -22,7 +23,7 @@ Especially still missing: * real elisp reader instead of Scheme's * set, makunbound, boundp functions * macros - * general primitives (+, -, *, cons, ...) + * more built-ins * funcall and apply * fset & friends * defvar, defun diff --git a/module/language/elisp/compile-tree-il.scm b/module/language/elisp/compile-tree-il.scm index ea6dab94e..05134d40e 100644 --- a/module/language/elisp/compile-tree-il.scm +++ b/module/language/elisp/compile-tree-il.scm @@ -37,6 +37,7 @@ ; Value to use for Elisp's nil and t. +; FIXME: Use real nil. (define (nil-value loc) (make-const loc #f)) (define (t-value loc) (make-const loc #t)) @@ -72,9 +73,11 @@ (define (ensure-fluid! loc sym module) (let ((resolved-module (call-primitive loc 'resolve-module - (make-const loc module)))) + (make-const loc module))) + (resolved-intf (call-primitive loc 'resolve-interface + (make-const loc module)))) (make-conditional loc - (call-primitive loc 'module-defined? resolved-module (make-const loc sym)) + (call-primitive loc 'module-defined? resolved-intf (make-const loc sym)) (make-void loc) (make-sequence loc (list (call-primitive loc 'module-define! @@ -82,7 +85,10 @@ (call-primitive loc 'make-fluid)) (call-primitive loc 'module-export! resolved-module - (call-primitive loc 'list (make-const loc sym)))))))) + (call-primitive loc 'list (make-const loc sym))) + (call-primitive loc 'fluid-set! + (make-module-ref loc module sym #t) + (make-module-ref loc runtime 'void #t))))))) (define (ensure-fluids-for loc syms module . body) @@ -419,6 +425,9 @@ ((function (lambda ,args . ,body)) (guard (not (null? body))) (compile-lambda loc args body)) + (('quote ,val) + (make-const loc val)) + ; Function calls using (function args) standard notation; here, we have to ; take the function value of a symbol if it is one. It seems that functions ; in form of uncompiled lists are not supported in this syntax, so we don't @@ -430,9 +439,6 @@ (compile-expr func)) (map compile-expr args))) - (('quote ,val) - (make-const loc val)) - (else (report-error loc "unrecognized elisp" expr)))) diff --git a/module/language/elisp/runtime.scm b/module/language/elisp/runtime.scm index 871f3a297..afdf59152 100644 --- a/module/language/elisp/runtime.scm +++ b/module/language/elisp/runtime.scm @@ -20,9 +20,35 @@ ;;; Code: (define-module (language elisp runtime) - #:export (void ensure-fluid! set-value! get-value unbind! bound?)) + #:export (void nil-value t-value elisp-bool) + #:export-syntax (built-in-func)) ; This module provides runtime support for the Elisp front-end. + ; The reserved value to mean (when eq?) void. + (define void (list 42)) + + +; Values for t and nil. + +; FIXME: Use real nil. +(define nil-value #f) +(define t-value #t) + + +; Convert a scheme boolean to Elisp. + +(define (elisp-bool b) + (if b + t-value + nil-value)) + + +; Define a predefined function; convenient macro for this task. + +(define-macro (built-in-func name value) + `(begin + (define-public ,name (make-fluid)) + (fluid-set! ,name ,value))) diff --git a/module/language/elisp/runtime/function-slot.scm b/module/language/elisp/runtime/function-slot.scm index e878e7e17..0327e2ca4 100644 --- a/module/language/elisp/runtime/function-slot.scm +++ b/module/language/elisp/runtime/function-slot.scm @@ -19,6 +19,83 @@ ;;; Code: -(define-module (language elisp runtime function-slot)) +(define-module (language elisp runtime function-slot) + #:use-module (language elisp runtime)) -; This module contains the function-slots of elisp symbols. +; This module contains the function-slots of elisp symbols. Elisp built-in +; functions are implemented as predefined function bindings here. + + +; Number predicates. + +(built-in-func floatp (lambda (num) + (elisp-bool (and (real? num) + (not (integer? num)))))) + +(built-in-func integerp (lambda (num) + (elisp-bool (integer? num)))) + +(built-in-func numberp (lambda (num) + (elisp-bool (real? num)))) + +(built-in-func wholenump (lambda (num) + (elisp-bool (and (integer? num) + ((@ (guile) >=) num 0))))) + +(built-in-func zerop (lambda (num) + (elisp-bool ((@ (guile) not) ((@ (guile) =) num 0))))) + + +; Number comparisons. + +(built-in-func = (lambda (num1 num2) + (elisp-bool ((@ (guile) =) num1 num2)))) +(built-in-func /= (lambda (num1 num2) + (elisp-bool ((@ (guile) not) ((@ (guile) =) num1 num2))))) + +(built-in-func < (lambda (num1 num2) + (elisp-bool ((@ (guile) <) num1 num2)))) +(built-in-func <= (lambda (num1 num2) + (elisp-bool ((@ (guile) <=) num1 num2)))) +(built-in-func > (lambda (num1 num2) + (elisp-bool ((@ (guile) >) num1 num2)))) +(built-in-func >= (lambda (num1 num2) + (elisp-bool ((@ (guile) >=) num1 num2)))) + +(built-in-func max (lambda (. nums) + ((@ (guile) apply) (@ (guile) max) nums))) +(built-in-func min (lambda (. nums) + ((@ (guile) apply) (@ (guile) min) nums))) + +(built-in-func abs (lambda (num) + ((@ (guile) abs) num))) + + +; Number conversion. + +(built-in-func float (lambda (num) + (if (exact? num) + (exact->inexact num) + num))) + +; TODO: truncate, floor, ceiling, round. + + +; Arithmetic functions. + +(built-in-func 1+ (@ (guile) 1+)) +(built-in-func 1- (@ (guile) 1-)) +(built-in-func + (@ (guile) +)) +(built-in-func - (@ (guile) -)) +(built-in-func * (@ (guile) *)) +(built-in-func % (@ (guile) modulo)) + +; TODO: / with correct integer/real behaviour, mod (for floating-piont values). + + +; Floating-point rounding operations. + +(built-in-func ffloor (@ (guile) floor)) +(built-in-func fceiling (@ (guile) ceiling)) +(built-in-func ftruncate (@ (guile) truncate)) +(built-in-func fround (@ (guile) round))