[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [xsmith-dev] Adding "else if" branches to if-statements



Hi Ömer,

Good catch on the else if branches being empty. This is probably what the problem is. I was way off on my guess, but that’s a good thing, because this is much easier to fix. 

The reason you are seeing an error is because as you render the `IfElseStatement`, it renders `’test` and `’then` just fine, but then it tries to render the `’elseif` child. Remember that the `’elseif` child is a *list* of `ElseIf` nodes. From the reference: add-to-grammar.

> If the optional kleene star is supplied, the field will be a list field.
> The init-expr for each field specifies a default value for the field. When a node is generated, each init-expr is evaluated unless a non-default value is supplied to the generating function. If no init-expr is supplied, the following defaults are used: […] For fields with a kleene star, an empty list.

So we need two things to happen. 1) We want the generator to properly handle the case where there is no `ElseIf`. 2) We need to randomly generate `ElseIf` nodes to make interesting programs.

1) This is pretty easy. Before you render the list of else ifs, check the length of the `’elseif` list (and maybe rename the child to `’elseifs` for clarity) and if the list is empty, simply don’t render anything, then move on to the else.

2) This should also be straightforward. The `ElseIf` node has `_expression_` and `Block` children, which should already be setup for random generation, so we just need to fill the `’elseif` list. Xsmith makes this pretty easy! 

> For nodes with a kleene star, init-expr may return a list or a number. If a number is provided, the default value is a list of that many of the non-kleene-star default value.

By this, the reference means that if you give it a number, it will fill the list with that many of the type without the Kleene star (`ElseIf *` -> list of `ElseIf`). To make interesting programs, you might want to vary the amount of else ifs between 0 and let’s say 10. To do that, you would change the `add-to-grammar` declaration to:
```
 [IfElseStatement Statement
        ([test : _expression_]
        [then : Block]
        [elseif : ElseIf * = (random 0 11)]
        [else : Block])
        #:prop block-user? #t
        #:prop strict-child-order? #t
        #:prop type-info [(fresh-maybe-return-type)
                        (λ (n t) (hash 'test bool-type
                                        'then t
                                        'elseif t
                                        'else t))]])
```


William would be able to tell you more about exactly why you got the error you did and why it said there was a cycle. I’m not 100% sure myself.

Let me know if anything else pops up!
-Guy



On Dec 22, 2023, at 10:21 AM, Sayilir, O.F. (Omer, Student M-CS) <o.f.sayilir@student.utwente.nl> wrote:

Hello Guy,
 
Thank you for the reply!
I currently have this as the render-node-info:
--------------------
  [ElseIf
  (λ (n)
    (h-append
     (h-append (text "else if") space lparen (att-value 'xsmith_render-node (ast-child 'test n)) rparen)
     (att-value 'xsmith_render-node (ast-child 'then n))
     ))]
 
[IfElseStatement
  (λ (n)
    (h-append
     (h-append (text "if") space lparen (att-value 'xsmith_render-node (ast-child 'test n)) rparen)
     (att-value 'xsmith_render-node (ast-child 'then n))
     (att-value 'xsmith_render-node (ast-child 'elseif n))
     (text "else")
     (att-value 'xsmith_render-node (ast-child 'else n))))]
 
--------------------
The main modifications to the original _javascript_ example are the addition of an “elseif” branch in the IfElseStatement render info, and the inclusion of ElseIf that is pretty much the same as the IfElseStatement with the text changed to “else if” and the else branch removed.
 
Thank you for sharing the debug flags, those will certainly come in handy!
I have taken a quick look at the differences between the S-_expression_ outputs with and without the Kleene star and I have noticed that when the star is included the elseif branches seem to be empty (as in “(elseif ())”).
 
 
Kind regards,
Ömer Sayilir
 
 
From: GUY ALEXANDRE WATSON <guy.watson@utah.edu
Sent: Friday, 22 December 2023 17:08
To: Sayilir, Ö.F. (Ömer, Student M-CS) <o.f.sayilir@student.utwente.nl>
Cc: xsmith-dev@flux.utah.edu
Subject: Re: [xsmith-dev] Adding "else if" branches to if-statements
 
Hi Ömer, 
 
I think everything worked well on the grammar side of things, actually. There are a few clues in the error output as to what exactly went wrong:
 
Error encountered while printing program!
and
"Unexpected" 'xsmith_render-node "cycle.”
 
