alex-eg 48a3d06925 move Sex to better types
Types, fns and vars are now written in another, better, more intuitive
and readable way.

Types:
"pointer to const char" is "* const char"
"array of pointers to volatile int" is "[* volatile int]"
Read left to right

Vars (as well as fn args, struct fields):
(var name type)
(struct vec3 ((x float) (y float) (z float))
(fn vec3-add ((v1 vec3) (v2 vec3)) vec3 ...)

Also fns are now have return types after arg list.

* is now must not be attached to any type name (or variable for that
matter)
2025-10-30 18:05:44 +03:00
2025-10-30 18:05:44 +03:00
2025-10-30 18:05:44 +03:00
2025-09-29 15:56:51 +03:00
2025-10-01 15:54:17 +03:00
2025-10-30 18:05:44 +03:00
2025-06-09 00:30:14 +03:00
2025-10-16 15:38:00 +03:00
2025-10-01 14:10:42 +03:00
2025-08-22 15:47:36 +03:00
2025-10-30 18:05:44 +03:00
2025-10-16 15:38:51 +03:00
2025-09-30 09:35:16 +03:00
2025-10-30 18:05:44 +03:00

The Sex language

./sex.png

Sex is a S-expressions language. Sex is written in Chicken, which is a 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

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

Compiling Hello World

sexc ./examples/hello-world.sex -o hello

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:

(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)

Compile and run:

~/dev/sex $ ./sexc ./example/hello-world.sex -o hello-world
~/dev/sex $ ./hello-world
Hello from Sex!
What is your name?
Alex
Hello, Alex!

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
(pub defmacro (list-T type)
  (let ((list-type (cat 'list- type)))
    `(struct ,list-type
       ((,type value)
        ((* ,list-type) next)))))

(list-T int)

->

(struct list_int
 ((int value)
  ((* list_int) next)))
Wrapper for checking return codes
(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)
...)

->

(%fun int init ()
  (if (< 0 (SDL_Init SDL_INIT_VIDEO))
    (%begin (puts "Failed to initialize SDL") (return 1)))
  ...)
}

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:

(use-package sex-mode
  :load-path "/path/to/sex"
  :mode ("\\.sex\\'"))
Description
Sex: for passionate software developers.
Readme 2.1 MiB
Languages
Scheme 92%
Makefile 6.1%
Emacs Lisp 1.9%