-
Notifications
You must be signed in to change notification settings - Fork 62
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add ppx. #89
Add ppx. #89
Conversation
@Drup Regarding #72, eventually, all attributes whose TyXML functions don't have "normal" names should be marked with |
This is incredible work ! I'll review a bit later, but just to answer some of your comment:
Also, is it possible to only raise warnings for those errors ?
You can look at lwt's ppx for an example.
|
I'm open to changing the name of the quotation. However, I want to note that it is already possible to have a pure SVG quotation. You simply write SVG and Markup.ml will detect what it is: let _ = [%tyxml "<g/>"] let _ = [Svg.g (Svg.Xml.W.nil ())] Unfortunately, this is problematic with the |
👍 I need this! |
I'm reading through the code more seriously this time. It's actually a bit bigger than I expected
|
I wasn't aware of ppx_tools/rewriter, but it makes sense. By "not very reasonable", do you mean that it is packaged as a ppx whose actual purpose is a side effect? In that case, I agree. Otherwise, please clarify. Also, please let me know soon if '"probably" going to do it [yourself]' becomes definitely will or will not, so I can decide what to focus on. Do you want me to wait on amendments so you can make the coding style adjustment, or you want to do it at the end? |
That, and the raw string emission. I'm definitely going to do it, yes. I'm putting them there: https://github.com/ocsigen/tyxml/tree/ppx |
@aantron Could you detail what should be the content of labeled_attributes exactly ? The implementation of reflect seems to contain a weird heuristic which doesn't work anymore on 4.03. |
@aantron I realized we can't transform ppx_reflect into a proper ppx: the input is a signature and the ouput is a module. I cleaned up the code emission to use ast_helper instead. I changed Str into Re_str, but we still need to replace it by proper use of re, but it can wait. |
@Drup: Oops, I somehow missed the question about I can change to proper usage of re – it shouldn't be a problem. BTW, the only reason I used What is your approximate time table for releasing 4.0? I don't, of course, intend to be making last-minute changes – hope to be done, except for nits, well before release. But I do need to take a bit more of a break from (public) OCaml, at the moment. |
When it's ready, as early as possible. End of week would be nice.
Then I really don't understand the code. Why are you using this sort of weird heuristic instead of just looking if there is a label ? |
Can you clarify what you mean by heuristic? Are you referring to the additional filtering beyond just looking for labels? Not all labeled are arguments are used to pass attributes, some are used to pass child elements, such as |
By heuristic, I'm mostly talking about things like that. |
Yes, in 4.02 the first case matches types of the form This code does not make sense as is with the different representation of labeled arguments in 4.03. In any case, even for the 4.02 version, I need to rearrange it and comment it. I had trouble comprehending it a month on after writing it. By the way, what are we doing about the parts of the AST that are incompatible between 4.02 and 4.03? |
As discussed, I pushed a version that replaces the handling of antiquotations by inserting dummy elements, letting markup work and replace them afterwards. It's quite brittle right now, since everything is accepted everywhere. I'll revisit tomorrow.
I would really like to avoid cppo, so we will have to be creative. :]
I think we should just annotate such functions arguments with [@attributes]. It's only for special labeled attributes, there aren't that many of them, so it's fine. |
Ok, thanks. Do you want to apply this to attribute antiquotations yourself as well, or I will do it?
I haven't done an exhaustive search recently, but IIRC the only sore point now is the new type
In that case we will have to maintain a small parser for that kind of annotation. IMO it's much easier to keep the approach we have now. The labeled argument attributes are actually quite regular, in that their name always matches the name of the attribute, and their nature is always given by their type ( |
let gen_token, find_expr = | ||
let r = ref 0 in | ||
let tbl = H.create 17 in | ||
let make_id () = incr r ; "tyxml" ^ string_of_int !r in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems to me that a more "distinctive" (ugly) prefix than tyxml
would be a good idea.. just in case of conflict with something the user chooses somehow.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that can be changed later easily, let's make it work before :)
So, the new implementation of the placeholder ... is a bit tricker than expected. Issues are things like that: utop # [%tyxml "<p>foo" (pcdata "bar") "</p>"] ;;
let _ = [Html5.p (Html5.Xml.W.cons (Html5.pcdata "footyxml1") (Html5.Xml.W.nil ()))];;
- : [> Html5_types.p ] Html5.elt list = [<p>footyxml1</p>]
utop # [%tyxml "<p id=foo"bla"></p>"] ;;
let _ = [Html5.p ~a:[Html5.a_id (Html5.Xml.W.return "footyxml1")] (Html5.Xml.W.nil ())];;
- : [> Html5_types.p ] Html5.elt list = [<p id="footyxml1"></p>] Basically, we need to do plaintext search. I'm not really fond of the idea. We also need a better token (with a terminator, in particular). |
Yeah, I assumed you were going to do a search in content. It's trickier for attributes, however, because not all attribute types support a (immediately) sensible notion of concatenation (e.g. concatenating a prefix |
@aantron Ok, the whole thing is implemented now. The error cases are mostly decent. I need to clean up a bit more, but that's okay. Locations need a lot of work, though. There is one error case that is not great: # let bar = "p" [%tyxml "<"bar">" "</"bar">"] ;;
Error: Bad token '(' in tag: invalid start character It should be rejected, clearly, but we need a better failure mode.
I decided to simply forbid it. It's simpler and more uniform. It works quite well now! :) |
@aantron I completed the test framework to work with the ppx (and added some basic ones). |
I just added comment handling. @aantron What is ``PI` ? |
``PI |
I fixed up ppx_reflect a bit wrt argument extraction, so it should be a bit more ready for 4.03 (not tested yet, will do a second run when we have the bits we need in ppx_tools). I also added the following form in the ppx extension:
|
Alright. Regarding locations, are you going to fix them, since you're on a roll? Let me know if you want me to jump in :p Taking care of 2. in aantron/markup.ml#12 as per IRC discussion, but still thinking about it more carefully first. |
Next things I plan to do:
|
Ok, after giving it more thought, I'm not convinced that specifying the language to Markup.ml is necessary for usage in TyXML (or a good idea). Given that it would have a complicated interaction with element context, I'd rather put it on hold. For TyXML's
I think that covers all cases – IIRC EDIT: I guess I could move this kind of check into Markup.ml (modulo special-casing of |
If you are keeping the |
Use Re_str temporarly.
Also added OPAM dependency on ppx_tools and conditioned building of ppx_reflect on --enable-ppx.
It works with string only because we emit a .ml, it wouldn't work if we were giving the generated AST to the compiler ...
Accepted syntaxes: %tyxml (auto) %(tyxml.)html5(.Mod) %(tyxml.)svg(.Mod)
Only builds by the "make" command are fixed by this change.
TyXML does not have <frameset> or <frame>, so these attributes are pointless. Also removed PPX machinery for handling these attributes' values.
Let's merge this first version, we will continue work in various other PRs! |
🎉 Agreed. The PR was getting quite monstrous. |
This looks good. I also think we don't need the |
This is a preliminary (but working) implementation of a PPX rewriter for TyXML, based on the HTML5 parser in Markup.ml. Here are usage examples, paired with the dumped TyXML expressions that are generated:
Basic
Antiquotation
SVG
Errors have location information, although without aantron/markup.ml#6, these are points instead of ranges, and, for errors inside a tag, the location reported is the start of the tag:
This would resolve #68. I will amend the commit to say "Closes #68" before this is merged into master, when review is done.
This makes TyXML depend on Markup.ml. However, projects using TyXML would not pull in Markup.ml as a run-time dependency, because it is used only in TyXML's PPX.
How it works and reading order
The PPX itself does a pretty straightforward translation of a Markup.ml signal stream into a TyXML expression tree. However, since different TyXML elements and attributes have different signatures, some type information is needed for the PPX to be able to assemble the TyXML tree correctly. This type information is generated by a second PPX rewriter called
ppx_reflect
, which is a build tool that runs onhtml5_sigs.mli
,svg_sigs.mli
, andhtml5_types.mli
.For a bottom-up review, you can look at the files in order:
ppx_common.mli
,ppx_attribute_value.mli
,ppx_element_content.mli
,ppx_sigs_reflected.mli
,ppx_reflect.ml
,ppx_namespace.mli
,ppx_attribute.mli
,ppx_element.mli
,ppx_tyxml.ml
.Notes
\n
, or by creating a new line in the file? This affects how source location information is reported. I chose to always assume the latter, because it seems that people would want to have a multiline template more than inserting pointless\n
escapes into markup meant for TyXML trees – unless, perhaps, they are creating<pre>
elements.Issues
(Edited to reflect status)
<input>
min
,max
. Is there a good library for parsing this?xmlns
,xml:space
, etc.Ppx_attributes.parse
andPpx_tyxml.markup_expr
.in a comment in the code).
Html5
, and similarly there will be a moduleSvg
. This is in line with whatpa_tyxml
expects. However, these obviously shadow the realHtml5
andSvg
.pcdata
and other combinators.a
, because there area
elements in both HTML and SVG. Deal with this.a_fs_rows
anda_fs_cols
.Also, as we have agreed, the PPX would benefit from having a test suite (as would the rest of TyXML).