Skip to content

Commit 4817810

Browse files
authored
fix #121 (#124)
1 parent 2d45f24 commit 4817810

File tree

3 files changed

+146
-11
lines changed

3 files changed

+146
-11
lines changed

evaluator/map.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,16 @@ func evaluateMap(node *ast.Map, scope *object.Scope) object.Object {
99
pairs := make(map[object.MapKey]object.MapPair)
1010

1111
for keyNode, valueNode := range node.Pairs {
12+
// if keyNode is an identifier, convert it to a string
13+
identifier, ok := keyNode.(*ast.Identifier)
14+
15+
if ok {
16+
keyNode = &ast.String{
17+
Token: identifier.Token,
18+
Value: identifier.Value,
19+
}
20+
}
21+
1222
key := Evaluate(keyNode, scope)
1323

1424
if isError(key) {

examples/hello.ghost

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,8 @@
1-
print("hello world")
2-
print(1 + 2)
1+
foo = 'hello'
32

4-
if (true) {
5-
print("true!!")
6-
} else {
7-
print("false :(")
3+
bar = {
4+
foo: 'bar'
85
}
96

10-
class Animal {
11-
function speak() {
12-
print("Animals speaks.")
13-
}
14-
}
7+
print(bar.foo)
8+
print(foo)

parser/parser_test.go

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,137 @@ func TestMapLiteralsWithStringKeys(t *testing.T) {
579579
}
580580
}
581581

582+
func TestMapLiteralsWithBooleanKeys(t *testing.T) {
583+
input := `{true: 1, false: 2}`
584+
585+
scanner := scanner.New(input, "test.ghost")
586+
parser := New(scanner)
587+
program := parser.Parse()
588+
589+
failIfParserHasErrors(t, parser)
590+
591+
statement, ok := program.Statements[0].(*ast.Expression)
592+
593+
if !ok {
594+
t.Fatalf("program.Statements[0] is not ast.Expression. got=%T", program.Statements[0])
595+
}
596+
597+
mapLiteral, ok := statement.Expression.(*ast.Map)
598+
599+
if !ok {
600+
t.Fatalf("statement is not ast.Map. got=%T", statement.Expression)
601+
}
602+
603+
if len(mapLiteral.Pairs) != 2 {
604+
t.Fatalf("map.Pairs has wrong length. got=%d", len(mapLiteral.Pairs))
605+
}
606+
607+
expected := map[bool]int64{
608+
true: 1,
609+
false: 2,
610+
}
611+
612+
for key, value := range mapLiteral.Pairs {
613+
boolean, ok := key.(*ast.Boolean)
614+
615+
if !ok {
616+
t.Errorf("key is not ast.Boolean. got=%T", key)
617+
}
618+
619+
expectedValue := expected[boolean.Value]
620+
621+
isNumberLiteral(t, value, expectedValue)
622+
}
623+
}
624+
625+
func TestMapLiteralsWithIntegerKeys(t *testing.T) {
626+
input := `{1: 1, 2: 2, 3: 3}`
627+
628+
scanner := scanner.New(input, "test.ghost")
629+
parser := New(scanner)
630+
program := parser.Parse()
631+
632+
failIfParserHasErrors(t, parser)
633+
634+
statement, ok := program.Statements[0].(*ast.Expression)
635+
636+
if !ok {
637+
t.Fatalf("program.Statements[0] is not ast.Expression. got=%T", program.Statements[0])
638+
}
639+
640+
mapLiteral, ok := statement.Expression.(*ast.Map)
641+
642+
if !ok {
643+
t.Fatalf("statement is not ast.Map. got=%T", statement.Expression)
644+
}
645+
646+
if len(mapLiteral.Pairs) != 3 {
647+
t.Fatalf("map.Pairs has wrong length. got=%d", len(mapLiteral.Pairs))
648+
}
649+
650+
expected := map[int64]int64{
651+
1: 1,
652+
2: 2,
653+
3: 3,
654+
}
655+
656+
for key, value := range mapLiteral.Pairs {
657+
number, ok := key.(*ast.Number)
658+
659+
if !ok {
660+
t.Errorf("key is not ast.Number. got=%T", key)
661+
}
662+
663+
expectedValue := expected[number.Value.IntPart()]
664+
665+
isNumberLiteral(t, value, expectedValue)
666+
}
667+
}
668+
669+
func TestMapLiteralsWithVariableKeys(t *testing.T) {
670+
input := `{foo: 1, bar: 2, baz: 3}`
671+
672+
scanner := scanner.New(input, "test.ghost")
673+
parser := New(scanner)
674+
program := parser.Parse()
675+
676+
failIfParserHasErrors(t, parser)
677+
678+
statement, ok := program.Statements[0].(*ast.Expression)
679+
680+
if !ok {
681+
t.Fatalf("program.Statements[0] is not ast.Expression. got=%T", program.Statements[0])
682+
}
683+
684+
mapLiteral, ok := statement.Expression.(*ast.Map)
685+
686+
if !ok {
687+
t.Fatalf("statement is not ast.Map. got=%T", statement.Expression)
688+
}
689+
690+
if len(mapLiteral.Pairs) != 3 {
691+
t.Fatalf("map.Pairs has wrong length. got=%d", len(mapLiteral.Pairs))
692+
}
693+
694+
expected := map[string]int64{
695+
"foo": 1,
696+
"bar": 2,
697+
"baz": 3,
698+
}
699+
700+
for key, value := range mapLiteral.Pairs {
701+
identifier, ok := key.(*ast.Identifier)
702+
703+
if !ok {
704+
t.Errorf("key is not ast.Identifier. got=%T", key)
705+
}
706+
707+
expectedValue := expected[identifier.Value]
708+
709+
isNumberLiteral(t, value, expectedValue)
710+
}
711+
}
712+
582713
func TestEmptyMapLiterals(t *testing.T) {
583714
input := `{}`
584715

0 commit comments

Comments
 (0)