Files
sex/Readme.org
2025-09-26 14:51:44 +03:00

150 lines
4.3 KiB
Org Mode

* The Sex language
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 fmt getopt-long brev-separate test tree srfi-1 srfi-13 srfi-69 matchable~
** 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 int main ((int argc) (char **argv))
(puts "Hello from Sex!")
(var (array char 512) name)
(puts "What is your name?")
(scanf "%s" (cast char* &name))
(printf "Hello, %s!\n" name)
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
((,type value)
((* ,list-type) next)))))
(list-T int)
#+end_src
->
#+begin_src scheme
(struct list_int
((int value)
((* list_int) next)))
#+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 int init ()
(check-sdl-return
(SDL-Init SDL-INIT-VIDEO) "Failed to initialize SDL" 1)
...)
#+end_src
->
#+begin_src c
(%fun int init ()
(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