Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Activity
    Rijnard van Tonder
    @rvantonder
    The way to invoke your custom matcher would be to specify -custom-matcher c-without-macros.json, something in something like this:
    comby 'if (:[cond])' 'rewrite...' .c -custom-matcher c-without-macros.json
    Buga Dániel
    @bugadani
    Thank you very much. I'll play around with comby on a few projects of mine, let's hope I run into some real issues or unsupported use cases, not just RTFM stuff. Thanks a lot for your explanation!
    Rijnard van Tonder
    @rvantonder
    For sure, don't hesitate if you have a specific use case in mind, or run into trouble. I didn't take your question to be a RTFM one :) Because there are lots of different options, it helps to narrow down what might work best for your use case. It's also helpful for me to learn about new use cases for extending/expanding capabilities, so I don't mind the questions at all.
    Buga Dániel
    @bugadani
    image.png
    Could you please take a look at this one? bit.ly/2moWl41 The in-browser behaviour looks promising, but running the "Run in terminal" output messes up the first if, kind of like in the github issue earlier.
    Maybe I'm just blind because it's 0:15AM right now...
    Rijnard van Tonder
    @rvantonder
    Is the idea to add braces around if conditionals that don't have them?
    Buga Dániel
    @bugadani
    Yes, that seemed simple enough :) I don't need a fully general solution, I was just playing around to see if I'm able to do it
    The issue I'm facing is the differing behaviour between the browser and my console, but printing the variables looks OK to me.
    Buga Dániel
    @bugadani
    Except now it works without me doing anything...
    David Aramant
    @davidaramant
    Hi and thanks for your Strange Loop talk, I'm going to be sharing this with people at work :)
    I was trying to come up with an example to show and I wonder if there's an elegant way to avoid trailing commas. The transform I want is from QList<int> a = QList<int>() << 1 << 2; to QList<int> a { 1, 2 };. A trailing comma is valid after the last argument but I would prefer it not be there. bit.ly/2mIyAnI
    Rijnard van Tonder
    @rvantonder
    Hi @davidaramant, thanks. Yeah this use case has come up a handful of times with things I've tried to do too. The most straightforward way I've come up with is to use the idea behind this little trick: bit.ly/2onM34G
    Basically, if you have a pattern where you want to exclude the suffix of some kind, putting it inside delimiters and then putting the thing you want to exclude at the end will remove it.
    for your example, I've reworked it a little to do this inside the {...} part
    It needs two additional rewrite rules: bit.ly/2mQ9VxG I'm not sure of a more elegant way with the capabilities that are available right now
    Rijnard van Tonder
    @rvantonder
    Actually, there's a simpler way for this specific case. If you can rely on the whitespace between <<, you can just exploit that to replace the whitespace with ,: bit.ly/2mLepWb
    (scroll down for the rest of the rewrite rule. I'm working on making the UI auto expand for longer rules :))
    David Aramant
    @davidaramant

    OK, I figured there was some combination of rewrite rules to do it :)

    I just ran into a worse problem. I was hoping to show it working for a simple case like int and then replace it with something complex like this to show that you wouldn't want to tackle it with regex: QList<QPair<int, int>> a = QList<QPair<int, int>>() << qMakeTuple(1, 2) << qMakeTuple(3, 4); (man don't you just love C++). I can't make those qMakeTuple calls parse though.

    Rijnard van Tonder
    @rvantonder
    Not sure I follow exactly, is the idea to have something like this (ignoring the trailing comma): bit.ly/2nt3YXT
    David Aramant
    @davidaramant
    I was hoping there was some way to have the same rewrite rule for both cases, but I guess the hole would need to match an entire arbitrary C++ expression for that to work...
    actually it's not as bad as I thought since the example you posted works for nested calls too, so it will happily match things likeqMakeTuple(f(g(2)), h(3)) too. Excellent!
    Rijnard van Tonder
    @rvantonder
    I see. Yeah I think it could get tricky trying to do something very general like that with one case.
    David Aramant
    @davidaramant
    As a general philosophical question, do you see language-specific refactoring tools like Resharper for C# as "competitors" or complimentary to comby?
    Rijnard van Tonder
    @rvantonder
    Right, if the only syntax variants are 'calls' and 'identifiers' then it should work OK. It's an interesting case though because I wonder if supporting a way to match, say identifier and expression() syntax using a single hole would be useful or feasible. I'd have to think about it a bit more
    I see it as complimentary. More specifically, program transformation tools fall on a spectrum that tradeoff expressivity/language-specificity. I think there's some tooling missing on that spectrum for certain applications, which is why comby exists at the end of the day. Longer musing on this in my reply here: https://lobste.rs/s/lvv8lj/comby_tool_for_changing_code#c_mbhuij
    David Aramant
    @davidaramant
    Makes sense. Comby seems like a useful tool in the toolbox even if there are extreme cases it can't handle (yet?)
    Anyway I think these examples will make for a good lightning talk at work :)
    Rijnard van Tonder
    @rvantonder
    Yeah, and I'm not sure where the limits lie (depends on what people want to do); the idea is to provide a handful of capabilities and see/use what's possible. I don't see it trying to replace or subsume dedicated frameworks for changing programs; my personal experience has just been that using those alternatives take more effort and there's not much midway between regex and "I-have-to-understand-or-write-a-grammar".
    Hope it goes well, and thanks for your interest!
    Maxime Quandalle
    @mquandalle
    Hi, I'm trying to match a function compose(:[arg]) in JavaScript where arg is a single argument, and the goal is to rewrite the expression without the compose function, so just :[arg].
    I don't want to match things like compose(a, b) because in this case compose is actually doing something. I haven't been able to match a function "with only one argument" so far. Is there an easy way?
    Rijnard van Tonder
    @rvantonder
    if arg is an identifier then using the :[[arg]] syntax will only match identifiers and should work
    if there's an instance where that's not the case, let me know. There's probably a way to work around other cases
    "only identifiers" meaning, alphanumeric characters
    Maxime Quandalle
    @mquandalle
    :[[arg]] doesn't work because I also want to match expressions, ie compose(myFunc(1, 2))
    I (re)discovered https://www.graspjs.com, and with it I can do compose(__) and it works (and doesn't match things like compose(1, 2)
    Rijnard van Tonder
    @rvantonder

    @mquandalle thanks for sharing that part about graspjs, I did not know about it. In the current state, it looks like comby isn't as well suited for this use case. graspjs can make stronger assumptions about the syntax because it only operates on the Javascript AST (i.e., it knows what expressions look like in Javascript, while comby looks only at syntax and matching it in ways that generally correspond to expressions). The current way I see how you could do this with comby would be to define (multiple) patterns in ways that correspond to expressions in JS expressions. I'm not satisfied with this solution, but it's the closest thing possible in the current state, without supporting a new kind of hole matching. For example, I think this collection captures most cases of single arguments:

    compose(:[[function]](:[arg]))
    compose(:[[identifier]])
    compose((:[tuple]))
    compose({:[object]})
    compose(:[[list]])

    It's possible to have the same sort of functionality in comby as graspjs, but I'd have to think a bit more carefully about how to support such matching. I've added a note to the repo, and will be thinking about this more in the next couple of days. Thanks for pointing out your use case! Will post an update when I've made progress.

    THofstee
    @THofstee

    Hi Rijnard, is it possible to have conditional rewrites inside captured holes? For example, I have this code:

    module foo(input logic clk, d, output logic q);
      always_ff @(posedge clk)
        q <= d;
    endmodule
    
    module bar(input logic clk, d, output logic q);
      foo temp(clk, d, q);
    endmodule
    
    module baz(input logic clk, d, output logic q);
      foo r1(clk, d, q);
      bar r2 (clk, d, q);
    endmodule

    and I'm trying to convert it to look like this:

    module foo_renamed(input logic clk, d, output logic q);
      always_ff @(posedge clk)
        q <= d;
    endmodule
    
    module bar_renamed(input logic clk, d, output logic q);
      foo_renamed temp(clk, d, q);
    endmodule
    
    module baz(input logic clk, d, output logic q);
      foo_renamed r1(clk, d, q);
      bar_renamed r2 (clk, d, q);
    endmodule

    So it has renamed all instantiated modules inside of every module, but it hasn't renamed the declaration of baz. I've come up with this but it feels a bit hacky:

    module :[[1]]:[2] endmodule
    where 
    rewrite :[1] { ":[1]" -> ":[1]_renamed" },
    rewrite :[1] { "baz_renamed" -> "baz" },
    rewrite :[2] { ":[[1]] :[[2]]:[3];" -> ":[[1]]_renamed :[[2]]:[3];" }
    Rijnard van Tonder
    @rvantonder
    Hey @THofstee , apologies for the late reply. There's a simpler way, you can prepend an expression that constrains when the rule fires. In your example, it looks like :[1] != "baz" works. Rules are evaluated sequentially (left to right) for each match, and if an expression evaluates to false then the rest of the rule will not be evaluated. Complete example: https://bit.ly/31rSrG2
    Daniel Hines
    @d4hines
    Hello! I'm working with ASP, a logic language that extends Datalog with constraints, strong negation, and other goodies. There is a further extension to ASP called AL that has a few very simple rewrite rules to compile to valid ASP. An example rewrite is a causes b if c becomes holds(b, T + 1) :- holds(c, T), occurs(a, T), T < n. I was planning on using the term rewriting system Meander directly on the AST to achieve these rewrites, but I watched the Strange Loop talk and was wondering if Comby could more easily express these rules. What do you think @rvantonder?
    Rijnard van Tonder
    @rvantonder
    Hey @d4hines . Seems like a great fit for your use case. You'll have to experiment and see if you run into issues (ping me if there's a specific pattern or use case). There was a talk on Meander at Strangeloop too (which I went to). I think it's neat. It emphasizes different slightly different goals, though there's plenty of overlap. I think if you want to manipulate syntax as data, Comby fits the bill and you'll have an easier time. It's a little difficult to predict what limitations you might run into (for example, currently, if your transformations rely on type information, this is a problem).
    Shane Delmore
    @ShaneDelmore
    Is there a way in Comby to swap [] for {}? I am unable to match the actual [] themselves, only match the code inside and including them.
    It “seems” like [:[expr]] should work from the docs but I can’t make it work so I may be misinterpreting the docs.
    Rijnard van Tonder
    @rvantonder
    Yeah that should work, and it looks like things behave that way in the live environment (https://bit.ly/2oyzNPo) and terminal :
    echo '[] [a] [a b c]' | comby '[:[expr]]' '{:[expr]}' -stdin
    ------ /dev/null
    ++++++ /dev/null
    @|-1,1 +1,1 ============================================================
    -|[] [a] [a b c]
    +|{} {a} {a b c}
    my suspicion is that the matches are being missed because of the language selection. if the program contains comments or strings and the parser doesn't interpret them, things go wrong down the line and things that are expected to match, don't.
    (you can specify the language manually with -matcher .c, for C, for example)
    (by default, the matcher is inferred from extensions, otherwise it falls back to a generic one)
    feel free to try the larger code snippet in the live site, or on the command line if it's too long for the live site. failing that, PM me the long example and I can look into whether it's a matcher/language definition issue.
    Shane Delmore
    @ShaneDelmore
    I just went to reproduce the issue on the live site and it works now. Not sure what I was doing wrong, but thanks for making me take a second look at it. Now that this works it’s quite handy for me.
    Er…now that I can make it work.
    Rijnard van Tonder
    @rvantonder
    haha. no worries, glad it worked out for you