func (ls *libstore) deletelist() { now := time.Now() // ls.mutex.Lock() // // fmt.Println("deleteinvalid") // defer ls.mutex.Unlock() for key, list := range ls.keyValudhistory { ls.initiateKeyValueMutex(key) ls.keyValueMutex[key].Lock() for list.Len() > 0 { e := list.Front() if e.Value.(time.Time).Add(time.Duration(storagerpc.QueryCacheSeconds)*time.Second).After(now) && list.Len() <= storagerpc.QueryCacheThresh { break } list.Remove(list.Front()) } ls.keyValueMutex[key].Unlock() } for key, list := range ls.keyListhistory { ls.initiateKeyListMutex(key) ls.keyListMutex[key].Lock() for list.Len() > 0 { e := list.Front() if e.Value.(time.Time).Add(time.Duration(storagerpc.QueryCacheSeconds)*time.Second).After(now) && list.Len() <= storagerpc.QueryCacheThresh { break } list.Remove(list.Front()) } ls.keyListMutex[key].Unlock() } }
func expandClass(regex []int) string { list := New() list.Init() nextEscape := false escaped := false var toDelete *Element for reg_index := 0; reg_index < len(regex); reg_index++ { escaped = nextEscape nextEscape = false switch regex[reg_index] { case '\\': if escaped { escaped = false list.PushBack(int('\\')) toDelete = nil } else { nextEscape = true toDelete = list.PushBack(int('\\')) } break case '-': if escaped { escaped = false list.PushBack(int('-')) toDelete.Value = Delete } else { if reg_index > 0 && reg_index < len(regex)-1 { start := regex[reg_index-1] end := uint8(regex[reg_index+1]) for char := uint8(start + 1); char < end; char++ { list.PushBack(int(char)) } } else { //ERROR fmt.Println("invalid character class") } } break default: list.PushBack(regex[reg_index]) break } } for e := list.Front(); e != nil; e = e.Next() { if e.Value.(int) == Delete { list.Remove(e) } } out := string(list.Remove(list.Front()).(int)) for e := list.Front(); e != nil; e = e.Next() { out += string('|') out += string(e.Value.(int)) } return out }
// Commit causes all requests that have been queued for the transaction // to be sent to the request channel for processing. Calls the commit // function (commitFunc) in order for each request that is part of the // transaction. func (txs *txStore) Commit(tx string, commitFunc func(f *frame.Frame) error) error { if list, ok := txs.transactions[tx]; ok { for element := list.Front(); element != nil; element = list.Front() { err := commitFunc(list.Remove(element).(*frame.Frame)) if err != nil { return err } } delete(txs.transactions, tx) return nil } return txUnknown }
func PrintDepartures(airport string, data *FlightData) { list := data.Departures[airport] for cursor := list.Front(); cursor != nil; cursor = cursor.Next() { f := cursor.Value.(Flight) fmt.Println(f.From, f.To, f.Cost) } }
// Reads a list of ASN1Cert types from |r| func readASN1CertList(r io.Reader, totalLenBytes int, elementLenBytes int) ([]ASN1Cert, error) { listBytes, err := readVarBytes(r, totalLenBytes) if err != nil { return []ASN1Cert{}, err } list := list.New() listReader := bytes.NewReader(listBytes) var entry []byte for err == nil { entry, err = readVarBytes(listReader, elementLenBytes) if err != nil { if err != io.EOF { return []ASN1Cert{}, err } } else { list.PushBack(entry) } } ret := make([]ASN1Cert, list.Len()) i := 0 for e := list.Front(); e != nil; e = e.Next() { ret[i] = e.Value.([]byte) i++ } return ret, nil }
// locate returns the node on which the item at the logical index should reside. // If the index lands on a slice node, the offset is the physical index relative // to the slice. If the index lands on a value node, then the offset is // meaningless and set to 0. func (s *GapSlice) locate(i int) (elem *list.Element, offset int) { if i < 0 || i >= s.size { return nil, 0 } remaining := i list := s.list for e := list.Front(); e != nil; e = e.Next() { switch value := e.Value.(type) { case gapSliceChunk: if chunkSize := len(value); remaining < chunkSize { return e, remaining } else { remaining -= chunkSize } default: if remaining == 0 { return e, 0 } else { remaining -= 1 } } } panic(Errorf("could not find element for index %d in GapSlice", i)) }
func (ss *storageServer) GetList(args *storagerpc.GetArgs, reply *storagerpc.GetListReply) error { if !ss.isInServerRange(args.Key) { reply.Status = storagerpc.WrongServer return nil } //get the lock for current key ss.mutex.Lock() lock, exist := ss.lockMap[args.Key] if !exist { lock = new(sync.Mutex) ss.lockMap[args.Key] = lock } ss.mutex.Unlock() //Lock current key we are going to work on lock.Lock() //process lease request grantLease := false if args.WantLease { //add to lease map var libServerList *list.List libServerList, exist := ss.leaseMap[args.Key] if !exist { libServerList = new(list.List) } leaseRecord := LeaseRecord{args.HostPort, time.Now()} libServerList.PushBack(leaseRecord) ss.leaseMap[args.Key] = libServerList grantLease = true } reply.Lease = storagerpc.Lease{grantLease, storagerpc.LeaseSeconds} //retrieve list list, exist := ss.keyListMap[args.Key] if !exist { reply.Status = storagerpc.KeyNotFound } else { //convert list format from "map" to "[]string" listSize := list.Len() replyList := make([]string, listSize) i := 0 for e := list.Front(); e != nil; e = e.Next() { val := (e.Value).(string) replyList[i] = val i = i + 1 } reply.Value = replyList reply.Status = storagerpc.OK } lock.Unlock() return nil }
func (stack *Stack) Top() []byte { list := (*list.List)(stack) el := list.Front() if el == nil { return nil } val, ok := el.Value.([]byte) if !ok { panic("Why is it not a byte array?") } return val }
func (h *hashMap) Get(key Value) (Value, error) { index := h.getIndex(key) if h.data[index] == nil { return nil, fmt.Errorf("not found") } list := h.data[index] for e := list.Front(); e != nil; e = e.Next() { if i := e.Value.(*item); i.key.Get() == key.Get() { return i.value, nil } } return nil, fmt.Errorf("not found") }
func IsBST(root *TreeNode) bool { list := list.New() createOrderedArray(root, list) prev := list.Front() for e := prev.Next(); e != nil; e = e.Next() { if prev.Value.(int) > e.Value.(int) { return false } prev = e } return true }
func MatchAll(m *Matcher, text string) []Match { list := list.New() ch := m.Match(text) for n := range ch { list.PushBack(n) } all := make([]Match, list.Len()) idx := 0 for e := list.Front(); e != nil; e = e.Next() { all[idx] = e.Value.(Match) idx++ } return all }
// GoString formats this GapSlice as a space-separated list of nodes surrounded // by parentheses. Value nodes are represented by the GoString format of the // value itself, while slice nodes are presented as a space-separated list of // values in GoString format surrounded by square brackets. func (s *GapSlice) GoString() string { list := s.list b := bytes.NewBufferString("(") for e := list.Front(); e != nil; e = e.Next() { if chunk, isChunk := e.Value.(gapSliceChunk); isChunk { b.WriteString(fmt.Sprintf("%v", chunk)) } else { b.WriteString(fmt.Sprintf("%#v", e.Value)) } if e != list.Back() { b.WriteRune(' ') } } b.WriteRune(')') return b.String() }
// Remove a service definition from the list. If a service has been removed, // return true. Different connections cannot remove services they did not add. func (l *serviceList) Remove(service *ServiceDef) bool { list := (*list.List)(l) for iter := list.Front(); iter != nil; iter = iter.Next() { e := iter.Value.(*ServiceDef) res := service.compare(e) if res > 0 { continue } else if res == 0 && e.connId == service.connId { list.Remove(iter) return true } // Did not find the service. break } return false }
func daythirteen() { file, _ := os.Open("input-day13") list := list.New() scanner := bufio.NewScanner(file) for scanner.Scan() { text := scanner.Text() list.PushFront(text) } arr := make([]string, list.Len()) count := 0 for e := list.Front(); e != nil; e = e.Next() { arr[count] = e.Value.(string) count++ } fmt.Printf("Best = %d\n", ProcSeatingArray(arr, 0)) fmt.Printf("Best = %d\n", ProcSeatingArray(arr, 1)) }
func toArray(values interface{}) ([]interface{}, os.Error) { // vector to array if vector, ok := values.(*vector.Vector); ok { return toArray(*vector) } result := new(vector.Vector) // list to array if list, ok := values.(*list.List); ok { for e := list.Front(); e != nil; e = e.Next() { result.Push(e.Value) } return *result, nil } switch v := reflect.ValueOf(values); v.Kind() { // array to array (copy) case reflect.Array, reflect.Slice: arr := v for i := 0; i < arr.Len(); i++ { obj := arr.Index(i).Interface() result.Push(obj) } // channel to array case reflect.Chan: ch := v for { if x, ok := ch.Recv(); ok { obj := x.Interface() result.Push(obj) } else { break } } // unknown type default: return nil, Errorf("type error: expected a collection type, but was “%v” of type “%T”", values, values) } return *result, nil }
// Walk iterates through this GapSlice, calling walkFn for each item visited by // Walk. // // If walkFun returns an error, the iteration is immediately halted, and in turn, // that error is returned by Walk. func (s *GapSlice) Walk(walkFn GapSliceWalkFunc) error { list := s.list for e := list.Front(); e != nil; e = e.Next() { switch value := e.Value.(type) { case gapSliceChunk: for _, v := range value { if err := walkFn(v); err != nil { return err } } default: if err := walkFn(value); err != nil { return nil } } } return nil }
func reconstructPath(came_from map[Coord]Coord, current_node Coord) []*Move { list := list.New() for present := true; present; _, present = came_from[current_node] { next_node := came_from[current_node] list.PushFront(findMove(current_node, next_node)) current_node = next_node } // Convert to a list and return rtn := make([]*Move, list.Len()) i := 0 for e := list.Front(); e != nil; e = e.Next() { move := e.Value.(Move) rtn[i] = &move i++ } return rtn }
// Add a new service definition to the list. If the definition is added or // updated, return true. func (l *serviceList) Add(service *ServiceDef) bool { list := (*list.List)(l) for iter := list.Front(); iter != nil; iter = iter.Next() { e := iter.Value.(*ServiceDef) res := service.compare(e) if res > 0 { continue } else if res < 0 { list.InsertBefore(service, iter) return true } else if e.connId == service.connId { // Replace the definition if it is from the same connection. iter.Value = service return true } // Equal entries but from a different connection. return false } list.PushBack(service) return true }
//查看某状态的任务 func taskView(w http.ResponseWriter, r *http.Request) { status := r.FormValue("status") reg := regexp.MustCompile(status_requ) if reg.MatchString(status) == false { io.WriteString(w, "need param status, status must be 0-new task ,1-success,2-can not get rdb,3-parse fatal, 4-get remote redis password error or 5-task is running!") return } int_stat, _ := strconv.ParseInt(status, 10, 32) mark, list := dbutil.FetchTask(int(int_stat)) if mark == 1 { var listHtml string = "<body><ol>" for e := list.Front(); e != nil; e = e.Next() { task, ok := e.Value.(dbutil.Task) if ok { //获取task信息 host := task.Host port := task.Port filterLength := task.FilterLength filterKey := task.FilterKey taskId := task.TaskId createTime := task.CreateTime listHtml += "<li>" + "host:" + host + ";port:" + port + ";filterLength:" + strconv.FormatInt(int64(filterLength), 10) + ";filterKey:" + filterKey + ";taskId:" + taskId + ";create_time:" + createTime + "</li>" } else { //task的类型不正确 return } } listHtml = listHtml + "</ol></body>" io.WriteString(w, listHtml) } else { io.WriteString(w, "error occure !") logs.Log("error occure in taskView!") } }
//根据taskId查看某一个task func task(w http.ResponseWriter, r *http.Request) { taskId := r.FormValue("taskId") mark, list := dbutil.FetchTaskById(taskId) if list.Len() == 0 { io.WriteString(w, "without this task !") return } if mark == 1 { var listHtml string = "<body><ol>" for e := list.Front(); e != nil; e = e.Next() { task, ok := e.Value.(dbutil.Task) if ok { //获取task信息 host := task.Host port := task.Port filterLength := task.FilterLength filterKey := task.FilterKey taskId := task.TaskId priority := task.Priority status := task.Status createTime := task.CreateTime listHtml += "<li>" + "host:" + host + ";port:" + port + ";filterLength:" + strconv.FormatInt(int64(filterLength), 10) + ";filter_key:" + filterKey + ";taskId:" + taskId + ";priority:" + strconv.FormatInt(int64(priority), 10) + ";status:" + strconv.FormatInt(int64(status), 10) + ";create_time:" + createTime + "</li>" } else { //task的类型不正确 return } listHtml = listHtml + "</ol></body>" } io.WriteString(w, listHtml) } else { io.WriteString(w, "error occure !") logs.Log("error occure in taskView!") } }
// String formats this GapSlice as a space-separated list of items surrounded // by parentheses. func (s *GapSlice) String() string { list := s.list b := bytes.NewBufferString("(") for e := list.Front(); e != nil; e = e.Next() { switch v := e.Value.(type) { case gapSliceChunk: last := len(v) - 1 for i, item := range v { b.WriteString(fmt.Sprintf("%v", item)) if i != last { b.WriteRune(' ') } } default: b.WriteString(fmt.Sprintf("%v", v)) } if e != list.Back() { b.WriteRune(' ') } } b.WriteRune(')') return b.String() }
func (t *Tree) Compile(file string) { _package, state, name, counts := "", "", "", [TypeLast]uint{} for element := t.Front(); element != nil; element = element.Next() { node := element.Value.(Node) switch node.GetType() { case TypePackage: _package = node.(Token).String() case TypePeg: peg := node.(Fix) name = peg.String() state = peg.GetNode().(Token).String() case TypeRule: rule := node.(*rule) t.rules[rule.String()] = rule } } join([]func(){ func() { var countTypes func(node Node) countTypes = func(node Node) { t := node.GetType() counts[t]++ switch t { case TypeRule: countTypes(node.(Rule).GetExpression()) case TypeAlternate, TypeUnorderedAlternate, TypeSequence: for element := node.(List).Front(); element != nil; element = element.Next() { countTypes(element.Value.(Node)) } case TypePeekFor, TypePeekNot, TypeQuery, TypeStar, TypePlus: countTypes(node.(Fix).GetNode()) } } for _, rule := range t.rules { countTypes(rule) } }, func() { var countRules func(node Node) ruleReached := make([]bool, len(t.rules)) countRules = func(node Node) { switch node.GetType() { case TypeRule: rule := node.(Rule) name, id := rule.String(), rule.GetId() if count, ok := t.rulesCount[name]; ok { t.rulesCount[name] = count + 1 } else { t.rulesCount[name] = 1 } if ruleReached[id] { return } ruleReached[id] = true countRules(rule.GetExpression()) case TypeName: countRules(t.rules[node.String()]) case TypeAlternate, TypeUnorderedAlternate, TypeSequence: for element := node.(List).Front(); element != nil; element = element.Next() { countRules(element.Value.(Node)) } case TypePeekFor, TypePeekNot, TypeQuery, TypeStar, TypePlus: countRules(node.(Fix).GetNode()) } } for element := t.Front(); element != nil; element = element.Next() { node := element.Value.(Node) if node.GetType() == TypeRule { countRules(node.(*rule)) break } } }, func() { var checkRecursion func(node Node) bool ruleReached := make([]bool, len(t.rules)) checkRecursion = func(node Node) bool { switch node.GetType() { case TypeRule: rule := node.(Rule) id := rule.GetId() if ruleReached[id] { fmt.Fprintf(os.Stderr, "possible infinite left recursion in rule '%v'\n", node) return false } ruleReached[id] = true consumes := checkRecursion(rule.GetExpression()) ruleReached[id] = false return consumes case TypeAlternate: for element := node.(List).Front(); element != nil; element = element.Next() { if !checkRecursion(element.Value.(Node)) { return false } } return true case TypeSequence: for element := node.(List).Front(); element != nil; element = element.Next() { if checkRecursion(element.Value.(Node)) { return true } } case TypeName: return checkRecursion(t.rules[node.String()]) case TypePlus: return checkRecursion(node.(Fix).GetNode()) case TypeCharacter, TypeString: return len(node.String()) > 0 case TypeDot, TypeClass: return true } return false } for _, rule := range t.rules { checkRecursion(rule) } }}) if t._switch { var optimizeAlternates func(node Node) (consumes, eof, peek bool, class *characterClass) cache := make([]struct { reached, consumes, eof, peek bool class *characterClass }, len(t.rules)) optimizeAlternates = func(node Node) (consumes, eof, peek bool, class *characterClass) { switch node.GetType() { case TypeRule: rule := node.(Rule) cache := &cache[rule.GetId()] if cache.reached { consumes, eof, peek, class = cache.consumes, cache.eof, cache.peek, cache.class return } cache.reached = true consumes, eof, peek, class = optimizeAlternates(rule.GetExpression()) cache.consumes, cache.eof, cache.peek, cache.class = consumes, eof, peek, class case TypeName: consumes, eof, peek, class = optimizeAlternates(t.rules[node.String()]) case TypeDot: consumes, class = true, new(characterClass) for index, _ := range *class { class[index] = 0xff } case TypeString, TypeCharacter: consumes, class = true, new(characterClass) b := node.String()[0] if b == '\\' { b = node.String()[1] switch b { case 'a': b = '\a' /* bel */ case 'b': b = '\b' /* bs */ case 'f': b = '\f' /* ff */ case 'n': b = '\n' /* nl */ case 'r': b = '\r' /* cr */ case 't': b = '\t' /* ht */ case 'v': b = '\v' /* vt */ } } class.add(b) case TypeClass: consumes, class = true, t.classes[node.String()] case TypeAlternate: consumes, peek, class = true, true, new(characterClass) alternate := node.(List) mconsumes, meof, mpeek, properties, c := consumes, eof, peek, make([]struct { intersects bool class *characterClass }, alternate.Len()), 0 for element := alternate.Front(); element != nil; element = element.Next() { mconsumes, meof, mpeek, properties[c].class = optimizeAlternates(element.Value.(Node)) consumes, eof, peek = consumes && mconsumes, eof || meof, peek && mpeek if properties[c].class != nil { class.union(properties[c].class) } c++ } if eof { break } intersections := 2 compare: for ai, a := range properties[0 : len(properties)-1] { for _, b := range properties[ai+1:] { for i, v := range *a.class { if (b.class[i] & v) != 0 { intersections++ properties[ai].intersects = true continue compare } } } } if intersections < len(properties) { c, unordered, ordered, max := 0, &nodeList{Type: TypeUnorderedAlternate}, &nodeList{Type: TypeAlternate}, 0 for element := alternate.Front(); element != nil; element = element.Next() { if properties[c].intersects { ordered.PushBack(element.Value) } else { class := &token{Type: TypeClass, string: properties[c].class.String(), class: properties[c].class} sequence, predicate := &nodeList{Type: TypeSequence}, &fix{Type: TypePeekFor, node: class} sequence.PushBack(predicate) sequence.PushBack(element.Value) length := properties[c].class.len() if length > max { unordered.PushBack(sequence) max = length } else { unordered.PushFront(sequence) } } c++ } alternate.Init() if ordered.Len() == 0 { alternate.SetType(TypeUnorderedAlternate) for element := unordered.Front(); element != nil; element = element.Next() { alternate.PushBack(element.Value) } } else { for element := ordered.Front(); element != nil; element = element.Next() { alternate.PushBack(element.Value) } alternate.PushBack(unordered) } } case TypeSequence: sequence := node.(List) meof, classes, c, element := eof, make([]struct { peek bool class *characterClass }, sequence.Len()), 0, sequence.Front() for ; !consumes && element != nil; element, c = element.Next(), c+1 { consumes, meof, classes[c].peek, classes[c].class = optimizeAlternates(element.Value.(Node)) eof, peek = eof || meof, peek || classes[c].peek } eof, peek, class = !consumes && eof, !consumes && peek, new(characterClass) for c--; c >= 0; c-- { if classes[c].class != nil { if classes[c].peek { class.intersection(classes[c].class) } else { class.union(classes[c].class) } } } for ; element != nil; element = element.Next() { optimizeAlternates(element.Value.(Node)) } case TypePeekNot: peek = true _, eof, _, class = optimizeAlternates(node.(Fix).GetNode()) eof = !eof class = class.copy() class.complement() case TypePeekFor: peek = true fallthrough case TypeQuery, TypeStar: _, eof, _, class = optimizeAlternates(node.(Fix).GetNode()) case TypePlus: consumes, eof, peek, class = optimizeAlternates(node.(Fix).GetNode()) } return } for element := t.Front(); element != nil; element = element.Next() { node := element.Value.(Node) if node.GetType() == TypeRule { optimizeAlternates(node.(*rule)) break } } } out, error := os.Open(file, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644) if error != nil { fmt.Printf("%v: %v\n", file, error) return } defer out.Close() print := func(format string, a ...interface{}) { fmt.Fprintf(out, format, a...) } printSave := func(n uint) { print("\n position%d := position", n) } printRestore := func(n uint) { print(" position = position%d", n) } print( `package %v import "fmt" type %v struct {%v Buffer string Min, Max int rules [%d]func() bool } func (p *%v) Parse() bool { if p.rules[0]() { return true } return false } func (p *%v) PrintError() { line := 1 character := 0 for i, c := range p.Buffer[0:] { if c == '\n' { line++ character = 0 } else { character++ } if i == p.Min { if p.Min != p.Max { fmt.Printf("parse error after line %%v character %%v\n", line, character) } else {break} } else if i == p.Max {break} } fmt.Printf("parse error: unexpected ") if p.Max >= len(p.Buffer) { fmt.Printf("end of file found\n") } else { fmt.Printf("'%%c' at line %%v character %%v\n", p.Buffer[p.Max], line, character) } } func (p *%v) Init() { var position int`, _package, name, state, len(t.rules), name, name, name) hasActions := t.actions.Len() != 0 if hasActions { bits := 0 for length := t.actions.Len(); length != 0; length >>= 1 { bits++ } switch { case bits < 8: bits = 8 case bits < 16: bits = 16 case bits < 32: bits = 32 case bits < 64: bits = 64 } print("\n actions := [...]func(buffer string, begin, end int) {\n") for i := t.actions.Front(); i != nil; i = i.Next() { a := i.Value.(Action) print(" /* %v %v */\n", a.GetId(), a.GetRule()) print(" func(buffer string, begin, end int) {\n") print(" %v\n", a) print(" },\n") } print( ` } var thunkPosition, begin, end int thunks := make([]struct {action uint%d; begin, end int}, 32) do := func(action uint%d) { if thunkPosition == len(thunks) { newThunks := make([]struct {action uint%d; begin, end int}, 2 * len(thunks)) copy(newThunks, thunks) thunks = newThunks } thunks[thunkPosition].action = action thunks[thunkPosition].begin = begin thunks[thunkPosition].end = end thunkPosition++ }`, bits, bits, bits) if counts[TypeCommit] > 0 { print( ` commit := func(thunkPosition0 int) bool { if thunkPosition0 == 0 { for thunk := 0; thunk < thunkPosition; thunk++ { actions[thunks[thunk].action](p.Buffer, thunks[thunk].begin, thunks[thunk].end) } p.Min = position thunkPosition = 0 return true } return false }`) } printSave = func(n uint) { print("\n position%d, thunkPosition%d := position, thunkPosition", n, n) } printRestore = func(n uint) { print(" position, thunkPosition = position%d, thunkPosition%d", n, n) } } if counts[TypeDot] > 0 { print( ` matchDot := func() bool { if position < len(p.Buffer) { position++ return true } else if position >= p.Max { p.Max = position } return false }`) } if counts[TypeCharacter] > 0 { print( ` matchChar := func(c byte) bool { if (position < len(p.Buffer)) && (p.Buffer[position] == c) { position++ return true } else if position >= p.Max { p.Max = position } return false }`) } if counts[TypeString] > 0 { print( ` matchString := func(s string) bool { length := len(s) next := position + length if (next <= len(p.Buffer)) && (p.Buffer[position:next] == s) { position = next return true } else if position >= p.Max { p.Max = position } return false }`) } classes := make(map[string]uint) if len(t.classes) != 0 { print("\n classes := [...][32]uint8 {\n") var index uint for className, classBitmap := range t.classes { classes[className] = index print(" [32]uint8{") for _, b := range *classBitmap { print("%d, ", b) } print("},\n") index++ } print( ` } matchClass := func(class uint) bool { if (position < len(p.Buffer)) && ((classes[class][p.Buffer[position] >> 3] & (1 << (p.Buffer[position] & 7))) != 0) { position++ return true } else if position >= p.Max { p.Max = position } return false }`) } var printRule func(node Node) var compile func(expression Node, ko uint) var label uint printBegin := func() { print("\n {") } printEnd := func() { print("\n }") } printLabel := func(n uint) { print("\n l%d:\t", n) } printJump := func(n uint) { print("\n goto l%d", n) } printRule = func(node Node) { switch node.GetType() { case TypeRule: print("%v <- ", node) expression := node.(Rule).GetExpression() if expression != nil { printRule(expression) } case TypeDot: print(".") case TypeName: print("%v", node) case TypeCharacter, TypeString: print("'%v'", node) case TypeClass: print("[%v]", node) case TypePredicate: print("&{%v}", node) case TypeAction: print("{%v}", node) case TypeCommit: print("commit") case TypeBegin: print("<") case TypeEnd: print(">") case TypeAlternate: print("(") list := node.(List) element := list.Front() printRule(element.Value.(Node)) for element = element.Next(); element != nil; element = element.Next() { print(" / ") printRule(element.Value.(Node)) } if list.GetLastIsEmpty() { print(" /") } print(")") case TypeUnorderedAlternate: print("(") element := node.(List).Front() printRule(element.Value.(Node)) for element = element.Next(); element != nil; element = element.Next() { print(" | ") printRule(element.Value.(Node)) } print(")") case TypeSequence: print("(") element := node.(List).Front() printRule(element.Value.(Node)) for element = element.Next(); element != nil; element = element.Next() { print(" ") printRule(element.Value.(Node)) } print(")") case TypePeekFor: print("&") printRule(node.(Fix).GetNode()) case TypePeekNot: print("!") printRule(node.(Fix).GetNode()) case TypeQuery: printRule(node.(Fix).GetNode()) print("?") case TypeStar: printRule(node.(Fix).GetNode()) print("*") case TypePlus: printRule(node.(Fix).GetNode()) print("+") default: fmt.Fprintf(os.Stderr, "illegal node type: %v\n", node.GetType()) } } compile = func(node Node, ko uint) { switch node.GetType() { case TypeRule: fmt.Fprintf(os.Stderr, "internal error #1 (%v)\n", node) case TypeDot: print("\n if !matchDot() {goto l%d}", ko) case TypeName: name := node.String() rule := t.rules[name] if t.inline && t.rulesCount[name] == 1 { compile(rule.GetExpression(), ko) return } print("\n if !p.rules[%d]() {goto l%d}", rule.GetId(), ko) case TypeCharacter: print("\n if !matchChar('%v') {goto l%d}", node, ko) case TypeString: print("\n if !matchString(\"%v\") {goto l%d}", node, ko) case TypeClass: print("\n if !matchClass(%d) {goto l%d}", classes[node.String()], ko) case TypePredicate: print("\n if !(%v) {goto l%d}", node, ko) case TypeAction: print("\n do(%d)", node.(Action).GetId()) case TypeCommit: print("\n if !(commit(thunkPosition0)) {goto l%d}", ko) case TypeBegin: if hasActions { print("\n begin = position") } case TypeEnd: if hasActions { print("\n end = position") } case TypeAlternate: list := node.(List) ok := label label++ printBegin() element := list.Front() if element.Next() != nil || list.GetLastIsEmpty() { printSave(ok) } for element.Next() != nil { next := label label++ compile(element.Value.(Node), next) printJump(ok) printLabel(next) printRestore(ok) element = element.Next() } if list.GetLastIsEmpty() { done := label label++ compile(element.Value.(Node), done) printJump(ok) printLabel(done) printRestore(ok) } else { compile(element.Value.(Node), ko) } printEnd() printLabel(ok) case TypeUnorderedAlternate: list := node.(List) done, ok := ko, label label++ printBegin() if list.GetLastIsEmpty() { done = label label++ printSave(ok) } print("\n if position == len(p.Buffer) {goto l%d}", done) print("\n switch p.Buffer[position] {") element := list.Front() for ; element.Next() != nil; element = element.Next() { sequence := element.Value.(List).Front() class := sequence.Value.(Fix).GetNode().(Token).GetClass() sequence = sequence.Next() print("\n case") comma := false for d := 0; d < 256; d++ { if class.has(uint8(d)) { if comma { print(",") } s := "" switch uint8(d) { case '\a': s = `\a` /* bel */ case '\b': s = `\b` /* bs */ case '\f': s = `\f` /* ff */ case '\n': s = `\n` /* nl */ case '\r': s = `\r` /* cr */ case '\t': s = `\t` /* ht */ case '\v': s = `\v` /* vt */ case '\'': s = `\'` /* ' */ default: s = fmt.Sprintf("%c", d) } print(" '%s'", s) comma = true } } print(":") compile(sequence.Value.(Node), done) } print("\n default:") compile(element.Value.(List).Front().Next().Value.(Node), done) print("\n }") if list.GetLastIsEmpty() { printJump(ok) printLabel(done) printRestore(ok) } printEnd() printLabel(ok) case TypeSequence: for element := node.(List).Front(); element != nil; element = element.Next() { compile(element.Value.(Node), ko) } case TypePeekFor: ok := label label++ printBegin() printSave(ok) compile(node.(Fix).GetNode(), ko) printRestore(ok) printEnd() case TypePeekNot: ok := label label++ printBegin() printSave(ok) compile(node.(Fix).GetNode(), ok) printJump(ko) printLabel(ok) printRestore(ok) printEnd() case TypeQuery: qko := label label++ qok := label label++ printBegin() printSave(qko) compile(node.(Fix).GetNode(), qko) printJump(qok) printLabel(qko) printRestore(qko) printEnd() printLabel(qok) case TypeStar: again := label label++ out := label label++ printLabel(again) printBegin() printSave(out) compile(node.(Fix).GetNode(), out) printJump(again) printLabel(out) printRestore(out) printEnd() case TypePlus: again := label label++ out := label label++ compile(node.(Fix).GetNode(), ko) printLabel(again) printBegin() printSave(out) compile(node.(Fix).GetNode(), out) printJump(again) printLabel(out) printRestore(out) printEnd() default: fmt.Fprintf(os.Stderr, "illegal node type: %v\n", node.GetType()) } } print("\n p.rules = [...]func() bool {") for element := t.Front(); element != nil; element = element.Next() { node := element.Value.(Node) if node.GetType() != TypeRule { continue } rule := node.(*rule) expression := rule.GetExpression() if expression == nil { fmt.Fprintf(os.Stderr, "rule '%v' used but not defined\n", rule) print("\n nil,") continue } ko := label label++ print("\n /* %v ", rule.GetId()) printRule(rule) print(" */") if count, ok := t.rulesCount[rule.String()]; !ok { fmt.Fprintf(os.Stderr, "rule '%v' defined but not used\n", rule) print("\n nil,") continue } else if t.inline && count == 1 && ko != 0 { print("\n nil,") continue } print("\n func() bool {") if !expression.GetType().IsSafe() { printSave(0) } compile(expression, ko) print("\n return true") if !expression.GetType().IsSafe() { printLabel(ko) printRestore(0) print("\n return false") } print("\n },") } print("\n }") print("\n}\n") }
func (ls *libstore) GetList(key string) ([]string, error) { now := time.Now() ls.initiateKeyListMutex(key) ls.keyListMutex[key].Lock() defer ls.keyListMutex[key].Unlock() value, ok := ls.keylist[key] if ok { validUntil := value.lease.startFrom.Add(time.Duration(value.lease.validSeconds) * time.Second) if now.After(validUntil) { delete(ls.keylist, key) ok = !ok } } list, list_ok := ls.keyListhistory[key] if list_ok { for list.Len() > 0 { e := list.Front() pretime := e.Value.(time.Time) judgetime := pretime.Add(time.Duration(storagerpc.QueryCacheSeconds) * time.Second) if judgetime.After(now) && list.Len() <= storagerpc.QueryCacheThresh { break } list.Remove(list.Front()) } list.PushBack(now) // do not know wether count cache or not } if ok { //use cache return value.list, nil } else { // use the storage want := false if ls.mode == Always { want = true } if ls.mode == Normal && list_ok && ls.keyListhistory[key].Len() >= storagerpc.QueryCacheThresh { want = true } args := &storagerpc.GetArgs{ Key: key, WantLease: want, HostPort: ls.myHostPort, } reply := &storagerpc.GetListReply{} server := ls.Findshashring(key) client, ok := ls.clientmap[server] if !ok { clienttemp, err := rpc.DialHTTP("tcp", server) if err != nil { return nil, errors.New("meet error when DialHTTP") } ls.clientmap[server] = clienttemp client = clienttemp } err := client.Call("StorageServer.GetList", args, &reply) if err != nil { return nil, errors.New("error when libstore call get to storageserver") } if reply.Status == storagerpc.OK { if reply.Lease.Granted == true { // update cache ls.keylist[key] = &listlib{ list: reply.Value, lease: leasetype{ startFrom: now, validSeconds: reply.Lease.ValidSeconds, }, } } } else if reply.Status == storagerpc.KeyNotFound { return make([]string, 0), nil } else { return nil, errors.New("reply not ready getlist: " + string(reply.Status)) } return reply.Value, nil } }
func (t *Tree) Compile(out io.Writer, optiFlags string) { counts := [TypeLast]uint{} nvar := 0 O := parseOptiFlags(optiFlags) for element := t.Front(); element != nil; element = element.Next() { node := element.Value.(Node) switch node.GetType() { case TypeRule: rule := node.(*rule) t.rules[rule.String()] = rule nvar += len(rule.variables) } } for name, r := range t.rules { if r.name == "" { r := &rule{name: name, id: t.ruleId} t.ruleId++ t.rules[name] = r t.PushBack(r) } } join([]func(){ func() { var countTypes func(node Node) countTypes = func(node Node) { t := node.GetType() counts[t]++ switch t { case TypeRule: countTypes(node.(Rule).GetExpression()) case TypeAlternate, TypeUnorderedAlternate, TypeSequence: for element := node.(List).Front(); element != nil; element = element.Next() { countTypes(element.Value.(Node)) } case TypePeekFor, TypePeekNot, TypeQuery, TypeStar, TypePlus: countTypes(node.(List).Front().Value.(Node)) } } for _, rule := range t.rules { countTypes(rule) } }, func() { var countRules func(node Node) ruleReached := make([]bool, len(t.rules)) countRules = func(node Node) { switch node.GetType() { case TypeRule: rule := node.(Rule) name, id := rule.String(), rule.GetId() if count, ok := t.rulesCount[name]; ok { t.rulesCount[name] = count + 1 } else { t.rulesCount[name] = 1 } if ruleReached[id] { return } ruleReached[id] = true countRules(rule.GetExpression()) case TypeName: countRules(t.rules[node.String()]) case TypeAlternate, TypeUnorderedAlternate, TypeSequence: for element := node.(List).Front(); element != nil; element = element.Next() { countRules(element.Value.(Node)) } case TypePeekFor, TypePeekNot, TypeQuery, TypeStar, TypePlus: countRules(node.(List).Front().Value.(Node)) } } for element := t.Front(); element != nil; element = element.Next() { node := element.Value.(Node) if node.GetType() == TypeRule { countRules(node.(*rule)) break } } }, func() { var checkRecursion func(node Node) bool ruleReached := make([]bool, len(t.rules)) checkRecursion = func(node Node) bool { switch node.GetType() { case TypeRule: rule := node.(Rule) id := rule.GetId() if ruleReached[id] { fmt.Fprintf(os.Stderr, "possible infinite left recursion in rule '%v'\n", node) return false } ruleReached[id] = true consumes := checkRecursion(rule.GetExpression()) ruleReached[id] = false return consumes case TypeAlternate: for element := node.(List).Front(); element != nil; element = element.Next() { if !checkRecursion(element.Value.(Node)) { return false } } return true case TypeSequence: for element := node.(List).Front(); element != nil; element = element.Next() { if checkRecursion(element.Value.(Node)) { return true } } case TypeName: return checkRecursion(t.rules[node.String()]) case TypePlus: return checkRecursion(node.(List).Front().Value.(Node)) case TypeCharacter, TypeString: return len(node.String()) > 0 case TypeDot, TypeClass: return true } return false } for _, rule := range t.rules { checkRecursion(rule) } }}) var inlineLeafes func(node Node) Node inlineLeafes = func(node Node) (ret Node) { ret = node switch node.GetType() { case TypeRule: rule := node.(Rule) switch x := rule.GetExpression(); x.GetType() { case TypeCharacter, TypeDot, TypeClass, TypeString: ret = x case TypePlus, TypeStar, TypeQuery, TypePeekNot, TypePeekFor: switch x.(List).Front().Value.(Node).GetType() { case TypeCharacter, TypeDot, TypeClass, TypeString: ret = x } } case TypeName: r := t.rules[node.String()] x := inlineLeafes(r) if r != x { stats.inlineLeafs++ ret = x } case TypeSequence, TypeAlternate: for el := node.(List).Front(); el != nil; el = el.Next() { el.Value = inlineLeafes(el.Value.(Node)) } case TypePlus, TypeStar, TypeQuery, TypePeekNot, TypePeekFor: v := &node.(List).Front().Value *v = inlineLeafes((*v).(Node)) } return } if O.inlineLeafs { for _, rule := range t.rules { inlineLeafes(rule.GetExpression()) } } if t._switch { var optimizeAlternates func(node Node) (consumes, eof, peek bool, class *characterClass) cache := make([]struct { reached, consumes, eof, peek bool class *characterClass }, len(t.rules)) optimizeAlternates = func(node Node) (consumes, eof, peek bool, class *characterClass) { switch node.GetType() { case TypeRule: rule := node.(Rule) if t.switchExcl != nil && t.switchExcl[rule.String()] { return } cache := &cache[rule.GetId()] if cache.reached { consumes, eof, peek, class = cache.consumes, cache.eof, cache.peek, cache.class if class == nil { class = anyChar } return } cache.reached = true consumes, eof, peek, class = optimizeAlternates(rule.GetExpression()) cache.consumes, cache.eof, cache.peek, cache.class = consumes, eof, peek, class case TypeName: consumes, eof, peek, class = optimizeAlternates(t.rules[node.String()]) case TypeDot: consumes, class = true, new(characterClass) for index, _ := range *class { class[index] = 0xff } case TypeString, TypeCharacter: if node.String() == "" { consumes, class = true, anyChar return } consumes, class = true, new(characterClass) b := node.String()[0] if b == '\\' { b = node.String()[1] switch b { case 'a': b = '\a' /* bel */ case 'b': b = '\b' /* bs */ case 'f': b = '\f' /* ff */ case 'n': b = '\n' /* nl */ case 'r': b = '\r' /* cr */ case 't': b = '\t' /* ht */ case 'v': b = '\v' /* vt */ default: if s := node.String(); len(s) == 4 { b = (s[1]-'0')*64 + (s[2]-'0')*8 + s[3] - '0' } } } class.add(b) case TypeClass: consumes, class = true, t.Classes[node.String()].Class case TypeAlternate: consumes, peek, class = true, true, new(characterClass) alternate := node.(List) mconsumes, meof, mpeek, properties, c := consumes, eof, peek, make([]struct { intersects bool class *characterClass }, alternate.Len()), 0 empty := false for element := alternate.Front(); element != nil; element = element.Next() { mconsumes, meof, mpeek, properties[c].class = optimizeAlternates(element.Value.(Node)) consumes, eof, peek = consumes && mconsumes, eof || meof, peek && mpeek if properties[c].class != nil { class.union(properties[c].class) if properties[c].class.len() == 0 { empty = true } } c++ } if eof { break } intersections := 0 compare: for ai, a := range properties[0 : len(properties)-1] { for _, b := range properties[ai+1:] { for i, v := range *a.class { if (b.class[i] & v) != 0 { intersections++ properties[ai].intersects = true continue compare } } } } if empty { class = new(characterClass) consumes = false break } if intersections < len(properties) && len(properties) >= 2 { c, unordered, ordered, max := 0, &nodeList{Type: TypeUnorderedAlternate}, &nodeList{Type: TypeAlternate}, 0 for element := alternate.Front(); element != nil; element = element.Next() { if properties[c].intersects { ordered.PushBack(element.Value) } else { class := &token{Type: TypeClass, string: properties[c].class.String(), class: properties[c].class} sequence, predicate, length := &nodeList{Type: TypeSequence}, &nodeList{Type: TypePeekFor}, properties[c].class.len() predicate.PushBack(class) sequence.PushBack(predicate) sequence.PushBack(element.Value) if element.Value.(Node).GetType() == TypeString && element.Value.(Node).String() == "" { unordered.PushBack(sequence) } else if element.Value.(Node).GetType() == TypeNil { unordered.PushBack(sequence) } else if length > max { unordered.PushBack(sequence) max = length } else { unordered.PushFront(sequence) } } c++ } alternate.Init() if ordered.Len() == 0 { alternate.SetType(TypeUnorderedAlternate) for element := unordered.Front(); element != nil; element = element.Next() { alternate.PushBack(element.Value) } } else { for element := ordered.Front(); element != nil; element = element.Next() { alternate.PushBack(element.Value) } if unordered.Len() == 1 { alternate.PushBack(unordered.Front().Value.(List).Front().Next().Value) } else { alternate.PushBack(unordered) } } } case TypeSequence: sequence := node.(List) meof, classes, c, element := eof, make([]struct { peek bool class *characterClass }, sequence.Len()), 0, sequence.Front() for ; !consumes && element != nil; element, c = element.Next(), c+1 { consumes, meof, classes[c].peek, classes[c].class = optimizeAlternates(element.Value.(Node)) eof, peek = eof || meof, peek || classes[c].peek } eof, peek, class = !consumes && eof, !consumes && peek, new(characterClass) for c--; c >= 0; c-- { if classes[c].class != nil { if classes[c].peek { class.intersection(classes[c].class) } else { class.union(classes[c].class) } } } for ; element != nil; element = element.Next() { optimizeAlternates(element.Value.(Node)) } case TypePeekNot: peek = true // might be buggy _, eof, _, _ = optimizeAlternates(node.(List).Front().Value.(Node)) class = new(characterClass) eof = !eof class = class.copy() class.complement() case TypePeekFor: peek = true fallthrough case TypeQuery, TypeStar: _, eof, _, class = optimizeAlternates(node.(List).Front().Value.(Node)) case TypePlus: consumes, eof, peek, class = optimizeAlternates(node.(List).Front().Value.(Node)) case TypeAction, TypeNil: class = new(characterClass) } return } for element := t.Front(); element != nil; element = element.Next() { node := element.Value.(Node) if node.GetType() == TypeRule { optimizeAlternates(node.(*rule)) break } } } w := newWriter(out) w.elimRestore = O.elimRestore print := func(format string, a ...interface{}) { if !w.dryRun { fmt.Fprintf(w, format, a...) } } var printRule func(node Node) var compile func(expression Node, ko *label) (chgFlags, chgFlags) printRule = func(node Node) { switch node.GetType() { case TypeRule: print("%v <- ", node) expression := node.(Rule).GetExpression() if expression != nilNode { printRule(expression) } case TypeDot: print(".") case TypeName: print("%v", node) case TypeCharacter, TypeString: print("'%v'", node) case TypeClass: print("[%v]", node) case TypePredicate: print("&{%v}", node) case TypeAction: print("{%v}", node) case TypeCommit: print("commit") case TypeBegin: print("<") case TypeEnd: print(">") case TypeAlternate: print("(") list := node.(List) element := list.Front() printRule(element.Value.(Node)) for element = element.Next(); element != nil; element = element.Next() { print(" / ") printRule(element.Value.(Node)) } print(")") case TypeUnorderedAlternate: print("(") element := node.(List).Front() printRule(element.Value.(Node)) for element = element.Next(); element != nil; element = element.Next() { print(" | ") printRule(element.Value.(Node)) } print(")") case TypeSequence: print("(") element := node.(List).Front() printRule(element.Value.(Node)) for element = element.Next(); element != nil; element = element.Next() { print(" ") printRule(element.Value.(Node)) } print(")") case TypePeekFor: print("&") printRule(node.(List).Front().Value.(Node)) case TypePeekNot: print("!") printRule(node.(List).Front().Value.(Node)) case TypeQuery: printRule(node.(List).Front().Value.(Node)) print("?") case TypeStar: printRule(node.(List).Front().Value.(Node)) print("*") case TypePlus: printRule(node.(List).Front().Value.(Node)) print("+") default: fmt.Fprintf(os.Stderr, "illegal node type: %v\n", node.GetType()) } } compileExpression := func(rule *rule, ko *label) (cko, c*k chgFlags) { nvar := len(rule.variables) if nvar > 0 { w.lnPrint("doarg(yyPush, %d)", nvar) } cko, c*k = compile(rule.GetExpression(), ko) if nvar > 0 { w.lnPrint("doarg(yyPop, %d)", nvar) cko.thPos = true c*k.thPos = true } return } canCompilePeek := func(node Node, jumpIfTrue bool, label *label) bool { if !O.peek { return false } switch node.GetType() { case TypeDot: label.cJump(jumpIfTrue, "(position < len(p.Buffer))") stats.Peek.Dot++ case TypeCharacter: label.cJump(jumpIfTrue, "peekChar('%v')", node) stats.Peek.Char++ case TypeClass: label.cJump(jumpIfTrue, "peekClass(%d)", t.Classes[node.String()].Index) stats.Peek.Class++ case TypePredicate: label.cJump(jumpIfTrue, "(%v)", node) default: return false } return true } compile = func(node Node, ko *label) (chgko, chgok chgFlags) { updateFlags := func(cko, c*k chgFlags) (chgFlags, chgFlags) { chgko, chgok = updateChgFlags(chgko, chgok, cko, c*k) return chgko, chgok } switch node.GetType() { case TypeRule: fmt.Fprintf(os.Stderr, "internal error #1 (%v)\n", node) case TypeDot: ko.cJump(false, "matchDot()") stats.Match.Dot++ chgok.pos = true case TypeName: varp := node.(*name).varp name := node.String() rule := t.rules[name] if t.inline && t.rulesCount[name] == 1 { chgko, chgok = compileExpression(rule, ko) } else { ko.cJump(false, "p.rules[rule%s]()", rule.GoString()) if len(rule.variables) != 0 || rule.hasActions { chgok.thPos = true } chgok.pos = true // safe guess } if varp != nil { w.lnPrint("doarg(yySet, %d)", varp.offset) chgok.thPos = true } case TypeCharacter: ko.cJump(false, "matchChar('%v')", node) stats.Match.Char++ chgok.pos = true case TypeString: if s := node.String(); s != "" { ko.cJump(false, "matchString(\"%s\")", s) stats.Match.String++ chgok.pos = true } case TypeClass: ko.cJump(false, "matchClass(%d)", t.Classes[node.String()].Index) chgok.pos = true case TypePredicate: ko.cJump(false, "(%v)", node) case TypeAction: w.lnPrint("do(%d)", node.(Action).GetId()) chgok.thPos = true case TypeCommit: ko.cJump(false, "(commit(thunkPosition0))") chgko.thPos = true case TypeBegin: if t.Actions != nil { w.lnPrint("begin = position") } case TypeEnd: if t.Actions != nil { w.lnPrint("end = position") } case TypeAlternate: list := node.(List) ok := w.newLabel() element := list.Front() if ok.unsafe() { w.begin() ok.save() } var next *label for element.Next() != nil { next = w.newLabel() cko, _ := updateFlags(compile(element.Value.(Node), next)) ok.jump() if next.used { ok.lrestore(next, cko.pos, cko.thPos) } element = element.Next() } if next == nil || next.used { updateFlags(compile(element.Value.(Node), ko)) } if ok.unsafe() { w.end() } if ok.used { ok.label() } case TypeUnorderedAlternate: list := node.(List) done, ok := ko, w.newLabel() w.begin() done.cJump(true, "position == len(p.Buffer)") w.lnPrint("switch p.Buffer[position] {") element := list.Front() for ; element != nil; element = element.Next() { sequence := element.Value.(List).Front() class := sequence.Value.(List).Front().Value.(Node).(Token).GetClass() node := sequence.Next().Value.(Node) if element.Next() == nil { if class.len() > 2 { w.lnPrint("default:") w.indent++ updateFlags(compile(node, done)) w.indent-- break } } w.lnPrint("case") comma := false for d := 0; d < 256; d++ { if class.has(uint8(d)) { if comma { print(",") } s := "" switch uint8(d) { case '\a': s = `\a` /* bel */ case '\b': s = `\b` /* bs */ case '\f': s = `\f` /* ff */ case '\n': s = `\n` /* nl */ case '\r': s = `\r` /* cr */ case '\t': s = `\t` /* ht */ case '\v': s = `\v` /* vt */ case '\\': s = `\\` /* \ */ case '\'': s = `\'` /* ' */ default: switch { case d >= 0 && d < 32 || d >= 0x80: s = fmt.Sprintf("\\%03o", d) default: s = fmt.Sprintf("%c", d) } } print(" '%s'", s) comma = true } } print(":") w.indent++ if O.unorderedFirstItem { updateFlags(compileOptFirst(w, node, done, compile)) } else { updateFlags(compile(node, done)) } w.lnPrint("break") w.indent-- if element.Next() == nil { w.lnPrint("default:") w.indent++ done.jump() w.indent-- } } w.lnPrint("}") w.end() if ok.used { ok.label() } case TypeSequence: var cs []string var peek Type var element0 = node.(List).Front() if O.seqPeekNot { for el := element0; el != nil; el = el.Next() { sub := el.Value.(Node) switch typ := sub.GetType(); typ { case TypePeekNot: switch child := sub.(List).Front().Value.(Node); child.GetType() { case TypeCharacter: cs = append(cs, "'"+child.String()+"'") continue } case TypeDot: if len(cs) > 0 { peek = typ element0 = el.Next() } default: if len(cs) > 1 { peek = typ element0 = el } } break } } if peek != 0 { stats.seqIfNot++ ko.cJump(true, "position == len(p.Buffer)") w.lnPrint("switch p.Buffer[position] {") w.lnPrint("case %s:", strings.Join(cs, ", ")) w.indent++ ko.jump() w.indent-- w.lnPrint("default:") w.indent++ if peek == TypeDot { w.lnPrint("position++") chgok.pos = true } } for element := element0; element != nil; element = element.Next() { cko, c*k := compile(element.Value.(Node), ko) if element.Next() == nil { if chgok.pos { cko.pos = true } if chgok.thPos { cko.thPos = true } } updateFlags(cko, c*k) } if peek != 0 { w.indent-- w.lnPrint("}") } case TypePeekFor: sub := node.(List).Front().Value.(Node) if canCompilePeek(sub, false, ko) { return } l := w.newLabel() l.saveBlock() cko, c*k := compile(sub, ko) l.lrestore(nil, c*k.pos, c*k.thPos) chgko = cko case TypePeekNot: sub := node.(List).Front().Value.(Node) if canCompilePeek(sub, true, ko) { return } ok := w.newLabel() ok.saveBlock() cko, c*k := compile(sub, ok) ko.jump() if ok.used { ok.restore(cko.pos, cko.thPos) } chgko = c*k case TypeQuery: sub := node.(List).Front().Value.(Node) switch sub.GetType() { case TypeCharacter: w.lnPrint("matchChar('%v')", sub) chgok.pos = true return case TypeDot: w.lnPrint("matchDot()") chgok.pos = true return } qko := w.newLabel() qok := w.newLabel() qko.saveBlock() cko, c*k := compile(sub, qko) if qko.unsafe() { qok.jump() } if qko.used { qko.restore(cko.pos, cko.thPos) } if qko.unsafe() { qok.label() } chgok = c*k case TypeStar: again := w.newLabel() out := w.newLabel() again.label() out.saveBlock() cko, c*k := compile(node.(List).Front().Value.(Node), out) again.jump() out.restore(cko.pos, cko.thPos) chgok = c*k case TypePlus: again := w.newLabel() out := w.newLabel() updateFlags(compile(node.(List).Front().Value.(Node), ko)) again.label() out.saveBlock() cko, _ := compile(node.(List).Front().Value.(Node), out) again.jump() if out.used { out.restore(cko.pos, cko.thPos) } case TypeNil: default: fmt.Fprintf(os.Stderr, "illegal node type: %v\n", node.GetType()) } return } // dry compilation // figure out which items need to restore position resp. thunkPosition, // storing into w.saveFlags w.setDry(true) for element := t.Front(); element != nil; element = element.Next() { node := element.Value.(Node) if node.GetType() != TypeRule { continue } rule := node.(*rule) expression := rule.GetExpression() if expression == nilNode { continue } ko := w.newLabel() ko.sid = 0 if count, ok := t.rulesCount[rule.String()]; !ok { } else if t.inline && count == 1 && ko.id != 0 { continue } ko.save() cko, _ := compileExpression(rule, ko) if ko.used { ko.restore(cko.pos, cko.thPos) } } w.setDry(false) if Verbose { log.Printf("%+v\n", stats) } tpl := template.New("parser") tpl.Funcs(template.FuncMap{ "len": itemLength, "def": func(key string) string { return t.defines[key] }, "id": func(identifier string) string { if t.defines["noexport"] != "" { return identifier } return strings.Title(identifier) }, "stats": func() *statValues { return &stats }, "nvar": func() int { return nvar }, "numRules": func() int { return len(t.rules) }, "sortedRules": func() (r []*rule) { for el := t.Front(); el != nil; el = el.Next() { node := el.Value.(Node) if node.GetType() != TypeRule { continue } r = append(r, node.(*rule)) } return }, "hasCommit": func() bool { return counts[TypeCommit] > 0 }, "actionBits": func() (bits int) { for n := len(t.Actions); n != 0; n >>= 1 { bits++ } switch { case bits < 8: bits = 8 case bits < 16: bits = 16 case bits < 32: bits = 32 case bits < 64: bits = 64 } return }, }) if _, err := tpl.Parse(parserTemplate); err != nil { log.Fatal(err) } if err := tpl.Execute(w, t); err != nil { log.Fatal(err) } /* now for the real compile pass */ for element := t.Front(); element != nil; element = element.Next() { node := element.Value.(Node) if node.GetType() != TypeRule { continue } rule := node.(*rule) expression := rule.GetExpression() if expression == nilNode { fmt.Fprintf(os.Stderr, "rule '%v' used but not defined\n", rule) w.lnPrint("nil,") continue } ko := w.newLabel() ko.sid = 0 w.lnPrint("/* %v ", rule.GetId()) printRule(rule) print(" */") if count, ok := t.rulesCount[rule.String()]; !ok { fmt.Fprintf(os.Stderr, "rule '%v' defined but not used\n", rule) } else if t.inline && count == 1 && ko.id != 0 { w.lnPrint("nil,") continue } w.lnPrint("func() bool {") w.indent++ ko.save() cko, _ := compileExpression(rule, ko) w.lnPrint("return true") if ko.used { ko.restore(cko.pos, cko.thPos) w.lnPrint("return false") } w.indent-- w.lnPrint("},") } print("\n\t}") print("\n}\n") for _, s := range t.trailers { print("%s", s) } }
// The command module takes as input a map, and runs that command. // // Parameters in the input map are: // :command, a list or vector, giving the command to run. Required. // :env, a map of names to values; if specified, these are added to the environment when running the command; optional // :input, a string to pass to the command's stdin; optional func (this Command) Exec(input types.Value) (output types.Value, err error) { var command []string var commandMap types.Map if m, ok := input.(types.Map); ok { commandMap = m } else { err = errors.New("input must be a map") return } var commandEntry = commandMap[types.Keyword("command")] if commandEntry == nil { err = errors.New("require at least :command in input") return } else if l, ok := commandEntry.(*types.List); ok { var list = (*list.List)(l) command = make([]string, list.Len()) var i = 0 for e := list.Front(); e != nil; e = e.Next() { if elem, ok := e.Value.(types.String); ok { command[i] = string(elem) i++ } else { err = errors.New(":command must be a list of strings") return } } } else if v, ok := commandEntry.(types.Vector); ok { var vect = ([]types.Value)(v) command = make([]string, len(vect)) for i, e := range vect { if elem, ok := e.(types.String); ok { command[i] = string(elem) } else { err = errors.New(":command must be a vector of strings") return } } } else { err = errors.New("expected a list or vector as :command") return } var cmd = exec.Command(command[0], command[1:]...) var envEntry = commandMap[types.Keyword("env")] if envEntry != nil { if e, ok := envEntry.(types.Map); ok { var env = make([]string, len(e)) var i = 0 for k := range e { v := e[k] if kk, ok := k.(types.String); ok && len(kk) > 0 { if vv, ok := v.(types.String); ok && len(vv) > 0 { env[i] = fmt.Sprint(string(kk), "=", string(vv)) } else { err = errors.New(":env values must be nonempty strings") return } } else { err = errors.New(":env keys must be nonempty strings") return } i++ } cmd.Env = env } else { err = errors.New(":env must be a map if specified") return } } var stdinEntry = commandMap[types.Keyword("input")] if stdinEntry != nil { if stdin, ok := stdinEntry.(types.String); ok { cmd.Stdin = strings.NewReader(string(stdin)) } else { err = errors.New(":input must be a string if specified") return } } var stderr = new(bytes.Buffer) var stdout = new(bytes.Buffer) cmd.Stderr = stderr cmd.Stdout = stdout err = cmd.Run() if err != nil { output = types.Map{ types.Keyword("success"): types.Bool(false), types.Keyword("err"): types.String(stderr.String()), types.Keyword("out"): types.String(stdout.String()), types.Keyword("system-time"): types.Float(cmd.ProcessState.SystemTime().Seconds()), types.Keyword("user-time"): types.Float(cmd.ProcessState.UserTime().Seconds()), } return } output = types.Map{ types.Keyword("success"): types.Bool(true), types.Keyword("err"): types.String(stderr.String()), types.Keyword("out"): types.String(stdout.String()), types.Keyword("system-time"): types.Float(cmd.ProcessState.SystemTime().Seconds()), types.Keyword("user-time"): types.Float(cmd.ProcessState.UserTime().Seconds()), } return }