Skip to main content
Glama
emicklei

melrōse musical expression player

by emicklei
evaluator_test.go7.99 kB
package dsl import ( "testing" "github.com/emicklei/melrose/control" "github.com/emicklei/melrose/core" "github.com/emicklei/melrose/op" ) func TestSemicolonSeparator(t *testing.T) { for _, entry := range []struct { input string want string }{ {`// help;me a=note('c') // or;him`, "note('C')"}, {`// help;me a=note('c');b=a // a==b`, "a"}, {`a=note('c') ; b=a; ;b`, "a"}, {`s=sequence('c d');join(s,s)//test`, "join(s,s)"}, } { e := NewEvaluator(MockContext()) r, err := e.EvaluateProgram(entry.input) if err != nil { t.Error(err) } if got, want := core.Storex(r), entry.want; got != want { t.Errorf("got [%v] want [%v]", got, want) } } } func TestIsCompatible(t *testing.T) { if got, want := true, IsCompatibleSyntax("0.20"); got != want { t.Errorf("got [%v] want [%v]", got, want) } if got, want := false, IsCompatibleSyntax("2.0"); got != want { t.Errorf("got [%v] want [%v]", got, want) } if got, want := false, IsCompatibleSyntax("1.1"); got != want { t.Errorf("got [%v] want [%v]", got, want) } } func TestNestedFunctions(t *testing.T) { e := NewEvaluator(MockContext()) input := `pitch(1,repeat(1,reverse(join(note('E'),sequence('F G')))))` _, err := e.EvaluateExpression(input) if err != nil { t.Error(err) } } func TestMulitLineEvaluate(t *testing.T) { e := NewEvaluator(MockContext()) input := `sequence(" C D E C C D E C E F 2G E F 2G 8G 8A 8G 8F E C 8G 8A 8G 8F E C 2C 2G3 2C 2C 2G3 2C ")` seq, err := e.EvaluateProgram(input) if err != nil { t.Error(err) } if got, want := seq.(core.Sequence).Storex(), "sequence('C D E C C D E C E F 2G E F 2G 8G 8A 8G 8F E C 8G 8A 8G 8F E C 2C 2G3 2C 2C 2G3 2C')"; got != want { t.Errorf("got [%v:%T] want [%v:%T]", got, got, want, want) } } func Test_isAssignment(t *testing.T) { type args struct { entry string } tests := []struct { name string args args wantVarname string wantExpression string wantOk bool }{ {"a=1", args{"a=1"}, "a", "1", true, }, {" a = note('=')", args{" a = note('=')"}, "a", "note('=')", true, }, {"multi line", args{`j2 = join( repeat(2,i2) )`}, "j2", "join( repeat(2,i2) )", true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { gotVarname, gotExpression, gotOk := IsAssignment(tt.args.entry) if gotVarname != tt.wantVarname { t.Errorf("isAssignment() gotVarname = %v, want %v", gotVarname, tt.wantVarname) } if gotExpression != tt.wantExpression { t.Errorf("isAssignment() gotExpression = %v, want %v", gotExpression, tt.wantExpression) } if gotOk != tt.wantOk { t.Errorf("isAssignment() gotOk = %v, want %v", gotOk, tt.wantOk) } }) } } func TestEvaluateProgram_SingleLine(t *testing.T) { e := NewEvaluator(MockContext()) if _, err := e.EvaluateProgram(`a = 1`); err != nil { t.Error(err) } } func TestEvaluateProgram_CommentLine(t *testing.T) { e := NewEvaluator(MockContext()) if _, err := e.EvaluateProgram(`// a = 1`); err != nil { t.Error(err) } } func TestEvaluateProgram_FirstTab(t *testing.T) { e := NewEvaluator(MockContext()) if _, err := e.EvaluateProgram(` a = 1`); err == nil { t.Error(err) } } func TestEvaluateProgram_TwoLines(t *testing.T) { e := NewEvaluator(MockContext()) r, err := e.EvaluateProgram( `a = 1 b = 2`) if err != nil { t.Error(err) } if got, want := r, 2; got != want { t.Errorf("got [%v] want [%v]", got, want) } } func TestEvaluateProgram_BrokenSequence(t *testing.T) { e := NewEvaluator(MockContext()) r, err := e.EvaluateProgram( `a = sequence( 'A')`) if err != nil { t.Error(err) } if got, want := r, 1; len(got.(core.Sequence).Notes) != want { t.Errorf("got [%v] want [%v]", got, want) } } func TestEvaluateProgram_AllBrokenSequence(t *testing.T) { e := NewEvaluator(MockContext()) r, err := e.EvaluateProgram( `a = sequence ( ' A ' )`) if err != nil { t.Error(err) } if r == nil { t.Fatal() } if got, want := r, 1; len(got.(core.Sequence).Notes) != want { t.Errorf("got [%v] want [%v]", got, want) } } func TestEvaluateProgram_TwoTabs(t *testing.T) { e := NewEvaluator(MockContext()) r, err := e.EvaluateProgram( `a = 1`) if err != nil { t.Error(err) } if got, want := r, 1; got != want { t.Errorf("got [%v] want [%v]", got, want) } } func TestEvaluateProgram_TrailingWhitespace(t *testing.T) { e := newTestEvaluator() r, err := e.EvaluateProgram( `a=1 `) checkError(t, err) if got, want := r, 1; got != want { t.Errorf("got [%v] want [%v]", got, want) } } func TestEvaluateError_Play(t *testing.T) { _, err := newTestEvaluator().evaluateCleanStatement(`repeat(-1,1)`) if err == nil { t.Fail() } } func TestEvaluateIndexOnArray(t *testing.T) { e := newTestEvaluator() r, err := e.EvaluateProgram( `([1,2,3])[1]`) checkError(t, err) if got, want := r, 2; got != want { t.Errorf("got [%v] want [%v]", got, want) } } func TestEvaluateIndexOnVariable(t *testing.T) { e := newTestEvaluator() r, err := e.EvaluateProgram( `a=[1,2,3] a[1]`) checkError(t, err) if got, want := r, 1; got != want { t.Errorf("got [%v] want [%v]", got, want) } } func TestEvaluate_Scale_At(t *testing.T) { e := newTestEvaluator() r, err := e.EvaluateProgram( `at(1,scale('C'))`) checkError(t, err) at, _ := r.(op.AtIndex) if got, want := at.Target.S().At(0)[0], core.MustParseNote("C"); !got.Equals(want) { t.Errorf("got [%v:%T] want [%v:%T]", got, got, want, want) } } func TestLineCommentOnBrokenExpression(t *testing.T) { e := newTestEvaluator() r, err := e.EvaluateProgram( `join( // comment sequence('A'))`) checkError(t, err) if got, want := r.(op.Join).Storex(), "join(sequence('A'))"; got != want { t.Errorf("got [%v:%T] want [%v:%T]", got, got, want, want) } } func TestKeyOnNoteString(t *testing.T) { e := newTestEvaluator() r, err := e.EvaluateProgram( `k = key('c2')`) checkError(t, err) if got, want := r.(control.Key).Storex(), "key(device(1,channel(1,note('C2'))))"; got != want { t.Errorf("got [%v:%T] want [%v:%T]", got, got, want, want) } } func TestKeyOnChannelNote(t *testing.T) { e := newTestEvaluator() r, err := e.EvaluateProgram( `k = key(channel(1,note('c2')))`) checkError(t, err) if got, want := r.(control.Key).Storex(), "key(device(1,channel(1,note('C2'))))"; got != want { t.Errorf("got [%v:%T] want [%v:%T]", got, got, want, want) } } func TestEuclidean(t *testing.T) { e := newTestEvaluator() r, err := e.EvaluateProgram( `e = euclidean(12,4,0,note('c'))`) checkError(t, err) if got, want := r.(*core.Euclidean).Storex(), "euclidean(12,4,0,note('C'))"; got != want { t.Errorf("got [%v:%T] want [%v:%T]", got, got, want, want) } } func TestMapFraction(t *testing.T) { e := newTestEvaluator() r, err := e.EvaluateProgram(` c = map(join(note('e')), fraction(8,_)) `) checkError(t, err) if got, want := r.(core.Map).Storex(), "map(join(note('E')),fraction(8,_))"; got != want { t.Errorf("got [%v:%T] want [%v:%T]", got, got, want, want) } if got, want := r.(core.Map).S().Storex(), "sequence('8E')"; got != want { t.Errorf("got [%v:%T] want [%v:%T]", got, got, want, want) } } func TestTransposeUnderscore(t *testing.T) { e := newTestEvaluator() r, err := e.EvaluateProgram(` c = transpose(1,_) `) checkError(t, err) if got, want := r.(op.Transpose).Storex(), "transpose(1,_)"; got != want { t.Errorf("got [%v:%T] want [%v:%T]", got, got, want, want) } } func TestMapTranspose(t *testing.T) { e := newTestEvaluator() r, err := e.EvaluateProgram(` c = map(join(note('e')), transpose(1,_)) `) checkError(t, err) if got, want := r.(core.Map).Storex(), "map(join(note('E')),transpose(1,_))"; got != want { t.Errorf("got [%v:%T] want [%v:%T]", got, got, want, want) } if got, want := r.(core.Map).S().Storex(), "sequence('F')"; got != want { t.Errorf("got [%v:%T] want [%v:%T]", got, got, want, want) } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/emicklei/melrose'

If you have feedback or need assistance with the MCP directory API, please join our Discord server