Introducing Sex SEMantic ENgine: the semen. Also split reader to other file (it can be replaced in the future). Macro expansion inside Sex code doesn't work yet, and it must be done in semen, not during fmt-c generation as before.
148 lines
4.2 KiB
Org Mode
148 lines
4.2 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]].
|
|
|
|
* 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
|
|
-E, --preprocess Emit C code
|
|
--public-interface Get module's public interface
|
|
-h, --help Show this help
|
|
-m, --macro-expand Emit macro-expanded Sex code
|
|
-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 unkebabification
|
|
For hardcore fans of traditional Lisp naming convention,
|
|
Sex offers automatic unkebabification 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
|