瀏覽代碼

FIX. 修复list操作部分问题

RegMs If 4 年之前
父節點
當前提交
e19261f472
共有 6 個文件被更改,包括 132 次插入113 次删除
  1. 16 35
      bind.go
  2. 2 2
      ctrl.go
  3. 4 2
      error.go
  4. 18 8
      in
  5. 87 61
      list.go
  6. 5 5
      mua.go

+ 16 - 35
bind.go

@@ -7,49 +7,30 @@ import (
 	"strings"
 )
 
-func parseFunc(val string) value {
-	if !isList(val) {
-		return value{body: errNop}
-	}
-	list := strings.Split(val, " ")
-	if list[1] != "[" {
-		return value{body: errNop}
-	}
-	i := 2
-	for ; list[i] != "]"; i++ {
-		if !isName(`"` + list[i]) {
-			return value{body: errNop}
-		}
-	}
-	if i == len(list)-2 {
-		return value{body: errNop}
-	}
-	j, bracketCnt := i+1, 0
-	for ; j < len(list)-1; j++ {
-		if list[j] == "[" {
-			bracketCnt++
-		}
-		if list[j] == "]" {
-			bracketCnt--
-		}
-		if bracketCnt == 0 && j < len(list)-2 {
-			return value{body: errNop}
+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:   val,
-		param: list[2:i],
-		body:  strings.Join(list[i+1:len(list)-1], " "),
-		env:   local}
+	return value{val: s, list: list, param: param, env: local}
 }
 
 func getFunc(name string) value {
 	if !isName(`"` + name) {
-		return value{body: errNop}
+		return value{}
 	}
 	envs := []int{len(env) - 1, len(env) - 2, 1}
 	for _, id := range envs {
@@ -58,7 +39,7 @@ func getFunc(name string) value {
 			return val
 		}
 	}
-	return value{body: errNop}
+	return value{}
 }
 
 func opMake(val1, val2 value) value {
@@ -67,7 +48,7 @@ func opMake(val1, val2 value) value {
 	if ok {
 		panic(fmt.Errorf("make: %s (%s)", errNameReserved, name))
 	}
-	if isList(val2.val) && val2.body == "" {
+	if isList(val2.val) && val2.list == nil {
 		val2 = parseFunc(val2.val)
 	}
 	env[len(env)-1][name] = val2

+ 2 - 2
ctrl.go

@@ -22,8 +22,8 @@ func opIf(val1, val2, val3 value) (value, bool) {
 }
 
 func opReturn(val1 value) value {
-	if isList(val1.val) && val1.body == "" {
-		return parseFunc(val1.val)
+	if isList(val1.val) && val1.list == nil {
+		val1 = parseFunc(val1.val)
 	}
 	return val1
 }

+ 4 - 2
error.go

@@ -28,8 +28,10 @@ const errWordOrListExpected = "word or list expected"
 
 const errEmptyWordOrList = "empty word or list"
 
+const errIndexOutOfBound = "index out of bound"
+
+const errIllegalRange = "illegal range"
+
 const errIllegalOperandType = "illegal operand type"
 
 const errFileError = "file error"
-
-const errNop = "nop"

+ 18 - 8
in

@@ -1,3 +1,19 @@
+print word "hello "world
+print word "hello TRUE
+print word "hello -134.5
+
+print sentence 483 "dba
+print sentence sentence [ [ a b ] c ] [ d [ e f ] ] [ g ]
+
+print list 483 "dba
+print list list [ [ a b ] c ] [ d [ e f ] ] [ g ]
+
+print join [ 483 ] "dba
+print join join [ [ a b ] c ] [ d [ e f ] ] [ g ]
+
+print first "hello
+print first butlast list list [ [ a b ] c ] [ d [ e f ] ] [ g ]
+
 make "pow [[a b] [
   if lt :b 1 [
     return 1
@@ -29,7 +45,7 @@ make "fib_out [
         fib :x
     ]
 ]
-print fib_out 3
+print fib_out 20
 
 make "f [[x] [
   make "g [[y] [return add :x :y]]
@@ -57,13 +73,7 @@ print f3 233
 
 make "fun [
     [x]
-    [
-        make "b [
-            [y]
-            [return make "x add :x :y]
-        ]
-        return :b
-    ]
+    [[[y] [make "x add :x :y]]]
 ]
 make "adder fun 5
 print adder 1

+ 87 - 61
list.go

@@ -5,6 +5,69 @@ import (
 	"strings"
 )
 
+func wrapList(list []string) []string {
+	return append(append([]string{"["}, list...), "]")
+}
+
+func parseList(s string) []string {
+	if !isList(s) {
+		panic(fmt.Errorf("parselist: %s (%s)", errListExpected, s))
+	}
+	list, bracketCnt, start, resList := strings.Split(s, " "), 0, 1, []string{}
+	for i := 1; i < len(list)-1; i++ {
+		if list[i] == "[" {
+			bracketCnt++
+		}
+		if list[i] == "]" {
+			bracketCnt--
+		}
+		if bracketCnt == 0 {
+			resList = append(resList, strings.Join(list[start:i+1], " "))
+			start = i + 1
+		}
+	}
+	return resList
+}
+
+func indexOfList(s string, index int) string {
+	if !isList(s) {
+		panic(fmt.Errorf("indexoflist: %s (%s)", errListExpected, s))
+	}
+	list := parseList(s)
+	if index < 0 || index >= len(list) {
+		panic(fmt.Errorf("indexoflist: %s", errIndexOutOfBound))
+	}
+	return list[index]
+}
+
+func rangeOfList(s string, index1, index2 int) string {
+	if !isList(s) {
+		panic(fmt.Errorf("rangeoflist: %s (%s)", errListExpected, s))
+	}
+	list := parseList(s)
+	if index1 < 0 || index1 > len(list) || index2 < 0 || index2 > len(list) {
+		panic(fmt.Errorf("rangeoflist: %s", errIndexOutOfBound))
+	}
+	if index1 > index2 {
+		panic(fmt.Errorf("rangelist: %s", errIllegalRange))
+	}
+	return strings.Join(wrapList(list[index1:index2]), " ")
+}
+
+func spliceList(s string, index int, cnt int, val ...string) string {
+	if !isList(s) {
+		panic(fmt.Errorf("splicelist: %s (%s)", errListExpected, s))
+	}
+	list := parseList(s)
+	if index < 0 || index > len(list) {
+		panic(fmt.Errorf("splicelist: %s", errIndexOutOfBound))
+	}
+	if index+cnt > len(list) {
+		cnt = len(list) - index
+	}
+	return strings.Join(wrapList(append(append(list[:index], val...), list[index+cnt:]...)), " ")
+}
+
 func opWord(val1, val2 value) value {
 	if !isWord(val1.val) {
 		panic(fmt.Errorf("word: %s (%s)", errWordExpceted, val1.val))
@@ -19,20 +82,25 @@ func opWord(val1, val2 value) value {
 }
 
 func opSentence(val1, val2 value) value {
-	return value{val: "[ " +
-		strings.TrimSuffix(strings.TrimPrefix(val1.val, "[ "), " ]") + " " +
-		strings.TrimSuffix(strings.TrimPrefix(val2.val, "[ "), " ]") + " ]"}
+	list1, list2 := []string{val1.val}, []string{val2.val}
+	if isList(val1.val) {
+		list1 = parseList(val1.val)
+	}
+	if isList(val2.val) {
+		list2 = parseList(val2.val)
+	}
+	return value{val: strings.Join(wrapList(append(list1, list2...)), " ")}
 }
 
 func opList(val1, val2 value) value {
-	return value{val: "[ " + val1.val + " " + val2.val + " ]"}
+	return value{val: strings.Join(wrapList([]string{val1.val, val2.val}), " ")}
 }
 
 func opJoin(val1, val2 value) value {
 	if !isList(val1.val) {
 		panic(fmt.Errorf("join: %s (%s)", errListExpected, val1.val))
 	}
-	return value{val: strings.TrimSuffix(val1.val, " ]") + " " + val2.val + " ]"}
+	return value{val: strings.Join(wrapList(append(parseList(val1.val), val2.val)), " ")}
 }
 
 func opFirst(val1 value) value {
@@ -43,22 +111,13 @@ func opFirst(val1 value) value {
 		panic(fmt.Errorf("first: %s (%s)", errEmptyWordOrList, val1.val))
 	}
 	if isWord(val1.val) {
-		return value{val: val1.val[1:2]}
-	}
-	list1 := strings.Split(val1.val, " ")
-	if list1[1] != "[" {
-		return value{val: list1[1]}
+		return value{val: val1.val[:2]}
 	}
-	i, bracketCnt := 2, 1
-	for ; bracketCnt > 0; i++ {
-		if list1[i] == "[" {
-			bracketCnt++
-		}
-		if list1[i] == "]" {
-			bracketCnt--
-		}
+	list1 := parseList(val1.val)
+	if !isList(list1[0]) {
+		list1[0] = `"` + list1[0]
 	}
-	return value{val: strings.Join(list1[1:i], " ")}
+	return value{val: list1[0]}
 }
 
 func opLast(val1 value) value {
@@ -69,22 +128,13 @@ func opLast(val1 value) value {
 		panic(fmt.Errorf("last: %s (%s)", errEmptyWordOrList, val1.val))
 	}
 	if isWord(val1.val) {
-		return value{val: val1.val[len(val1.val)-1:]}
-	}
-	list1 := strings.Split(val1.val, " ")
-	if list1[len(list1)-2] != "]" {
-		return value{val: list1[len(list1)-2]}
+		return value{val: `"` + val1.val[len(val1.val)-1:]}
 	}
-	i, bracketCnt := len(list1)-3, 1
-	for ; bracketCnt > 0; i-- {
-		if list1[i] == "]" {
-			bracketCnt++
-		}
-		if list1[i] == "[" {
-			bracketCnt--
-		}
+	list1 := parseList(val1.val)
+	if !isList(list1[len(list1)-1]) {
+		list1[len(list1)-1] = `"` + list1[len(list1)-1]
 	}
-	return value{val: strings.Join(list1[i+1:len(list1)-1], " ")}
+	return value{val: list1[len(list1)-1]}
 }
 
 func opButFirst(val1 value) value {
@@ -97,20 +147,8 @@ func opButFirst(val1 value) value {
 	if isWord(val1.val) {
 		return value{val: `"` + val1.val[2:]}
 	}
-	list1 := strings.Split(val1.val, " ")
-	if list1[1] != "[" {
-		return value{val: "[ " + strings.Join(list1[2:], " ")}
-	}
-	i, bracketCnt := 2, 1
-	for ; bracketCnt > 0; i++ {
-		if list1[i] == "[" {
-			bracketCnt++
-		}
-		if list1[i] == "]" {
-			bracketCnt--
-		}
-	}
-	return value{val: "[ " + strings.Join(list1[i:], " ")}
+	list1 := parseList(val1.val)
+	return value{val: strings.Join(wrapList(list1[1:]), " ")}
 }
 
 func opButLast(val1 value) value {
@@ -123,18 +161,6 @@ func opButLast(val1 value) value {
 	if isWord(val1.val) {
 		return value{val: val1.val[:len(val1.val)-1]}
 	}
-	list1 := strings.Split(val1.val, " ")
-	if list1[len(list1)-2] != "]" {
-		return value{val: strings.Join(list1[:len(list1)-2], " ") + " ]"}
-	}
-	i, bracketCnt := len(list1)-3, 1
-	for ; bracketCnt > 0; i-- {
-		if list1[i] == "]" {
-			bracketCnt++
-		}
-		if list1[i] == "[" {
-			bracketCnt--
-		}
-	}
-	return value{val: strings.Join(list1[:i+1], " ") + " ]"}
+	list1 := parseList(val1.val)
+	return value{val: strings.Join(wrapList(list1[:len(list1)-1]), " ")}
 }

+ 5 - 5
mua.go

@@ -25,8 +25,8 @@ var reserved = map[string]int{
 type environ map[string]value
 type value struct {
 	val   string
+	list  []string
 	param []string
-	body  string
 	env   environ
 }
 
@@ -109,7 +109,7 @@ func interpret(scanner *bufio.Scanner) (val value, returned bool) {
 				}
 			}
 			stack = append(stack, value{val: strings.Join(list, " ")})
-		} else if '0' <= s[0] && s[0] <= '9' || s[0] == '-' {
+		} else if s[0] >= '0' && s[0] <= '9' || s[0] == '-' {
 			toNumber(s)
 			stack = append(stack, value{val: s})
 		} else {
@@ -218,7 +218,7 @@ func interpret(scanner *bufio.Scanner) (val value, returned bool) {
 					break
 				}
 				val := getFunc(stack[i].val)
-				if val.body != errNop {
+				if val.param != nil {
 					if len(val.param) == len(stack)-1-i {
 						for j := i + 1; j < len(stack); j++ {
 							if !isValue(stack[j].val) {
@@ -230,7 +230,7 @@ func interpret(scanner *bufio.Scanner) (val value, returned bool) {
 							local[name] = stack[i+1+j]
 						}
 						env = append(env, val.env, local)
-						stack[i], _ = opRun(value{val: val.body})
+						stack[i], _ = opRun(value{val: val.list[1]})
 						env = env[:len(env)-2]
 						stack = stack[:i+1]
 						updated = true
@@ -246,7 +246,7 @@ func interpret(scanner *bufio.Scanner) (val value, returned bool) {
 	if len(stack) == stackTop {
 		stack = append(stack, value{val: "[ ]"})
 	}
-	val = stack[len(stack)-1]
+	val = opReturn(stack[len(stack)-1])
 	stack = stack[:stackTop]
 	return
 }