package main import ( "bufio" "fmt" "os" "strings" ) func parseFunc(s string) value { if !isList(s) { return value{val: s} } list := parseList(s) if len(list) != 2 || !isList(list[0]) || !isList(list[1]) { return value{val: s, list: list} } param := parseList(list[0]) for _, name := range param { if !isName(`"` + name) { return value{val: s, list: list} } } local := make(environ) for name, val := range env[len(env)-1] { local[name] = val } return value{val: s, list: list, param: param, env: local} } func getFunc(name string) value { if !isName(`"` + name) { return value{} } envs := []int{len(env) - 1, len(env) - 2, 1} for _, id := range envs { val, ok := env[id][name] if ok { return val } } return value{} } func opMake(val1, val2 value) value { name := toName(val1.val) _, ok := reserved[name] if ok { panic(fmt.Errorf("make: %s (%s)", errNameReserved, name)) } if isList(val2.val) && val2.list == nil { val2 = parseFunc(val2.val) } env[len(env)-1][name] = val2 return val2 } func opThing(val1 value) value { name := toName(val1.val) envs := []int{len(env) - 1, len(env) - 2, 1} for _, id := range envs { val, ok := env[id][name] if ok { return val } } panic(fmt.Errorf("thing: %s (%s)", errNameNotFound, name)) } func opErase(val1 value) value { name := toName(val1.val) val, ok := env[len(env)-1][name] if ok { delete(env[len(env)-1], name) return val } panic(fmt.Errorf("erase: %s (%s)", errNameNotFound, name)) } func opExport(val1 value) value { name := toName(val1.val) val, ok := env[len(env)-1][name] if ok { env[1][name] = val return val } panic(fmt.Errorf("export: %s (%s)", errNameNotFound, name)) } func opSave(val1 value) value { name := toName(val1.val) s := "" for name, val := range env[len(env)-1] { s += `make "` + name + " " + val.val + "\n" } err := os.WriteFile(name, []byte(s), 0666) if err != nil { panic(fmt.Errorf("save: %s (%s)", errFileError, name)) } return val1 } func opLoad(val1 value) value { name := toName(val1.val) s, err := os.ReadFile(name) if err != nil { panic(fmt.Errorf("load: %s (%s)", errFileError, name)) } interpret(bufio.NewScanner(strings.NewReader(string(s)))) return value{val: "true"} } func opErAll() value { env[len(env)-1] = make(environ) return value{val: "true"} } func opPoAll() value { list := []string{} for name := range env[len(env)-1] { list = append(list, name) } return value{val: "[ " + strings.Join(list, " ") + " ]"} }