* 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 a [[https://call-cc.org][R5RS 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. ** 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) (begin (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)) (begin (puts "Failed to initialize SDL") (return 1))) ...) } #+end_src ** 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