Skip to content

Commit 28e3051

Browse files
committed
Speed up dictionary access.
1 parent 6462f4f commit 28e3051

File tree

2 files changed

+37
-22
lines changed

2 files changed

+37
-22
lines changed

pkg/forth/dictionary.go

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,10 @@ import (
1414

1515
// A Dictionary entry. Contains the name, the word itself, and the flags.
1616
type DictionaryEntry struct {
17-
Name string
18-
NameLower string
19-
ulpName string // the name we're going to compile this to
20-
Word Word
21-
Flag Flag
17+
Name string
18+
ulpName string // the name we're going to compile this to
19+
Word Word
20+
Flag Flag
2221
}
2322

2423
func (d DictionaryEntry) String() string {
@@ -44,13 +43,15 @@ func (d *DictionaryEntry) BodyLabel() string {
4443
// The Forth Dictionary. This architecture uses individual entries
4544
// representing words rather than a flat cell structure.
4645
type Dictionary struct {
47-
Entries []*DictionaryEntry
48-
vm *VirtualMachine
46+
Entries []*DictionaryEntry
47+
vm *VirtualMachine
48+
entryMap map[string][]*DictionaryEntry
4949
}
5050

5151
// Set up the empty dictionary.
5252
func (d *Dictionary) Setup(vm *VirtualMachine) error {
5353
d.Entries = make([]*DictionaryEntry, 0)
54+
d.entryMap = make(map[string][]*DictionaryEntry)
5455
d.vm = vm
5556
return nil
5657
}
@@ -66,20 +67,37 @@ func (d *Dictionary) AddEntry(entry *DictionaryEntry) error {
6667
fmt.Fprintf(d.vm.Out, "Redefining %s ", name)
6768
}
6869
}
69-
entry.NameLower = strings.ToLower(name)
70+
lower := d.standardizeName(name)
7071
d.Entries = append(d.Entries, entry)
72+
lst, ok := d.entryMap[lower]
73+
if !ok {
74+
lst = make([]*DictionaryEntry, 0)
75+
}
76+
lst = append(lst, entry)
77+
d.entryMap[lower] = lst
7178
return nil
7279
}
7380

81+
// standardizeName takes in the name of a word and
82+
// returns the standardized version. Currently this is
83+
// the lower case version for case-insensitivity but
84+
// it could be changes to a case-sensitive meaning.
85+
func (d *Dictionary) standardizeName(name string) string {
86+
return strings.ToLower(name)
87+
}
88+
7489
func (d *Dictionary) FindName(name string) (*DictionaryEntry, error) {
7590
if d.Entries == nil {
7691
return nil, fmt.Errorf("Dictionary not set up when finding name, please file a bug report.")
7792
}
78-
nameLower := strings.ToLower(name) // case insensitive finding
79-
for i := len(d.Entries) - 1; i >= 0; i-- {
80-
entry := d.Entries[i]
81-
if !entry.Flag.Hidden && entry.NameLower == nameLower {
82-
return entry, nil
93+
nameLower := d.standardizeName(name)
94+
same, ok := d.entryMap[nameLower]
95+
if ok {
96+
for i := len(same) - 1; i >= 0; i-- {
97+
entry := same[i]
98+
if !entry.Flag.Hidden {
99+
return entry, nil
100+
}
83101
}
84102
}
85103
return nil, fmt.Errorf("%s not found in dictionary.", name)

pkg/forth/vm.go

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -354,12 +354,10 @@ func (n *VMNumber) Setup(vm *VirtualMachine, name string, shared bool) error {
354354
Entry: &allocEntry,
355355
}
356356
n.Word.Cells[0] = CellNumber{0} // initialize to 0
357-
nameLower := strings.ToLower(name)
358357
allocEntry = DictionaryEntry{
359-
Name: name,
360-
NameLower: strings.ToLower(name),
361-
Word: &n.Word,
362-
Flag: Flag{Data: true},
358+
Name: name,
359+
Word: &n.Word,
360+
Flag: Flag{Data: true},
363361
}
364362
// then create the actual dictionary entry
365363
exit, err := vm.Dictionary.FindName("EXIT")
@@ -374,12 +372,11 @@ func (n *VMNumber) Setup(vm *VirtualMachine, name string, shared bool) error {
374372
dWord.Cells[0] = CellLiteral{CellAddress{&allocEntry, 0, false}} // put address on stack
375373
dWord.Cells[1] = CellAddress{exit, 0, false} // then exit
376374
dEntry = DictionaryEntry{
377-
Name: name,
378-
NameLower: nameLower,
379-
Word: &dWord,
375+
Name: name,
376+
Word: &dWord,
380377
}
381378
// add the actual entry to the dictionary
382-
vm.Dictionary.Entries = append(vm.Dictionary.Entries, &dEntry)
379+
vm.Dictionary.AddEntry(&dEntry)
383380
return nil
384381
}
385382

0 commit comments

Comments
 (0)