diff --git a/go/_test/let.go b/go/_test/let.go index cc099c6..dc2a6b9 100644 --- a/go/_test/let.go +++ b/go/_test/let.go @@ -32,20 +32,20 @@ if x { func F() { var cmd *Cmd = nil for _, x := range builtin_commands { - if viml_stridx(x.name, name) == 0 && viml_len(name) >= x.minlen { + if viml_stridx(x.name, name) == 0 && len(name) >= x.minlen { cmd = x break } } if self.neovim { for _, x := range neovim_additional_commands { - if viml_stridx(x.name, name) == 0 && viml_len(name) >= x.minlen { + if viml_stridx(x.name, name) == 0 && len(name) >= x.minlen { cmd = x break } } for _, x := range neovim_removed_commands { - if viml_stridx(x.name, name) == 0 && viml_len(name) >= x.minlen { + if viml_stridx(x.name, name) == 0 && len(name) >= x.minlen { cmd = nil break } diff --git a/go/_test/special.vim b/go/_test/special.vim index 855006f..134c149 100644 --- a/go/_test/special.vim +++ b/go/_test/special.vim @@ -11,6 +11,10 @@ function! s:ExprTokenizer.token() " skip ExprTokenizer.token endfunction +function! s:StringReader.__init__() + " skip StringReader.__init__ +endfunction + function! s:StringReader.getpos() " skip StringReader.getpos endfunction diff --git a/go/gocompiler.vim b/go/gocompiler.vim index 716c4cd..51e10b2 100644 --- a/go/gocompiler.vim +++ b/go/gocompiler.vim @@ -347,7 +347,7 @@ function s:GoCompiler.compile_function(node) let [_0, struct, name; _] = matchlist(left, '^\(.*\)\.\(.*\)$') if name == 'new' \ || (struct == 'ExprTokenizer' && name == 'token') - \ || (struct == 'StringReader' && name == 'getpos') + \ || (struct == 'StringReader' && (name == 'getpos' || name == '__init__')) \ || (struct == 'VimLParser' && (name =~ '\(push\|pop\)_context\|__init__')) \ || (struct == 'Compiler' && ( \ name == '__init__' @@ -871,6 +871,8 @@ function s:GoCompiler.compile_call(node) if index(s:viml_builtin_functions, left) != -1 if left == 'add' let left = 'append' + elseif left == 'len' + let left = 'len' else let left = printf('viml_%s', left) endif diff --git a/go/type.go b/go/type.go index cf1f17b..8971f41 100644 --- a/go/type.go +++ b/go/type.go @@ -167,7 +167,7 @@ func NewLvalueParser(reader *StringReader) *LvalueParser { type StringReader struct { i int - pos [][]interface{} // (lnum, col int) + pos []pos buf []string } @@ -177,10 +177,52 @@ func NewStringReader(lines []string) *StringReader { return obj } +func (self *StringReader) __init__(lines []string) { + size := 0 + for _, l := range lines { + size += len(l) + 1 // +1 for EOL + } + self.buf = make([]string, 0, size) + self.pos = make([]pos, 0, size+1) // +1 for EOF + var lnum = 0 + for lnum < len(lines) { + var col = 0 + for _, r := range lines[lnum] { + c := string(r) + self.buf = append(self.buf, c) + self.pos = append(self.pos, pos{lnum: lnum + 1, col: col + 1}) + col += len(c) + } + for lnum+1 < len(lines) && viml_eqregh(lines[lnum+1], "^\\s*\\\\") { + var skip = true + col = 0 + for _, r := range lines[lnum+1] { + c := string(r) + if skip { + if c == "\\" { + skip = false + } + } else { + self.buf = append(self.buf, c) + self.pos = append(self.pos, pos{lnum: lnum + 2, col: col + 1}) + } + col += len(c) + } + lnum += 1 + } + self.buf = append(self.buf, "") + self.pos = append(self.pos, pos{lnum: lnum + 1, col: col + 1}) + lnum += 1 + } + // for + self.pos = append(self.pos, pos{lnum: lnum + 1, col: 0}) + self.i = 0 +} + func (self *StringReader) getpos() *pos { - var p = self.pos[self.i] - var lnum, col = p[0].(int), p[1].(int) - return &pos{i: self.i, lnum: lnum, col: col} + p := self.pos[self.i] + p.i = self.i + return &p } type Compiler struct { @@ -200,7 +242,7 @@ func (self *Compiler) __init__() { } func (self *Compiler) out(f string, args ...interface{}) { - if viml_len(args) == 0 { + if len(args) == 0 { if string(f[0]) == ")" { self.lines[len(self.lines)-1] += f } else { diff --git a/go/vimlfunc.go b/go/vimlfunc.go index 59ebdf8..caf8f27 100644 --- a/go/vimlfunc.go +++ b/go/vimlfunc.go @@ -77,7 +77,7 @@ func init() { type vimlList interface{} func viml_empty(obj interface{}) bool { - return viml_len(obj) == 0 + return reflect.ValueOf(obj).Len() == 0 } func viml_equalci(a, b string) bool { @@ -125,10 +125,6 @@ func viml_join(lst vimlList, sep string) string { return strings.Join(ss, sep) } -func viml_len(obj interface{}) int { - return reflect.ValueOf(obj).Len() -} - func viml_printf(f string, args ...interface{}) string { return fmt.Sprintf(f, args...) } @@ -143,7 +139,7 @@ func viml_range(start, end int) []int { func viml_split(s string, sep string) []string { if sep == `\zs` { - var ss []string + ss := make([]string, 0, len(s)) for _, r := range s { ss = append(ss, string(r)) } diff --git a/go/vimlfunc_test.go b/go/vimlfunc_test.go index 9fa164d..1019761 100644 --- a/go/vimlfunc_test.go +++ b/go/vimlfunc_test.go @@ -5,26 +5,6 @@ import ( "testing" ) -func TestViml_len(t *testing.T) { - tests := []struct { - in interface{} - want int - }{ - {in: "hoge", want: 4}, - {in: "あいうえお", want: 15}, - {in: "", want: 0}, - {in: []string{"hoge", "foo"}, want: 2}, - {in: []int{1, 2, 3}, want: 3}, - {in: []interface{}{1, "2", float64(3)}, want: 3}, - } - for _, tt := range tests { - got := viml_len(tt.in) - if got != tt.want { - t.Errorf("viml_len(%v) = %v, want %v", tt.in, got, tt.want) - } - } -} - func TestViml_eqreg(t *testing.T) { tests := []struct { in string diff --git a/go/vimlparser.go b/go/vimlparser.go index b369d30..a092aaa 100644 --- a/go/vimlparser.go +++ b/go/vimlparser.go @@ -427,55 +427,55 @@ func (self *VimLParser) parse_command_modifiers() { var k = self.reader.read_alpha() var c = self.reader.peekn(1) self.reader.skip_white() - if viml_stridx("aboveleft", k) == 0 && viml_len(k) >= 3 { + if viml_stridx("aboveleft", k) == 0 && len(k) >= 3 { // abo\%[veleft] modifiers = append(modifiers, map[string]interface{}{"name":"aboveleft"}) - } else if viml_stridx("belowright", k) == 0 && viml_len(k) >= 3 { + } else if viml_stridx("belowright", k) == 0 && len(k) >= 3 { // bel\%[owright] modifiers = append(modifiers, map[string]interface{}{"name":"belowright"}) - } else if viml_stridx("browse", k) == 0 && viml_len(k) >= 3 { + } else if viml_stridx("browse", k) == 0 && len(k) >= 3 { // bro\%[wse] modifiers = append(modifiers, map[string]interface{}{"name":"browse"}) - } else if viml_stridx("botright", k) == 0 && viml_len(k) >= 2 { + } else if viml_stridx("botright", k) == 0 && len(k) >= 2 { // bo\%[tright] modifiers = append(modifiers, map[string]interface{}{"name":"botright"}) - } else if viml_stridx("confirm", k) == 0 && viml_len(k) >= 4 { + } else if viml_stridx("confirm", k) == 0 && len(k) >= 4 { // conf\%[irm] modifiers = append(modifiers, map[string]interface{}{"name":"confirm"}) - } else if viml_stridx("keepmarks", k) == 0 && viml_len(k) >= 3 { + } else if viml_stridx("keepmarks", k) == 0 && len(k) >= 3 { // kee\%[pmarks] modifiers = append(modifiers, map[string]interface{}{"name":"keepmarks"}) - } else if viml_stridx("keepalt", k) == 0 && viml_len(k) >= 5 { + } else if viml_stridx("keepalt", k) == 0 && len(k) >= 5 { // keepa\%[lt] modifiers = append(modifiers, map[string]interface{}{"name":"keepalt"}) - } else if viml_stridx("keepjumps", k) == 0 && viml_len(k) >= 5 { + } else if viml_stridx("keepjumps", k) == 0 && len(k) >= 5 { // keepj\%[umps] modifiers = append(modifiers, map[string]interface{}{"name":"keepjumps"}) - } else if viml_stridx("keeppatterns", k) == 0 && viml_len(k) >= 5 { + } else if viml_stridx("keeppatterns", k) == 0 && len(k) >= 5 { // keepp\%[atterns] modifiers = append(modifiers, map[string]interface{}{"name":"keeppatterns"}) - } else if viml_stridx("hide", k) == 0 && viml_len(k) >= 3 { + } else if viml_stridx("hide", k) == 0 && len(k) >= 3 { //hid\%[e] if self.ends_excmds(c) { break } modifiers = append(modifiers, map[string]interface{}{"name":"hide"}) - } else if viml_stridx("lockmarks", k) == 0 && viml_len(k) >= 3 { + } else if viml_stridx("lockmarks", k) == 0 && len(k) >= 3 { // loc\%[kmarks] modifiers = append(modifiers, map[string]interface{}{"name":"lockmarks"}) - } else if viml_stridx("leftabove", k) == 0 && viml_len(k) >= 5 { + } else if viml_stridx("leftabove", k) == 0 && len(k) >= 5 { // lefta\%[bove] modifiers = append(modifiers, map[string]interface{}{"name":"leftabove"}) - } else if viml_stridx("noautocmd", k) == 0 && viml_len(k) >= 3 { + } else if viml_stridx("noautocmd", k) == 0 && len(k) >= 3 { // noa\%[utocmd] modifiers = append(modifiers, map[string]interface{}{"name":"noautocmd"}) - } else if viml_stridx("rightbelow", k) == 0 && viml_len(k) >= 6 { + } else if viml_stridx("rightbelow", k) == 0 && len(k) >= 6 { //rightb\%[elow] modifiers = append(modifiers, map[string]interface{}{"name":"rightbelow"}) - } else if viml_stridx("sandbox", k) == 0 && viml_len(k) >= 3 { + } else if viml_stridx("sandbox", k) == 0 && len(k) >= 3 { // san\%[dbox] modifiers = append(modifiers, map[string]interface{}{"name":"sandbox"}) - } else if viml_stridx("silent", k) == 0 && viml_len(k) >= 3 { + } else if viml_stridx("silent", k) == 0 && len(k) >= 3 { // sil\%[ent] if c == "!" { self.reader.get() @@ -490,16 +490,16 @@ func (self *VimLParser) parse_command_modifiers() { } else { modifiers = append(modifiers, map[string]interface{}{"name":"tab"}) } - } else if viml_stridx("topleft", k) == 0 && viml_len(k) >= 2 { + } else if viml_stridx("topleft", k) == 0 && len(k) >= 2 { // to\%[pleft] modifiers = append(modifiers, map[string]interface{}{"name":"topleft"}) - } else if viml_stridx("unsilent", k) == 0 && viml_len(k) >= 3 { + } else if viml_stridx("unsilent", k) == 0 && len(k) >= 3 { // uns\%[ilent] modifiers = append(modifiers, map[string]interface{}{"name":"unsilent"}) - } else if viml_stridx("vertical", k) == 0 && viml_len(k) >= 4 { + } else if viml_stridx("vertical", k) == 0 && len(k) >= 4 { // vert\%[ical] modifiers = append(modifiers, map[string]interface{}{"name":"vertical"}) - } else if viml_stridx("verbose", k) == 0 && viml_len(k) >= 4 { + } else if viml_stridx("verbose", k) == 0 && len(k) >= 4 { // verb\%[ose] if d != "" { modifiers = append(modifiers, map[string]interface{}{"name":"verbose", "count":viml_str2nr(d, 10)}) @@ -803,7 +803,7 @@ func (self *VimLParser) find_command() *Cmd { name = self.reader.read_alpha() if name != "del" && viml_eqregh(name, "\\v^d%[elete][lp]$") { self.reader.seek_set(pos) - name = self.reader.getn(viml_len(name) - 1) + name = self.reader.getn(len(name) - 1) } } if name == "" { @@ -814,20 +814,20 @@ func (self *VimLParser) find_command() *Cmd { } var cmd *Cmd = nil for _, x := range builtin_commands { - if viml_stridx(x.name, name) == 0 && viml_len(name) >= x.minlen { + if viml_stridx(x.name, name) == 0 && len(name) >= x.minlen { cmd = x break } } if self.neovim { for _, x := range neovim_additional_commands { - if viml_stridx(x.name, name) == 0 && viml_len(name) >= x.minlen { + if viml_stridx(x.name, name) == 0 && len(name) >= x.minlen { cmd = x break } } for _, x := range neovim_removed_commands { - if viml_stridx(x.name, name) == 0 && viml_len(name) >= x.minlen { + if viml_stridx(x.name, name) == 0 && len(name) >= x.minlen { cmd = nil break } @@ -2543,7 +2543,7 @@ func (self *ExprParser) parse_expr8() *VimNode { } } } - if viml_len(node.rlist) > MAX_FUNC_ARGS { + if len(node.rlist) > MAX_FUNC_ARGS { // TODO: funcname E740: Too many arguments for function: %s panic(Err("E740: Too many arguments for function", node.pos)) } @@ -2723,7 +2723,7 @@ func (self *ExprParser) parse_identifier() *VimNode { self.reader.skip_white() var npos = self.reader.getpos() var curly_parts = self.parse_curly_parts() - if viml_len(curly_parts) == 1 && curly_parts[0].type_ == NODE_CURLYNAMEPART { + if len(curly_parts) == 1 && curly_parts[0].type_ == NODE_CURLYNAMEPART { var node = Node(NODE_IDENTIFIER) node.pos = npos node.value = curly_parts[0].value @@ -2892,42 +2892,8 @@ func (self *LvalueParser) parse_lv9() *VimNode { return node } -func (self *StringReader) __init__(lines []string) { - var lnum = 0 - for lnum < viml_len(lines) { - var col = 0 - for _, c := range viml_split(lines[lnum], "\\zs") { - self.buf = append(self.buf, c) - self.pos = append(self.pos, []interface{}{lnum + 1, col + 1}) - col += viml_len(c) - } - for lnum + 1 < viml_len(lines) && viml_eqregh(lines[lnum + 1], "^\\s*\\\\") { - var skip = true - col = 0 - for _, c := range viml_split(lines[lnum + 1], "\\zs") { - if skip { - if c == "\\" { - skip = false - } - } else { - self.buf = append(self.buf, c) - self.pos = append(self.pos, []interface{}{lnum + 2, col + 1}) - } - col += viml_len(c) - } - lnum += 1 - } - self.buf = append(self.buf, "") - self.pos = append(self.pos, []interface{}{lnum + 1, col + 1}) - lnum += 1 - } - // for - self.pos = append(self.pos, []interface{}{lnum + 1, 0}) - self.i = 0 -} - func (self *StringReader) eof() bool { - return self.i >= viml_len(self.buf) + return self.i >= len(self.buf) } func (self *StringReader) tell() int { @@ -2943,25 +2909,25 @@ func (self *StringReader) seek_cur(i int) { } func (self *StringReader) seek_end(i int) { - self.i = viml_len(self.buf) + i + self.i = len(self.buf) + i } func (self *StringReader) p(i int) string { - if self.i >= viml_len(self.buf) { + if self.i >= len(self.buf) { return "" } return self.buf[self.i + i] } func (self *StringReader) peek() string { - if self.i >= viml_len(self.buf) { + if self.i >= len(self.buf) { return "" } return self.buf[self.i] } func (self *StringReader) get() string { - if self.i >= viml_len(self.buf) { + if self.i >= len(self.buf) { return "" } self.i += 1 @@ -2978,7 +2944,7 @@ func (self *StringReader) peekn(n int) string { func (self *StringReader) getn(n int) string { var r = "" var j = 0 - for self.i < viml_len(self.buf) && (n < 0 || j < n) { + for self.i < len(self.buf) && (n < 0 || j < n) { var c = self.buf[self.i] if c == "" { break @@ -3003,7 +2969,7 @@ func (self *StringReader) readline() string { func (self *StringReader) getstr(begin *pos, end *pos) string { var r = "" for _, i := range viml_range(begin.i, end.i - 1) { - if i >= viml_len(self.buf) { + if i >= len(self.buf) { break } var c = self.buf[i] diff --git a/go/vimlparser_test.go b/go/vimlparser_test.go index 3236c73..67f4a8a 100644 --- a/go/vimlparser_test.go +++ b/go/vimlparser_test.go @@ -13,7 +13,7 @@ import ( "testing" ) -func recovert(t *testing.T) { +func recovert(t testing.TB) { if r := recover(); r != nil { t.Errorf("Recovered: %v\n%s", r, debug.Stack()) } @@ -174,6 +174,16 @@ func readlines(path string) ([]string, error) { } func TestVimLParser_VimLParser(t *testing.T) { + testParseVimLParser(t) +} + +func BenchmarkVimLParser_VimLParser(b *testing.B) { + for i := 0; i < b.N; i++ { + testParseVimLParser(b) + } +} + +func testParseVimLParser(t testing.TB) { defer recovert(t) p, err := build.Default.Import(basePkg, "", build.FindOnly) if err != nil {