Skip to content

Conversation

@HertzDevil
Copy link
Contributor

@HertzDevil HertzDevil commented Aug 19, 2020

Fixes #62. Also confirmed that it works on qt5.cr, with the exception that I need to alias Qt::CrystalString to Qt::Binding::CrystalString (somewhere Bindgen thinks that CrystalString isn't a binding type because it's configured as a built-in type).

The solution is unsatisfactory; it expands the result of CallBuilder::CrystalFromCpp inside Crystal::Pass#to_binding. The better way would be moving that part into a separate CallBuilder then adding the Crystal wrapper call inside the Qt processor, but then the conversions would only work within that processor. (This was the original plan, which explains why I tried to move the lambda expression stuff into its own Call::Body, hoping that Crystal Procs could be done in a similar pattern.) Another way is to extend the templating mechanism so that subclasses of Call::Result can specialize the template behaviour.

By the way, similar issues will probably arise in #76 when methods start passing Slices around, another generic type like Proc. Any refactoring finished here will surely benefit that PR as well.

The Call hierarchy has always looked confusing to me; although every Call refers to one Parser::Method, the code bodies range from method invocation to entire code fragments. It seems they would fit into an even larger AST type hierarchy.

@Papierkorb
Copy link
Owner

It seems they would fit into an even larger AST type hierarchy

That is correct. The reason is simply that I didn't want to model a full AST for C++ and Crystal each (even one would be crazy). So it's a compromise between having a partial one to model the overall structure but not individual expressions.


# Calls the *method*, using the *proc_name* to call-through to Crystal.
def build(method : Parser::Method, receiver = "self") : Call
def build(method : Parser::Method, receiver = "self", do_block = false) : Call
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does do_block do?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It generates snippets like Proc(Void).new do ... end instead of Proc(Void).new { ... }. This is because the template will be used inside the BindgenHelper.wrap_proc(%) template, which now comes directly from builtin_types.yml, and is a full template string that has access to environment variables. Thus Util.template will interpret the Proc body as an environment variable, unless the do notation is used.

Other solutions are to disable ENV access from from_crystal and friends, or support escape sequences for braces in Util.template.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah ok, could you put what you just said into the docs of the method? Escaping-Support would be great, but that's for another day.


# The default template. Uses `Util.template` to substitute *code* into the
# given *pattern*.
class Full < Base
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the simple/full split adds more complexity than it saves. Just collapse them into one.

end

# Compound template which runs *code* through two child templaters.
class Seq < Base
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Rename it to Sequence, Seq isn't too often typed for the long form to be annoying (Or the short form to be memorable).
  2. Use an array for input(s) to allow for 1..n instead of exactly two. In #template do some #reduce magic.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See #79.

puts "#{"<<< Failed spec command:".colorize.mode(:bold)} #{command}"

raise Spec::AssertionFailed.new("Test for #{name}.yml failed, see above", source_file, source_start)
# raise Spec::AssertionFailed.new("Test for #{name}.yml failed, see above", source_file, source_start)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a mistake, will be fixed.

@Papierkorb
Copy link
Owner

  1. I think the PR is too large. I like the concept of the proper Template module, much better than calling Util.template everywhere. Could you split that off into its own PR? (The review comments are primarily on the templating code)
  2. As you have obviously put a lot of time into this, could you tell us your thoughts which got you to your decision(s)? I want to better understand your thought process on this.

I'm not saying (or thinking) that these changes are bad – Especially if they make it work, I mean, it works so it works right? I'm simply weary as to merge this PR without being completely in the loop. Thank You!

@Papierkorb
Copy link
Owner

and Slice will probably be another one

Why?

I may take a look at the possibility of a language-agnostic AST representation later. (The Templates model a linear chain of AST nodes, but only for Call::Result objects.)

Without clear evidence that this helps a ton in the general case I don't see the need much. For Bindgen, due to what it's doing, it's hard to strike a balance between under-engineering and over-engineering and keeping complexity in check while it all still being readable. If you intend to do something in that area, please open a conversation beforehand.

@HertzDevil
Copy link
Contributor Author

Closing this one in favour of #82.

@HertzDevil HertzDevil closed this Aug 28, 2020
@HertzDevil HertzDevil deleted the fix-crystalproc branch August 29, 2020 10:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CrystalProc ignores Crystal-side type conversions

2 participants