Bladeren bron

FIX.全局函数不捕获全局变量

RegMs If 4 jaren geleden
bovenliggende
commit
d273270e59
5 gewijzigde bestanden met toevoegingen van 107 en 19 verwijderingen
  1. 4 2
      bind.go
  2. 81 5
      in0
  3. BIN
      mua
  4. 15 7
      mua.go
  5. 7 5
      type.go

+ 4 - 2
bind.go

@@ -34,7 +34,7 @@ func setValue(s string, val value, envs []environ) (value, error) {
 	} else if len(index) > 0 {
 		return value{}, fmt.Errorf("set: %s (%s)", errNameNotFound, name)
 	}
-	val = toValue(val, envs[0])
+	val = toValue(val, envs)
 	envs[0][name] = val
 	return val, nil
 }
@@ -107,7 +107,9 @@ func opExport(val1 value, envs []environ) value {
 	name := toName(val1)
 	val, ok := envs[0][name]
 	if ok {
-		envs[2][name] = val
+		if envs[2] != nil {
+			envs[2][name] = val
+		}
 		return val
 	}
 	panic(fmt.Errorf("export: %s (%s)", errNameNotFound, name))

+ 81 - 5
in0

@@ -1,3 +1,78 @@
+make "fact_base [
+  [rec x]
+  [
+    if eq :x 0
+    [return 1]
+    [return mul :x rec :rec sub :x 1]
+  ]
+]
+
+make "fact_simple [
+  [x]
+  [return fact_base :fact_base :x]
+]
+
+print fact_simple 5
+
+make "fact_nice [
+  [rec]
+  [
+    make "g [
+      [x]
+      [
+        if eq :x 0
+        [return 1]
+        [
+          make "tmp rec :rec
+          return mul :x tmp sub :x 1
+        ]
+      ]
+    ]
+    return :g
+  ]
+]
+
+make "fact_curry fact_nice :fact_nice
+print fact_curry 5
+
+make "fact_nicer [
+  [rec]
+  [
+    make "g [
+      [x]
+      [
+        if eq :x 0
+        [return 1]
+        [return mul :x rec sub :x 1]
+      ]
+    ]
+    return :g
+  ]
+]
+
+make "z_comb [
+  [g]
+  [
+    make "t [
+      [r]
+      [
+        make "y [
+          [yy]
+          [
+            make "tmp r :r
+            return tmp :yy
+          ]
+        ]
+        return g :y
+      ]
+    ]
+    return t :t
+  ]
+]
+
+make "fact_z z_comb :fact_nicer
+print fact_z 5
+
 make "rev_func [
   [f]
   [
@@ -144,9 +219,10 @@ make "f [[x] [
 print f 233
 
 make "f1 [[x] [
-  make "g1 [[y] [return add :x :y]]
-  return :g1
-]]
+    make "g1 [[y] [return add :x :y]]
+    return :g1
+  ]
+]
 make "c1 f1 42
 make "c2 f1 24
 print c1 1
@@ -158,8 +234,8 @@ make "curry_two [[f x] [
 make "f2 [[x y] [
   return add :x :y
 ]]
-make "f3 curry_two :f2 42
-print f3 233
+make "f2p curry_two :f2 42
+print f2p 233
 
 make "fun [
   [x]


+ 15 - 7
mua.go

@@ -48,9 +48,9 @@ func interpret(scanner *scanProvider, envs []environ) (val value, returned bool)
 		}
 		if s[0] == ':' {
 			leading := len(s) - len(strings.TrimLeft(s, ":"))
-			val := toValue(value{word: `"` + s[leading:]}, envs[0])
+			val := toValue(value{word: `"` + s[leading:]}, envs)
 			for i := 0; i < leading; i++ {
-				val = toValue(opThing(val, envs), envs[0])
+				val = toValue(opThing(val, envs), envs)
 			}
 			stack = append(stack, val)
 		} else if s[0] == '[' && !scanner.isList {
@@ -103,7 +103,7 @@ func interpret(scanner *scanProvider, envs []environ) (val value, returned bool)
 					}
 					if paramCnt == len(stack)-1-i {
 						for j := i + 1; j < len(stack); j++ {
-							stack[j] = toValue(stack[j], envs[0])
+							stack[j] = toValue(stack[j], envs)
 						}
 						switch stack[i].word {
 						case "make":
@@ -200,13 +200,21 @@ func interpret(scanner *scanProvider, envs []environ) (val value, returned bool)
 				if val.param != nil {
 					if len(val.param) == len(stack)-1-i {
 						for j := i + 1; j < len(stack); j++ {
-							stack[j] = toValue(stack[j], envs[0])
+							stack[j] = toValue(stack[j], envs)
 						}
 						local := environ{stack[i].word: val}
 						for j, name := range val.param {
 							local[name] = stack[i+1+j]
 						}
-						stack[i], _ = opRun(value{tp: typeList, list: val.body}, []environ{local, val.env, envs[2]})
+						ctx := environ{}
+						for name, val := range val.env {
+							ctx[name] = val
+						}
+						global := envs[0]
+						if envs[2] != nil {
+							global = envs[2]
+						}
+						stack[i], _ = opRun(value{tp: typeList, list: val.body}, []environ{local, ctx, global})
 						stack = stack[:i+1]
 						updated = true
 					}
@@ -219,7 +227,7 @@ func interpret(scanner *scanProvider, envs []environ) (val value, returned bool)
 	if len(stack) == 0 {
 		val = value{tp: typeList, list: []string{}}
 	} else {
-		val = toValue(stack[len(stack)-1], envs[0])
+		val = toValue(stack[len(stack)-1], envs)
 	}
 	return
 }
@@ -236,5 +244,5 @@ func main() {
 	}
 	scanner := bufio.NewScanner(os.Stdin)
 	scanner.Split(splitFunc)
-	interpret(&scanProvider{isList: false, scanner: scanner}, []environ{env, nil, env})
+	interpret(&scanProvider{isList: false, scanner: scanner}, []environ{env, nil, nil})
 }

+ 7 - 5
type.go

@@ -170,7 +170,7 @@ func isList(val value) bool {
 	return val.word != "" && val.word[0] == '['
 }
 
-func parseFunc(s string, env environ) value {
+func parseFunc(s string, envs []environ) value {
 	list := parseList(s)
 	if len(list) != 2 || !isList(value{word: list[0]}) || !isList(value{word: list[1]}) {
 		return value{tp: typeList, list: list}
@@ -182,8 +182,10 @@ func parseFunc(s string, env environ) value {
 		}
 	}
 	local := environ{}
-	for name, val := range env {
-		local[name] = val
+	if envs[2] != nil {
+		for name, val := range envs[0] {
+			local[name] = val
+		}
 	}
 	return value{tp: typeList, list: list, param: param, body: parseList(list[1]), env: local}
 }
@@ -198,7 +200,7 @@ func isEmpty(val value) bool {
 	return val.word == `"` || val.word == "[ ]"
 }
 
-func toValue(val value, env environ) value {
+func toValue(val value, envs []environ) value {
 	if val.tp != typeUnknown {
 		return val
 	}
@@ -218,7 +220,7 @@ func toValue(val value, env environ) value {
 		return parseWord(val.word)
 	}
 	if isList(val) {
-		return parseFunc(val.word, env)
+		return parseFunc(val.word, envs)
 	}
 	panic(fmt.Errorf("value: %s (%s)", errValueExpected, val.word))
 }