how to wrap functions from a context without prefixing?

Started by conan, June 19, 2013, 05:50:58 PM

Previous topic - Next topic

conan

This is a mock-up to simplify my question.

I got these scheme:



[*]hin.lsp

(context 'hin)

(define (hin-show)
(println "from hin.lsp"))


  • [*]wrappers.lsp

    (load "hin.lsp")

    (define (wrap-one)
    (context hin)
    (hin-show) ; this wont work
    (context MAIN))


  • [*]main.lsp

    (load "wrappers.lsp")

    (wrap-one)
  • [/list]


    File hin.lsp contains 244 symbols (functions and constants) autogenerated. It's a DSL for HTML5.



    File wrappers.lsp contains functions to wrap snippets of reusable code like: header, navbar, sidebar, you-get-the-idea.



    File main.lsp calls functions from wrappers.lsp.



    Now, the context switch shown in function wrap-one wont produce the desired result. I think it's because the double pass newlisp parser does. So on the first pass (hin-show) gets transformed into (MAIN:hin-show).



    The idea of hin.lsp is to be able to wrote code like this:

    (html lang= "en"
    (head
    (title "Some title"))
    (body
    (p class= "shiny" "Lore ipsum...")))


    If I have to prefix every call with "hin:" or even with an alias like "h:" hin's while purpose is defeated, which is to be as close to HTML syntax as possible.



    My question is: what's the best way to wrap functions calls from hin inside a function defined in another context without prefixing hin calls?



    I'm trying to build a macro to parse those calls by my own and prefix when appropriate, it will be used like this:

    (define (wrap-one)
    (wrap-in-context
    (...))) ; calls to hin functions


    But I'm having problems recurring inside the macro. And now I'm thinking all this extra parsing could make the whole idea to work too slow. Anyway, I'm digressing. Back to the point: any ideas about how to avoid prepending all calls with context name?

    xytroxon

    #1
    Here is a small example of how newLISP can use the power of

    "context" to create an html5 dsl.



    ; This module and program code is run
    ; together as one file to make it easier
    ; to experiment with.

    ; ----------------------------------------
    ; module file "html5.lsp" code section

    (context 'html5)

    (define (html5:html) (string "<html>" (join (args)) "</html>"))
    (define (html5:head) (string "<head>" (join (args)) "</head>"))
    (define (html5:title) (string "<title>" (join (args)) "</title>"))
    (define (html5:body) (string "<body>" (join (args)) "</body>"))
    (define (html5:div) (string "<div>" (join (args)) "</div>"))
    (define (html5:h1) (string "<h1>" (join (args)) "</h1>"))
    (define (html5:p) (string "<p>" (join (args)) "</p>"))

    (context MAIN)

    ; -----------------------------------------
    ; program file code section
    ; uncomment next line when code is in two files
    ;(load "html5.lsp")

    ; create copy of html5 context
    (new html5 'page)

    ; switch into the copy of html5 context
    (context page)

    ; Welcome to a DSL (Domain Specific Language)
    ; for working with html5 tags
    ; No more: (html5:html (html5:head...
    ; Just use: (html (head ...

    ; Note inside this context "div" is now redefined.
    ; If you need to divide, use (MAIN:div num1 num2)
    ; But only because it was redefined in this context
    ; (add num1 num2) does not need to be (MAIN:add num1 num2) etc...

    (setq output
      (html
        (head
          (title "page title")
        )
        (body
          (div
            (h1 "Page Heading")
            (p "Text for page.")
          )
        )
      )
    )
    (context MAIN)

    (println page:output)
    ; Uncomment next line to make html page
    ; that you can view in browser.
    ;(write-file "my.html" page:output)
    (exit)


    -- xytroxon
    \"Many computers can print only capital letters, so we shall not use lowercase letters.\"

    -- Let\'s Talk Lisp (c) 1976

    conan

    #2
    Thanks for your reply xytroxon. However I'm looking for a different concept. I'm still not there, but my idea is that only proper HTML5 code comes from my DSL, my objective is to produce valid HTML without the need to validate it.



    Anyway I found a partial answer to my previous question, first I did this wraper:

    (define-macro (wrap-in-context:wrap-in-context ctx-new)
    (eval
    (doargs (arg)
    (read-expr
    (replace {w+:} (string arg) "" 0) (eval ctx-new)))))


    Problem is that it replaces any context, so I wrote another one:

    (define-macro (replace-this-context:replace-this-context ctx-old ctx-new)
    (eval
    (doargs (arg)
    (read-expr
    (replace (string (eval ctx-old) ":") (string arg) "" 0) (eval ctx-new)))))


    And it kind of solves my issue, but I'm still not satisfied because while I can wrap data in a context different from the one I'll replace, I cannot build functions with arguments, because those arguments get the context I wanna replace. So I have to juggle with data, and that's not cool.



    So I'm still looking for a better solution.



    Anyway, if you or someone else wanna take a look, I just uploaded it here:



    https://github.com/conan-lugmen/newlisp-hin.git">//https://github.com/conan-lugmen/newlisp-hin.git



    Please note it's not alpha nor beta software... maybe omega :P



    Current work is still in the dev branch, master is old and probably non-functional. Also I found a couple of bugs recently that are becoming hard to track with the current definition if hin:hin (which grew too big), so I'll be changing stuff there these days.