* The Sex language #+NAME: the Sex logo #+ATTR_HTML: :width 300px [[sex.png][file:./sex.png]] Sex is a S-expressions language. Sex is written in Chicken, which is an [[https://call-cc.org][R7RS Scheme]]. Sex is statically typed, compiled general purpose language. * Compilation First, get yourself a Chicken, then, some Chicken deps. You also will need a C compiler. ** Install Chicken Eggs Tip: there's a way to make Chicken install eggs non-globally. You need to export ~CHICKEN_INSTALL_REPOSITORY~ and ~CHICKEN_REPOSITORY_PATH~ environment variables. Refer to the documentation for more info: https://wiki.call-cc.org/man/5/Extension%20tools#changing-the-repository-location ~chicken-install `cat dependencies.txt`~ ** Compilation ~make~ * Usage ** Summary #+begin_src Usage: sexc [options] filename [-- options-for-c-compiler] Options: --c-compiler=ARG Select C compiler. Defaults to value of SEX_CC environment variable, or if it is empty, to cc -c, --compile-object Compile object file instead of executable program -C, --preprocess Emit C code --public-interface Get module's public interface -h, --help Show this help -m, --macro-expand Emit macro-expanded semantically processed Sex code (sort of IR). May be useful for debugging -o, --output=ARG Write output to file. Default file name is a.out. If -E or -m options are provided, defaults to stdout #+end_src ** Compiling Hello World #+begin_src shell sexc ./examples/hello-world.sex -o hello #+end_src That's it. Now you should have executable named ~hello~ in your directory. Sex uses C under the hood, the default C compiler is ~cc~, but you can pass any using ~--c-compiler~ option, or by setting ~SEX_CC~ environment variable. Everything after ~--~ is handed to the C compiler exactly as written: #+begin_src shell sexc example/sdl3-triangle.sex -o triangle -- `pkg-config --cflags --libs sdl3` -framework OpenGL #+end_src ** Example An example of Sex source: #+begin_src scheme (include stdio.h) (pub fn main ((argc int) (argv [* const char])) int (puts "Hello from Sex!") (var name [char 512]) (puts "What is your name?") (scanf "%s" (cast (& name) (* char))) (printf "Hello, %s!\n" name) (return 0)) #+end_src Compile and run: #+begin_src shell ~/dev/sex $ ./sexc ./example/hello-world.sex -o hello-world ~/dev/sex $ ./hello-world Hello from Sex! What is your name? Alex Hello, Alex! #+end_src * Features ** Full C interoperability Just ~(include "Your/Favourite/Library.h")~ and use it as you would have is C. *** Auto kebabification For hardcore fans of traditional Lisp naming convention, Sex offers automatic kebabification of all symbols, i.e. no more ugly ~GL_ARRAY_BUFFER~ s in your code, they may be written in their proper form: ~GL-ARRAY-BUFFER~. ** Modules Each source file is a module. Module can provide public interface and be imported by using ~(import path/to/module)~ expression. Module search path consists of two parts: first is relative to the source being compiled location, and the second is ~SEX_MODULE_PATH~ environment variable. Module's public interface consists of everything declared ~pub~. Structures, function, macros, types, variables can be public. ** Syntactic macros Sex has support for syntactic macros. Macro definitions look like functions: they have a name, an argument list and a body. Macro should return Sex code. *** Examples: **** Structure with templated value type #+begin_src scheme (pub defmacro (list-T type) (let ((list-type (cat 'list- type))) `(struct ,list-type ((value ,type) (next (* ,list-type)))))) (list-T int) #+end_src -> #+begin_src scheme (struct list_int ((value int) (next (* list_int)))) #+end_src **** Wrapper for checking return codes #+begin_src scheme (pub defmacro (check-sdl-return call message ret-code) `(if (< 0 ,call) (do (puts ,message) (return ,ret-code)))) (pub fn init () int (check-sdl-return (SDL-Init SDL-INIT-VIDEO) "Failed to initialize SDL" 1) ...) #+end_src -> #+begin_src scheme (pub fn init () int (if (< 0 (SDL_Init SDL_INIT_VIDEO)) (do (puts "Failed to initialize SDL") (return 1))) ...) #+end_src ** Compile-time type information Sex has a number of type reflection features, aiming to help with macro writing. During the compilation, all type info is collected, and is accessible during macro expansion. This allows us to write things like providing auto serialization, adding meta information, and so on. ** Use an established environment for development As Sex is S-expressions, you always have Emacs with paredit as your best option. *** sex-mode.el To harness the power of sex-mode, add the following lines to your ~$HOME/.config/emacs/init.el~: #+begin_src emacs-lisp (use-package sex-mode :load-path "/path/to/sex" :mode ("\\.sex\\'")) #+end_src