This tells me that the AST was successfully constructed, and the error happened as Xsmith was rendering the program. In particular, a node was visited twice making a loop when printing. Could you send us your `render-node-info`? My best guess is that the `render-node-info` for the `elseif` child of the `IfElseStatement` nodes is either trying to print the first of the `elseif` list multiple times, or the recursion is set up from child to child (multiple paths from the `elseif to the `else`) instead of parent to each child. We should be able to help you more once we see your `render-node-info`.
 
Please keep on asking questions if things are confusing! RACR error messages are sometimes obtuse, and it’s hard to know what exactly to look out for.
 
As far as debug tooling goes, Xsmith has a wonderful option to print the S-_expression_ form of the program. You can try it out by passing the flag `--s-exp-on-error true` to print it only when errors occur, or even `--s-exp-print-override true` to print the S-_expression_ form in place of normal program output. This lets you examine the components of your program in AST form if you’re trying to narrow down exactly where something went wrong. I’m fairly certain this flag has saved me dozens of hours of debugging.
 
-Guy
 
 
 
On Dec 22, 2023, at 3:51 AM, Sayilir, O.F. (Omer, Student M-CS) <o.f.sayilir@student.utwente.nl> wrote:
 
Hello everyone,
 
I am currently working on a fuzzer for the language Oberon-0 using Xsmith to create synthetic language samples that are to be used as input for a grammatical inference algorithm.
I am using the “simple/_javascript_.rkt” file as my main source of inspiration.
I noticed that this _javascript_ fuzzer does not have an “else if” in its definition for if-statements. As an experiment, I tried adding it myself by copying the grammar definition for if-else statements from the canned components and modifying it to generate zero-or-more “else if” branches in the if-statements. The modified definition is displayed below:
 
--------------------
(add-to-grammar
    _javascript_-comp
    [ElseIf #f ([test : _expression_]
                [then : Block])
        #:prop block-user? #t
        #:prop strict-child-order? #t
        #:prop type-info [(fresh-maybe-return-type)
                        (λ (n t) (hash 'test bool-type
                                        'then t))]]
 
    [IfElseStatement Statement
        ([test : _expression_]
        [then : Block]
        [elseif : ElseIf *]
        [else : Block])
        #:prop block-user? #t
        #:prop strict-child-order? #t
        #:prop type-info [(fresh-maybe-return-type)
                        (λ (n t) (hash 'test bool-type
                                        'then t
                                        'elseif t
                                        'else t))]])
--------------------
 
I am wondering if this is correct way to define this since, without the Kleene star, this definition seems to be generating code where every if-statement has an “else if” branch as it should. Once the Kleene star is added however, the fuzzer no longer seems to work as expected and outputs error messages similar to the one below.
 
--------------------
!!! Xsmith Error !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Error encountered while printing program!
 
Options:
Fuzzer: simple-_javascript_
Version: simple-_javascript_ 1.0, xsmith 2.0.6 (de6ace1), in Racket 8.2 (vm-type chez-scheme)
Options: --max-depth 2
Seed: 106358447
Debug Log:
Concretizing binding b_3.  Type: #<type-variable (#<mutable (#<array-type (#<type-variable #f>)>)>)>, concretized to: #<mutable (#<array-type (#<bool>)>)>
Lifting binding "lift_4", of type #<mutable (#<array-type (#<bool>)>)>, with SN 14, caused by node with SN 13
Lifting binding "lift_6", of type #<int>, with SN 19, caused by node with SN 18
Lifting binding "lift_7", of type #<bool>, with SN 25, caused by node with SN 22
Lifting binding "lift_8", of type #<string>, with SN 29, caused by node with SN 27
Lifting binding "lift_9", of type #<string>, with SN 32, caused by node with SN 30
Lifting binding "lift_10", of type #<string>, with SN 34, caused by node with SN 33
Lifting binding "lift_11", of type #<string>, with SN 36, caused by node with SN 35
Lifting binding "lift_12", of type #<mutable (#<structural-record-type final?:#t, fields: #hash()>)>, with SN 41, caused by node with SN 39
 
 
Exception:
RACR exception: "AG evaluator exception;" "Unexpected" 'xsmith_render-node "cycle."
 
Program output captured:
--------------------
 
My apologies if this is an obvious question, I am still new to the world of Racket and RACR an Xsmith and I could not find an example of something similar in the examples folder in the git repository.
 
Kind regards,
Ömer Sayilir