ox-lang / ox

Ox - An immutable statically typed Lisp for the JVM
https://ox-lang.org
66 stars 3 forks source link

Broken build: Feature expression support #5

Closed arrdem closed 9 years ago

arrdem commented 9 years ago

According to puredanger the following are valid host expressions:

#+cljs foo

#+(or cljs clj) foo

#+(and clj foo) bar

Neither of the latter two are listed here: research and figure out what needs to be supported. http://dev.clojure.org/display/design/Feature+Expressions

mikera commented 9 years ago

Maybe I'm stupid, but host expression support feels like a bit of an ugly hack. Why does it justify a special syntax?

IMHO It's just a special case of evaluating something differently based on a compile time check.

I was playing with the idea of being able to "unquote" and execute arbitrary code at compile time, something like:

~(when (some-host-check?) `(call-host-specific-code)) 

Obviously that could probably be made prettier with some macro magic but hopefully gives you the idea....

arrdem commented 9 years ago

Clojure prides itself on its host interop, and I've repeatedly seen the arugment that were it not for Clojure's very permissive host interop story Clojure wouldn't have taken off the way it has. I think this is compelling, especially because most of the really early libraries for Clojure were just wrappers around existing Java tooling. In fact Java "drivers" are still a huge part of the ecosystem so I think it's safe to say that we "need" strong interop stories both here and in Clojure(Script).

Looking at Projects that use cljx, it seems to me that a common pattern is to have namespace isolation for different platform's implementation(s) which expose the same set of defs as an API and to use cljx to choose which one you intend to load in a given context. The other "common" use case of cljx seems to be monkey patching single forms when some small subexpression requires a different implementation on different hosts due to discrepencies in the standard libraries.

The former, conditionalized requires, I think is entirely reasonable. It's also in keeping with how traditional C projects will use the preprocessor to select which specific implementation to #include. I would argue that this behavior would be better provided not by reader support but rather by host postfixed loading, so when attempting to find the file implementing a given namespace a language implementation will first check the "host specific" file extension (say .oxj for JVM Oxlang) and then the "common" platform independent file extension here .ox which may contain no host interop forms.

The latter is a failure in the language implementation(s) to provide a consistent API across platforms and should be resolved either by refactoring so that host conditional loading can be used or should be addressed at the language level.

TL;DR Oxlang probaly won't have host exprs, I'm just supporting them for now because I want to start with a "working" 1.7 grammar.

arrdem commented 9 years ago

Okay. Fixed the build, and Oxlang kinda-sorta supports host expressions in that the parser will emit a sane read-eval form to check the features in the evaluation current context. How read-eval deals with form discarding in the failure is not defined yet, but will be shared with form discard.

Not sure if either of these are strictly good ideas but I'll keep them for now.

arrdem commented 9 years ago
ox.lang.parser> (parse-string "(lambda (x) (try (+ x 1) (catch #+cljs js/Error #+clj Exception e 0)))")
=> (lambda (x)
     (try (+ x 1)
          (catch (read-eval (when (eval-feature-expr 'cljs) js/Error))
                 (read-eval (when (eval-feature-expr 'clj) Exception))
                 e 0)))