[gambit-list] How to work with the splitted unversal backend?

ben yakawp ben at yakawp.com
Thu Nov 26 13:12:33 EST 2015


Marc,
thanks for your detailed answer. That was a lot more than I was hoping
for.
I thought, I would add the Perl language as an additional backend
because I know the language and its limitations pretty well and it's
syntactically close to Php.

If Alexandre  could send me the document you mentioned, that'd be really
nice.

Regards
ben


On Tue, Nov 24, 2015, at 05:49 PM, Marc Feeley wrote:
> The split is roughly as follows:
> 
>   _univadt.scm     macros for code emitter abstractions such
>                    as (^if test then else) and (^cons car cdr)
> 
>   _t-univ-1.scm    procedures for generic code emitter abstractions
>                    such as (univ-emit-if …)
> 
>   _t-univ-2.scm    code generation for the runtime library such as
>   println
> 
>   _t-univ-3.scm    procedures for “Scheme level” code emitter
>   abstractions
>                    such as (univ-emit-cons …)
> 
>   _t-univ-4.scm    code generation for Gambit primitives, such
>                    as ##cons, ##fx+, …
> 
> To add a new target language, say for the language Lua (a random choice),
> you need to:
> 
> 1) Add to _t-univ-1.scm a declaration of that target language:
> 
> (univ-setup 'lua '((".lua" . Lua)) '() '())
> 
> This will allow calling gsc with: gsc -target lua foo.scm
> to generate “foo.lua”.
> 
> 2) Extend the code emitters in _t-univ-1.scm and _t-univ-3.scm for Lua. 
> For example, to generate “if” statements the procedure univ-emit-if must
> be modified by adding a case for “lua” which uses the “if <expr> then
> <statement> else <statement> end” syntax:
> 
> (define (univ-emit-if ctx test true #!optional (false #f))
>   (case (target-name (ctx-target ctx))
> 
>     ((js php java)
>      (^ "if (" test ") {\n"
>         (univ-indent true)
>         (if false
>             (^ "} else {\n"
>                (univ-indent false))
>             (^))
>         "}\n"))
> 
>     ((python)
>      (^ "if " test ":\n"
>         (univ-indent true)
>         (if false
>             (^ "else:\n"
>                   (univ-indent false))
>             (^))))
> 
>     ((ruby)
>      (^ "if " test "\n"
>         (univ-indent true)
>         (if false
>             (^ "else\n"
>                (univ-indent false))
>             (^))
>         "end\n"))
> 
>     ((lua)
>      (^ "if " test " then\n"
>         (univ-indent true)
>         (if false
>             (^ "else\n"
>                (univ-indent false))
>             (^))
>         "end\n"))
> 
>     (else
>      (compiler-internal-error
>       "univ-emit-if, unknown target"))))
> 
> 3) Extend the runtime library code generators in _t-univ-2.scm for Lua. 
> For example, for I/O the println procedure can use Lua’s io.write()
> function:
> 
>     ((println)
>      (rts-method
>       'println
>       '(public)
>       'noresult
>       (list (univ-field 'obj 'str))
>       "\n"
>       '()
>       (lambda (ctx)
>         (let ((obj (^local-var 'obj)))
>           (case (target-name (ctx-target ctx))
>             ((js)
>              (^if (^prop-index-exists?
>                    "function () {return this;}()"
>                    (^str "console"))
>                   (^expr-statement
>                    (^call-prim (^member (^global-var 'console) 'log)
>                                obj))
>                   (^expr-statement
>                    (^call-prim "print"
>                                obj))))
>             ((python)
>              (^expr-statement (^call-prim "print" obj)))
>             ((ruby php)
>              (^ (^expr-statement (^call-prim "print" obj))
>                 (^expr-statement (^call-prim "print" (^str "\\n")))))
>             ((java)
>              (^expr-statement
>               (^call-prim (^member (^member 'System 'out) 'println)
>               obj)))
>             ((lua)
>              (^expr-statement
>               (^call-prim (^member 'io 'write) obj (^str "\\n"))))
>             (else
>              (compiler-internal-error
>               "univ-rtlib-feature println, unknown target")))))))
> 
> 4) There are minimal changes to extend _t-univ-4.scm for Lua, unless you
> want to add new Scheme primitives (but in that case you also need to add
> the primitives to _prims.scm).
> 
> The development process of a new target backend can be guided by the unit
> tests.  The unit tests start by testing simple things (such as verifying
> that println works on numbers and strings) and gradually work up to
> testing (almost) all the features of Gambit.  So by running the unit
> tests (with ./runtests.scm -lua) you can see what is the next
> unimplemented feature to work on.
> 
> What is the target language you are interested in adding?  My student,
> Alexandre St-Louis Fortier, has been helping out with implementing the
> universal backend and can help you understand what needs to be done.  He
> has prepared a document explaining how the various parts of the universal
> backend fit together.  Alexandre, can you send a copy to Ben?
> 
> Marc
> 
> > On Nov 24, 2015, at 4:20 AM, ben yakawp <ben at yakawp.com> wrote:
> > 
> > hi
> > 17 days ago you commited a change with:
> > "Universal backend: split _t-univ.scm into 4 files to improve build time
> > "
> > 
> > I try to understand how the backend works, especially how all the host
> > interop/ffi is implented across the different targets. Together these 4
> > files make almost 16'000 lines of code, which are splitted with
> > quantitative criteria in mind. That makes the process of understanding
> > and the possible task of adding a new backend hard. Is there a semantic
> > structure behind the splits? That would help.
> > 
> > ben
> > _______________________________________________
> > Gambit-list mailing list
> > Gambit-list at iro.umontreal.ca
> > https://webmail.iro.umontreal.ca/mailman/listinfo/gambit-list
> 



More information about the Gambit-list mailing list