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(value{word: 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(value{word: s}) { return value{}, fmt.Errorf("set: %s (%s)", errInvalidName, s) } name, index := toNameWithIndex(value{word: s}) _, ok := reserved[name] if ok { return value{}, fmt.Errorf("set: %s (%s)", errNameReserved, name) } oldVal, ok := envs[0][name] if ok { delete(envs[0], name) if len(index) > 0 { val = value{word: assign(toString(oldVal), index, toString(val), envs)} } } else if len(index) > 0 { return value{}, fmt.Errorf("set: %s (%s)", errNameNotFound, name) } val = toValue(val, envs[0]) envs[0][name] = val return val, nil } func getValue(s string, envs []environ) (value, error) { if !isNameWithIndex(value{word: s}) { return value{}, fmt.Errorf("get: %s (%s)", errInvalidName, s) } name, index := toNameWithIndex(value{word: s}) for _, env := range envs { val, ok := env[name] if ok { if len(index) > 0 { val = value{word: toString(val)} for _, i := range index { list := parseList(val.word) r := strings.Split(i, ":") if len(r) == 1 { val = value{word: indexOfList(list, toInt(value{word: r[0]}, envs))} if !isList(val) { val.word = `"` + val.word } } else { num1, num2 := 0, len(list) if r[0] != "" { num1 = toInt(value{word: r[0]}, envs) } if r[1] != "" { num2 = toInt(value{word: r[1]}, envs) } val = value{word: rangeOfList(list, num1, num2)} } } } return val, nil } } return value{}, fmt.Errorf("get: %s (%s)", errNameNotFound, name) } func opMake(val1, val2 value, envs []environ) value { val, err := setValue(val1.word, val2, envs) if err != nil { panic(err) } return val } func opThing(val1 value, envs []environ) value { val, err := getValue(val1.word, 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 { envs[2][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.word + "\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) value { 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 value{tp: typeBool, b: true} } func opErAll(env environ) value { for name := range env { delete(env, name) } return value{tp: typeBool, b: true} } func opPoAll(env environ) value { list := []string{} for name := range env { list = append(list, name) } return value{word: makeList(list)} }