Giter Club home page Giter Club logo

dolorem-c's Introduction

Overview

This is a simplified version of shenniger/dolorem to show the basic principle of a dolorem staging system.

Try it online

Try it here: https://shenniger.github.io/try-dolorem-c/

Try it on your own computer

Dependencies

  • Mac OS/Linux (BSD might work)
  • either clang in PATH or libtcc

Compiling it

Just type make. You may need to specify the environment variable CC, especially if you installed libtcc in a non-standard directory.

If you want to use tcc compilation (much, much faster, but currently only works on Linux), use make TCC=1.

First steps

There is some simple example code in this repository. To run it, type ./dolorem a.dlr. (Depending on the system, you may need to add . to LD's search path. export LD_LIBRARY_PATH=.:$LD_LIBRARY:PATH should do it.)

Hello, world

Here's a dolorem-c program that prints "Hello, world!" during compilation:

(include "def.dlr")
(defun hello () void (puts "Hello, world!"))
(defmacro run (progn (hello) (make-cexp "" "" "" "")))
(run)

Put this into a file and then call dolorem on it.

The first lines includes the standard macros and headers from "def.dlr". The second line defines a function called hello that calls puts to print the string. Now we need to call hello. The easiest way is to create a macro run that calls hello and then evaluates to nothing and to run that macro after.

Addition

Dolorem-c currently does not come with any kind of arithmetic abilities. Fortunately, this is very easy to change. Suppose we want to create a macro add that generates the C code for adding two numbers. We start with this (with a question mark instead of the return value):

(defmacro add ?)

Since our macro will be multiple lines long, we add progn. Within that, we create two variables, left and right to store the two lowered operands. Note that macro parameters are always stored in an argument named args.

(defmacro add (progn
  (:= left (lower (car args)))
  (:= right (lower (car (cdr args))))
 ?))

We now have two cexps. Their context, global, header attributes will simply needed to be added together to reach the result and their expression attribute will be (left.expression)+(right.expression). To do this, we first call add-cexp to add everything of the right to left. This function helpfully leaves left.expression untouched. We then call set-expression to set the expression and return the changed left.

(defmacro add (progn
  (:= left (lower (car args)))
  (:= right (lower (car (cdr args))))
  (add-cexp left right)
  (set-expression left (print-to-mem "(%s) + (%s)" (get-expression left) (get-expression right)))
 left))

This is our finished add macro. We can use it like this: (printf "1+1=%i\n" (add 1 1)).

dolorem-c's People

Contributors

shenniger avatar

Watchers

Nada Amin avatar  avatar

dolorem-c's Issues

make on mac

% make
gcc -c -Wall -Wextra -fpic main.c -o main.o -g -O0 
gcc -c -Wall -Wextra -fpic list.c -o list.o -g -O0 
gcc -c -Wall -Wextra -fpic cgen.c -o cgen.o -g -O0 
gcc -c -Wall -Wextra -fpic hashmap.c -o hashmap.o -g -O0 
gcc -c -Wall -Wextra -fpic include.c -o include.o -g -O0 
gcc -c -Wall -Wextra -fpic lower.c -o lower.o -g -O0 
lower.c:8:10: fatal error: 'libtcc.h' file not found
#include <libtcc.h>
         ^~~~~~~~~~
1 error generated.
make: *** [Makefile:9: lower.o] Error 1

first steps on mac

% ./dolorem a.dlr
compiling the following: [|||void* make_cexp(void* a, void* before, void* global, void* header);]
compiling the following: [|||void* add_cexp(void* a, void* b);]
compiling the following: [|||void append_cexp(void* a, char* a, char* before, char* global, char* header);]
compiling the following: [|||void* call_macro(char* name, void* e);]
compiling the following: [|||void lower_compile(void* a);]
compiling the following: [|||void* car(void* a);]
compiling the following: [|||char* get_expression(void* a);]
compiling the following: [|||char* get_context(void* a);]
compiling the following: [|||char* get_global(void* a);]
compiling the following: [|||char* get_header(void* a);]
compiling the following: [|||void set_expression(void* a, char* b);]
compiling the following: [|||void* cdr(void* a);]
compiling the following: [|||void* lower(void* a);]
compiling the following: [|||void* cdr(void* a);]
compiling the following: [|||void* cons(void* a, void* b);]
compiling the following: [|||char* expect_ident(void* a);]
compiling the following: [|||char* expect_type(void* a);]
compiling the following: [|||void* make_nil_val();]
compiling the following: [|||void* make_int_val(long i);]
compiling the following: [|||void* make_string_val(char* i);]
compiling the following: [|||void* make_ident_val(char* i);]
compiling the following: [|||void* make_char_val(char i);]
compiling the following: [|||char* print_to_mem(char* fmt, ...);]
compiling the following: [|||void lower_mark_as_macro(char* a);]
compiling the following: [|||void puts(char* a);]
compiling the following: [|||int printf(char* fmt, ...);]
compiling the following: [||void* defun(void* args) {
lower_compile(call_macro("function", args));
return make_cexp("", "", "", "");
}
|void* defun(void* args);]
tcc: error: file 'crti.o' not found
tcc: error: library 'c' not found
tcc: error: file 'crtn.o' not found
: ERR: linking failure: dlopen(/tmp/doloutDLXOM9, 0x000A): tried: '/tmp/doloutDLXOM9' (), '/private/tmp/doloutDLXOM9' ()

exercise

I am trying to define a defmacro variant that takes its arguments instead of hard-coding an args parameter. This is how it's used:

(defmacro2 (add left-arg right-arg) (progn
  (:= left (lower left-arg))
  (:= right (lower right-arg))
  (add-cexp left right)
  (set-expression left (print-to-mem "(%s) + (%s)" (get-expression left) (get-expression right)))
 left))

Arguably, it's rather redundant compared to just using args directly since we need to name things after lowering anyways. But it's an exercise for me to play with the system.

This is how I defined it, hardcoding two arguments:

(defmacro comment
  (make-cexp "" "" "" ""))

(comment "how to generalize to N arguments -- need a recursive builder")
(defmacro defmacro2 (progn
  (comment "why is it an error to wrap an expect-ident around the RHS of name")
  (:= name (car (car args)))
  (:= params (cdr (car args)))
  (:= param1 (car params))
  (:= val1 (cons (make-ident-val "car") (cons (make-ident-val "args") (make-nil-val))))
  (:= param2 (car (cdr params)))
  (:= val2 (cons (make-ident-val "car") (cons (cons (make-ident-val "cdr") (cons (make-ident-val "args") (make-nil-val))) (make-nil-val))))
  (:= body (car (cdr args)))
  (call-macro "defmacro" (cons
    name
    (cons
      (cons (make-ident-val "progn")
      (cons (cons (make-ident-val ":=") (cons param1 (cons val1 (make-nil-val))))
      (cons (cons (make-ident-val ":=") (cons param2 (cons val2 (make-nil-val))))
      (cons body (make-nil-val)))))
      (make-nil-val))))
))

Do you know why I am not supposed to use expect-ident on the name?

Next, I'd like to experiment with the variant for any number of arguments. It will require recursion. Any tips?

Thanks.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.