Returning a symbol from C code added by jacius on Thu Apr 8 07:19:13 2021


;;; Goal: Use a C switch statement to perform a fast lookup of an
;;; integer constant and return a symbol. (In the real code there are
;;; about 300 integer constants to lookup.)
;;;
;;; Are there any problems (e.g. memory leaks) with this approach?
;;; Is there a better way to do this?


(import (chicken base)
        (chicken foreign)
        (chicken format))

#>
enum {
  FOO,
  BUZZ,
  THIS_IS_AN_EXTREMELY_LONG_INTEGER_CONSTANT_NAME
};
<#

(define FOO (foreign-value FOO int))
(define BUZZ (foreign-value BUZZ int))
(define THIS_IS_AN_EXTREMELY_LONG_INTEGER_CONSTANT_NAME
  (foreign-value THIS_IS_AN_EXTREMELY_LONG_INTEGER_CONSTANT_NAME int))

(define ->symbol
  (foreign-primitive
   ((int x))
#<<EOF
     C_word av[2+1] = {C_SCHEME_UNDEFINED, C_k, C_SCHEME_FALSE};
     C_word* a;
     switch(x) {
       case FOO:
         a = C_alloc(C_SIZEOF_INTERNED_SYMBOL(sizeof("foo")));
         av[2+1-1] = C_intern2(&a, "foo");
         break;
       case BUZZ:
         a = C_alloc(C_SIZEOF_INTERNED_SYMBOL(sizeof("buzz")));
         av[2+1-1] = C_intern2(&a, "buzz");
         break;
       case THIS_IS_AN_EXTREMELY_LONG_INTEGER_CONSTANT_NAME:
         a = C_alloc(C_SIZEOF_INTERNED_SYMBOL(sizeof("this-is-an-extremely-long-symbol-name")));
         av[2+1-1] = C_intern2(&a, "this-is-an-extremely-long-symbol-name");
         break;
     }
     C_values(2+1, av);
EOF
))


(printf "~A -> ~A [~A]~N"
        FOO
        (->symbol FOO)
        (eq? 'foo (->symbol FOO)))

(printf "~A -> ~A [~A]~N"
        BUZZ
        (->symbol BUZZ)
        (eq? 'buzz (->symbol BUZZ)))

(printf "~A -> ~A [~A]~N"
        THIS_IS_AN_EXTREMELY_LONG_INTEGER_CONSTANT_NAME
        (->symbol THIS_IS_AN_EXTREMELY_LONG_INTEGER_CONSTANT_NAME)
        (eq? 'this-is-an-extremely-long-symbol-name
             (->symbol THIS_IS_AN_EXTREMELY_LONG_INTEGER_CONSTANT_NAME)))