package main import ( "bufio" "fmt" "io/ioutil" "strings" ) func assign(s string, index []string, val string, envs []environ) string { if len(index) == 0 { return val } list := parseList(s) i := toInt(&_unknown{s: index[0]}, envs) return spliceList(list, i, 1, assign(indexOfList(list, i), index[1:], val, envs)) } func setValue(s string, val value, envs []environ) (value, error) { if !isNameWithIndex(&_unknown{s: s}) { return nil, fmt.Errorf("set: %s (%s)", errInvalidName, s) } name, index := toNameWithIndex(&_unknown{s: s}) _, ok := reserved[name] if ok { return nil, fmt.Errorf("set: %s (%s)", errNameReserved, name) } oldVal, ok := envs[0][name] if ok { delete(envs[0], name) if len(index) > 0 { val = &_unknown{s: assign(oldVal.String(), index, val.String(), envs)} } } else if len(index) > 0 { return nil, fmt.Errorf("set: %s (%s)", errNameNotFound, name) } val = toValue(val, envs) envs[0][name] = val return val, nil } func getValue(s string, envs []environ) (value, error) { if !isNameWithIndex(&_unknown{s: s}) { return nil, fmt.Errorf("get: %s (%s)", errInvalidName, s) } name, index := toNameWithIndex(&_unknown{s: s}) for _, env := range envs { val, ok := env[name] if ok { if len(index) > 0 { for _, i := range index { list := parseList(val.String()) r, s := strings.Split(i, ":"), "" if len(r) == 1 { s = indexOfList(list, toInt(&_unknown{s: r[0]}, envs)) if !isList(&_unknown{s: s}) { s = `"` + s } } else { num1, num2 := 0, len(list) if len(r[0]) > 0 { num1 = toInt(&_unknown{s: r[0]}, envs) } if len(r[1]) > 0 { num2 = toInt(&_unknown{s: r[1]}, envs) } s = rangeOfList(list, num1, num2) } val = &_unknown{s: s} } } return val, nil } } return nil, fmt.Errorf("get: %s (%s)", errNameNotFound, name) } func opMake(val1, val2 value, envs []environ) value { val, err := setValue(val1.String(), val2, envs) if err != nil { panic(err) } return val } func opThing(val1 value, envs []environ) value { val, err := getValue(val1.String(), envs) if err != nil { panic(err) } return val } func opErase(val1 value, envs []environ) value { name := toName(val1) for _, env := range envs { val, ok := env[name] if ok { delete(env, name) return val } } panic(fmt.Errorf("erase: %s (%s)", errNameNotFound, name)) } func opExport(val1 value, envs []environ) value { name := toName(val1) val, ok := envs[0][name] if ok { if envs[1] != nil { envs[1][name] = val } return val } panic(fmt.Errorf("export: %s (%s)", errNameNotFound, name)) } func opSave(val1 value, env environ) value { name := toName(val1) s := "" for name, val := range env { s += `make "` + name + " " + val.String() + "\n" } err := ioutil.WriteFile(name, []byte(s), 0666) if err != nil { panic(fmt.Errorf("save: %s (%s)", errFileError, name)) } return val1 } func opLoad(val1 value, env environ) *_bool { name := toName(val1) s, err := ioutil.ReadFile(name) if err != nil { panic(fmt.Errorf("load: %s (%s)", errFileError, name)) } scanner := bufio.NewScanner(strings.NewReader(string(s))) scanner.Split(splitFunc) interpret(&scanProvider{isList: false, scanner: scanner}, []environ{env, nil, nil}) return &_bool{b: true} } func opErAll(env environ) *_bool { for name := range env { delete(env, name) } return &_bool{b: true} } func opPoAll(env environ) *_list { list := []string{} for name := range env { list = append(list, name) } return &_list{list: list} }