github.com/MontFerret/ferret@v0.18.0/pkg/compiler/compiler_for_while_test.go (about)

     1  package compiler_test
     2  
     3  import (
     4  	"context"
     5  	"testing"
     6  
     7  	. "github.com/smartystreets/goconvey/convey"
     8  
     9  	"github.com/MontFerret/ferret/pkg/compiler"
    10  	"github.com/MontFerret/ferret/pkg/runtime"
    11  	"github.com/MontFerret/ferret/pkg/runtime/core"
    12  	"github.com/MontFerret/ferret/pkg/runtime/values"
    13  )
    14  
    15  func TestForWhile(t *testing.T) {
    16  	Convey("FOR WHILE", t, func() {
    17  		Convey("WHILE", func() {
    18  			Convey("Should compile FOR i WHILE false RETURN i", func() {
    19  				c := compiler.New()
    20  
    21  				p, err := c.Compile(`
    22  			FOR i WHILE false
    23  				RETURN i
    24  		`)
    25  
    26  				So(err, ShouldBeNil)
    27  				So(p, ShouldHaveSameTypeAs, &runtime.Program{})
    28  
    29  				out, err := p.Run(context.Background())
    30  
    31  				So(err, ShouldBeNil)
    32  				So(string(out), ShouldEqual, "[]")
    33  			})
    34  
    35  			Convey("Should compile FOR i WHILE [] RETURN i", func() {
    36  				c := compiler.New()
    37  
    38  				p, err := c.Compile(`
    39  			FOR i WHILE []
    40  				RETURN i
    41  		`)
    42  
    43  				So(err, ShouldBeNil)
    44  				So(p, ShouldHaveSameTypeAs, &runtime.Program{})
    45  
    46  				out, err := p.Run(context.Background())
    47  
    48  				So(err, ShouldBeNil)
    49  				So(string(out), ShouldEqual, "[]")
    50  			})
    51  
    52  			Convey("Should compile FOR i WHILE F() < 10 RETURN i", func() {
    53  				c := compiler.New()
    54  
    55  				counter := -1
    56  				c.RegisterFunction("F", func(ctx context.Context, args ...core.Value) (core.Value, error) {
    57  					counter++
    58  					return values.NewInt(counter), nil
    59  				})
    60  
    61  				p, err := c.Compile(`
    62  			FOR i WHILE F() < 10
    63  				RETURN i
    64  		`)
    65  
    66  				So(err, ShouldBeNil)
    67  				So(p, ShouldHaveSameTypeAs, &runtime.Program{})
    68  
    69  				out, err := p.Run(context.Background())
    70  
    71  				So(err, ShouldBeNil)
    72  				So(string(out), ShouldEqual, "[0,1,2,3,4,5,6,7,8,9]")
    73  			})
    74  
    75  			Convey("Should compile FOR i WHILE F() RETURN i", func() {
    76  				c := compiler.New()
    77  
    78  				counter := -1
    79  				c.RegisterFunction("F", func(ctx context.Context, args ...core.Value) (core.Value, error) {
    80  					counter++
    81  
    82  					if counter == 10 {
    83  						return values.False, nil
    84  					}
    85  
    86  					return values.True, nil
    87  				})
    88  
    89  				p, err := c.Compile(`
    90  			FOR i WHILE F()
    91  				RETURN i
    92  		`)
    93  
    94  				So(err, ShouldBeNil)
    95  				So(p, ShouldHaveSameTypeAs, &runtime.Program{})
    96  
    97  				out, err := p.Run(context.Background())
    98  
    99  				So(err, ShouldBeNil)
   100  				So(string(out), ShouldEqual, "[0,1,2,3,4,5,6,7,8,9]")
   101  			})
   102  
   103  			Convey("Should compile nested FOR operators", func() {
   104  				c := compiler.New()
   105  
   106  				counter := -1
   107  				c.RegisterFunction("F", func(ctx context.Context, args ...core.Value) (core.Value, error) {
   108  					counter++
   109  					return values.NewInt(counter), nil
   110  				})
   111  
   112  				p, err := c.Compile(`
   113  			FOR i WHILE F() < 5
   114  				LET y = i + 1
   115  				FOR x IN 1..y
   116  					RETURN i * x
   117  		`)
   118  
   119  				So(err, ShouldBeNil)
   120  
   121  				out, err := p.Run(context.Background())
   122  
   123  				So(err, ShouldBeNil)
   124  
   125  				So(string(out), ShouldEqual, "[0,1,2,2,4,6,3,6,9,12,4,8,12,16,20]")
   126  			})
   127  		})
   128  
   129  		Convey("DO-WHILE", func() {
   130  			Convey("Should compile FOR i DO WHILE false RETURN i", func() {
   131  				c := compiler.New()
   132  
   133  				p, err := c.Compile(`
   134  			FOR i DO WHILE false
   135  				RETURN i
   136  		`)
   137  
   138  				So(err, ShouldBeNil)
   139  				So(p, ShouldHaveSameTypeAs, &runtime.Program{})
   140  
   141  				out, err := p.Run(context.Background())
   142  
   143  				So(err, ShouldBeNil)
   144  				So(string(out), ShouldEqual, "[0]")
   145  			})
   146  
   147  			Convey("Should compile FOR i DO WHILE [] RETURN i", func() {
   148  				c := compiler.New()
   149  
   150  				p, err := c.Compile(`
   151  			FOR i DO WHILE []
   152  				RETURN i
   153  		`)
   154  
   155  				So(err, ShouldBeNil)
   156  				So(p, ShouldHaveSameTypeAs, &runtime.Program{})
   157  
   158  				out, err := p.Run(context.Background())
   159  
   160  				So(err, ShouldBeNil)
   161  				So(string(out), ShouldEqual, "[0]")
   162  			})
   163  
   164  			Convey("Should compile FOR i DO WHILE F() < 10 RETURN i", func() {
   165  				c := compiler.New()
   166  
   167  				counter := -1
   168  				c.RegisterFunction("F", func(ctx context.Context, args ...core.Value) (core.Value, error) {
   169  					counter++
   170  					return values.NewInt(counter), nil
   171  				})
   172  
   173  				p, err := c.Compile(`
   174  			FOR i DO WHILE F() < 10
   175  				RETURN i
   176  		`)
   177  
   178  				So(err, ShouldBeNil)
   179  				So(p, ShouldHaveSameTypeAs, &runtime.Program{})
   180  
   181  				out, err := p.Run(context.Background())
   182  
   183  				So(err, ShouldBeNil)
   184  				So(string(out), ShouldEqual, "[0,1,2,3,4,5,6,7,8,9,10]")
   185  			})
   186  
   187  			Convey("Should compile FOR i WHILE F() RETURN i", func() {
   188  				c := compiler.New()
   189  
   190  				counter := -1
   191  				c.RegisterFunction("F", func(ctx context.Context, args ...core.Value) (core.Value, error) {
   192  					counter++
   193  
   194  					if counter == 10 {
   195  						return values.False, nil
   196  					}
   197  
   198  					return values.True, nil
   199  				})
   200  
   201  				p, err := c.Compile(`
   202  			FOR i WHILE F()
   203  				RETURN i
   204  		`)
   205  
   206  				So(err, ShouldBeNil)
   207  				So(p, ShouldHaveSameTypeAs, &runtime.Program{})
   208  
   209  				out, err := p.Run(context.Background())
   210  
   211  				So(err, ShouldBeNil)
   212  				So(string(out), ShouldEqual, "[0,1,2,3,4,5,6,7,8,9]")
   213  			})
   214  
   215  			Convey("Should compile nested FOR operators", func() {
   216  				c := compiler.New()
   217  
   218  				counter := -1
   219  				c.RegisterFunction("F", func(ctx context.Context, args ...core.Value) (core.Value, error) {
   220  					counter++
   221  					return values.NewInt(counter), nil
   222  				})
   223  
   224  				p, err := c.Compile(`
   225  			FOR i WHILE F() < 5
   226  				LET y = i + 1
   227  				FOR x IN 1..y
   228  					RETURN i * x
   229  		`)
   230  
   231  				So(err, ShouldBeNil)
   232  
   233  				out, err := p.Run(context.Background())
   234  
   235  				So(err, ShouldBeNil)
   236  
   237  				So(string(out), ShouldEqual, "[0,1,2,2,4,6,3,6,9,12,4,8,12,16,20]")
   238  			})
   239  		})
   240  	})
   241  }