Selaa lähdekoodia

FIX.修改isname操作逻辑

RegMs If 4 vuotta sitten
vanhempi
commit
4fb29707aa
9 muutettua tiedostoa jossa 262 lisäystä ja 131 poistoa
  1. 1 1
      ctrl.go
  2. 2 0
      error.go
  3. 0 0
      in0
  4. 119 0
      in1
  5. 10 11
      list.go
  6. 3 3
      math.go
  7. BIN
      mua
  8. 106 105
      mua.go
  9. 21 11
      type.go

+ 1 - 1
ctrl.go

@@ -6,7 +6,7 @@ import (
 
 func opRun(val1 value, envs []environ) (value, bool) {
 	if !isList(val1) {
-		panic(fmt.Errorf("run: %s", errListExpected))
+		panic(fmt.Errorf("run: %s (%s)", errListExpected, toString(val1)))
 	}
 	return interpret(&scanProvider{isList: true, list: val1.list}, envs)
 }

+ 2 - 0
error.go

@@ -30,6 +30,8 @@ const errWordOrListExpected = "word or list expected"
 
 const errEmptyWordOrList = "empty word or list"
 
+const errFunctionExpected = "function expected"
+
 const errIndexOutOfBound = "index out of bound"
 
 const errIllegalRange = "illegal range"

+ 0 - 0
in → in0


+ 119 - 0
in1

@@ -0,0 +1,119 @@
+print not gt 3 1
+make "d read
+1234dd
+print isname "d
+print :d
+make "x eq :d "1234dd
+print :x
+erase "d
+print not isname "d
+
+make "a 2
+print isname "a
+erase "a
+print isname "a
+
+make "a 5
+make "b 3
+make "c :b
+print gt "a "b
+print gt :a :b
+print lt :a :b
+print eq :a :b
+print eq :b :c
+print and gt :a :b eq :b :c
+print or gt :b :a eq :b :c
+print not gt :a :b
+print or gt :b :a not eq :b :c
+
+make "testlist [print gt :a :b]
+run :testlist
+make "a 2
+run :testlist
+
+make "a 1
+run [make "a add :a 1 print :a]
+print :a
+
+if gt :a :b [print "A] [print "B]
+
+print if eq :a :b [1] [0]
+
+print isnumber "2
+print isnumber "a
+print isnumber :a
+print isword :a
+print isword "a
+print islist "testlist
+print islist :testlist
+print isbool run :testlist
+
+print isempty :testlist
+print isempty "a
+print isempty "d
+
+make "a 3
+make "a add :a 4
+make "f [
+	[a]
+	[return add mul :a :a 1]
+]
+print f 3
+make "f
+[
+	[]
+	[print "a]
+]
+f
+make "n 5
+make "f [
+	[n]
+	[
+		if lt :n 2
+			[return 1]
+			[return mul :n f sub :n 1]
+	]
+]
+print f :n
+print :n
+make "let [
+	[__a __b]
+	[
+		make :__a :__b
+		export :__a
+	]
+]
+let "a 6
+print :a
+make "a 1
+make "repeat [
+    [n s]
+    [
+		if eq :n 0 
+			[] 
+			[run :s repeat sub :n 1 :s]
+	]
+]
+repeat 4 [make "a add :a 1]
+print :a
+make "n 5
+make "factorial [
+	[n]
+	[
+		if lt :n 2
+			[return 1]
+			[return mul :n factorial sub :n 1]
+	]
+]
+print factorial :n
+print :n
+make "gcd [
+    [a b]
+    [
+        if eq :b 0
+            [return :a]
+            [return gcd :b mod :a :b]
+    ]
+]
+print gcd 18 14
+print gcd 18 13

+ 10 - 11
list.go

@@ -58,7 +58,7 @@ func spliceList(list []string, index int, cnt int, val ...string) string {
 
 func opWord(val1, val2 value) value {
 	if !isWord(val1) || isList(val2) {
-		panic(fmt.Errorf("word: %s", errWordExpceted))
+		panic(fmt.Errorf("word: %s (%s, %s)", errWordExpceted, toString(val1), toString(val2)))
 	}
 	return value{tp: typeWord, word: val1.word + toString(val2)}
 }
@@ -80,18 +80,17 @@ func opList(val1, val2 value) value {
 
 func opJoin(val1, val2 value) value {
 	if !isList(val1) {
-		fmt.Println(val1, val2)
-		panic(fmt.Errorf("join: %s", errListExpected))
+		panic(fmt.Errorf("join: %s (%s)", errListExpected, toString(val1)))
 	}
 	return value{word: makeList(append(val1.list, toString(val2)))}
 }
 
 func opFirst(val1 value) value {
 	if !isWord(val1) && !isList(val1) {
-		panic(fmt.Errorf("first: %s", errWordOrListExpected))
+		panic(fmt.Errorf("first: %s (%s)", errWordOrListExpected, toString(val1)))
 	}
 	if isEmpty(val1) {
-		panic(fmt.Errorf("first: %s", errEmptyWordOrList))
+		panic(fmt.Errorf("first: %s (%s)", errEmptyWordOrList, toString(val1)))
 	}
 	if isWord(val1) {
 		return value{word: val1.word[:2]}
@@ -105,10 +104,10 @@ func opFirst(val1 value) value {
 
 func opLast(val1 value) value {
 	if !isWord(val1) && !isList(val1) {
-		panic(fmt.Errorf("last: %s", errWordOrListExpected))
+		panic(fmt.Errorf("last: %s (%s)", errWordOrListExpected, toString(val1)))
 	}
 	if isEmpty(val1) {
-		panic(fmt.Errorf("last: %s", errEmptyWordOrList))
+		panic(fmt.Errorf("last: %s (%s)", errEmptyWordOrList, toString(val1)))
 	}
 	if isWord(val1) {
 		return value{word: `"` + val1.word[len(val1.word)-1:]}
@@ -122,10 +121,10 @@ func opLast(val1 value) value {
 
 func opButFirst(val1 value) value {
 	if !isWord(val1) && !isList(val1) {
-		panic(fmt.Errorf("butfirst: %s", errWordOrListExpected))
+		panic(fmt.Errorf("butfirst: %s (%s)", errWordOrListExpected, toString(val1)))
 	}
 	if isEmpty(val1) {
-		panic(fmt.Errorf("butfirst: %s", errEmptyWordOrList))
+		panic(fmt.Errorf("butfirst: %s (%s)", errEmptyWordOrList, toString(val1)))
 	}
 	if isWord(val1) {
 		return value{word: `"` + val1.word[2:]}
@@ -135,10 +134,10 @@ func opButFirst(val1 value) value {
 
 func opButLast(val1 value) value {
 	if !isWord(val1) && !isList(val1) {
-		panic(fmt.Errorf("butlast: %s", errWordOrListExpected))
+		panic(fmt.Errorf("butlast: %s (%s)", errWordOrListExpected, toString(val1)))
 	}
 	if isEmpty(val1) {
-		panic(fmt.Errorf("butlast: %s", errEmptyWordOrList))
+		panic(fmt.Errorf("butlast: %s (%s)", errEmptyWordOrList, toString(val1)))
 	}
 	if isWord(val1) {
 		return value{word: val1.word[:len(val1.word)-1]}

+ 3 - 3
math.go

@@ -44,7 +44,7 @@ func opEq(val1, val2 value) value {
 	if isWord(val1) && isWord(val2) {
 		return value{tp: typeBool, b: escapeWord(val1.word) == escapeWord(val2.word)}
 	}
-	panic(fmt.Errorf("eq: %s", errIllegalOperandType))
+	panic(fmt.Errorf("eq: %s (%s == %s)", errIllegalOperandType, toString(val1), toString(val2)))
 }
 
 func opGt(val1, val2 value) value {
@@ -57,7 +57,7 @@ func opGt(val1, val2 value) value {
 	if isWord(val1) && isWord(val2) {
 		return value{tp: typeBool, b: escapeWord(val1.word) > escapeWord(val2.word)}
 	}
-	panic(fmt.Errorf("gt: %s", errIllegalOperandType))
+	panic(fmt.Errorf("gt: %s (%s > %s)", errIllegalOperandType, toString(val1), toString(val2)))
 }
 
 func opLt(val1, val2 value) value {
@@ -70,7 +70,7 @@ func opLt(val1, val2 value) value {
 	if isWord(val1) && isWord(val2) {
 		return value{tp: typeBool, b: escapeWord(val1.word) < escapeWord(val2.word)}
 	}
-	panic(fmt.Errorf("lt: %s", errIllegalOperandType))
+	panic(fmt.Errorf("lt: %s (%s < %s)", errIllegalOperandType, toString(val1), toString(val2)))
 }
 
 func opAnd(val1, val2 value) value {


+ 106 - 105
mua.go

@@ -96,117 +96,118 @@ func interpret(scanner *scanProvider, envs []environ) (val value, returned bool)
 				}
 				paramCnt, ok := reserved[stack[i].word]
 				if ok {
-					if paramCnt > len(stack)-1-i {
-						break
+					if paramCnt == len(stack)-1-i {
+						for j := i + 1; j < len(stack); j++ {
+							stack[j] = toValue(stack[j], envs[0])
+						}
+						switch stack[i].word {
+						case "make":
+							stack[i] = opMake(stack[i+1], stack[i+2], envs)
+						case "thing":
+							stack[i] = opThing(stack[i+1], envs)
+						case "print":
+							stack[i] = opPrint(stack[i+1])
+						case "read":
+							stack[i] = opRead(scanner)
+						case "add":
+							stack[i] = opAdd(stack[i+1], stack[i+2])
+						case "sub":
+							stack[i] = opSub(stack[i+1], stack[i+2])
+						case "mul":
+							stack[i] = opMul(stack[i+1], stack[i+2])
+						case "div":
+							stack[i] = opDiv(stack[i+1], stack[i+2])
+						case "mod":
+							stack[i] = opMod(stack[i+1], stack[i+2])
+						case "erase":
+							stack[i] = opErase(stack[i+1], envs)
+						case "isname":
+							stack[i] = opIsName(stack[i+1], envs)
+						case "run":
+							stack[i], returned = opRun(stack[i+1], envs)
+						case "eq":
+							stack[i] = opEq(stack[i+1], stack[i+2])
+						case "gt":
+							stack[i] = opGt(stack[i+1], stack[i+2])
+						case "lt":
+							stack[i] = opLt(stack[i+1], stack[i+2])
+						case "and":
+							stack[i] = opAnd(stack[i+1], stack[i+2])
+						case "or":
+							stack[i] = opOr(stack[i+1], stack[i+2])
+						case "not":
+							stack[i] = opNot(stack[i+1])
+						case "if":
+							stack[i], returned = opIf(stack[i+1], stack[i+2], stack[i+3], envs)
+						case "isnumber":
+							stack[i] = opIsNumber(stack[i+1])
+						case "isword":
+							stack[i] = opIsWord(stack[i+1])
+						case "islist":
+							stack[i] = opIsList(stack[i+1])
+						case "isbool":
+							stack[i] = opIsBool(stack[i+1])
+						case "isempty":
+							stack[i] = opIsEmpty(stack[i+1])
+						case "return":
+							stack[i], returned = stack[i+1], true
+						case "export":
+							stack[i] = opExport(stack[i+1], envs)
+						case "readlist":
+							stack[i] = opReadList(scanner)
+						case "word":
+							stack[i] = opWord(stack[i+1], stack[i+2])
+						case "sentence":
+							stack[i] = opSentence(stack[i+1], stack[i+2])
+						case "list":
+							stack[i] = opList(stack[i+1], stack[i+2])
+						case "join":
+							stack[i] = opJoin(stack[i+1], stack[i+2])
+						case "first":
+							stack[i] = opFirst(stack[i+1])
+						case "last":
+							stack[i] = opLast(stack[i+1])
+						case "butfirst":
+							stack[i] = opButFirst(stack[i+1])
+						case "butlast":
+							stack[i] = opButLast(stack[i+1])
+						case "random":
+							stack[i] = opRandom(stack[i+1])
+						case "int":
+							stack[i] = opInt(stack[i+1])
+						case "sqrt":
+							stack[i] = opSqrt(stack[i+1])
+						case "save":
+							stack[i] = opSave(stack[i+1], envs[0])
+						case "load":
+							stack[i] = opLoad(stack[i+1], envs[0])
+						case "erall":
+							stack[i] = opErAll(envs[0])
+						case "poall":
+							stack[i] = opPoAll(envs[0])
+						}
+						stack = stack[:i+1]
+						updated = true
 					}
-					for j := i + 1; j < len(stack); j++ {
-						stack[j] = toValue(stack[j], envs[0])
-					}
-					switch stack[i].word {
-					case "make":
-						stack[i] = opMake(stack[i+1], stack[i+2], envs)
-					case "thing":
-						stack[i] = opThing(stack[i+1], envs)
-					case "print":
-						stack[i] = opPrint(stack[i+1])
-					case "read":
-						stack[i] = opRead(scanner)
-					case "add":
-						stack[i] = opAdd(stack[i+1], stack[i+2])
-					case "sub":
-						stack[i] = opSub(stack[i+1], stack[i+2])
-					case "mul":
-						stack[i] = opMul(stack[i+1], stack[i+2])
-					case "div":
-						stack[i] = opDiv(stack[i+1], stack[i+2])
-					case "mod":
-						stack[i] = opMod(stack[i+1], stack[i+2])
-					case "erase":
-						stack[i] = opErase(stack[i+1], envs)
-					case "isname":
-						stack[i] = opIsName(stack[i+1])
-					case "run":
-						stack[i], returned = opRun(stack[i+1], envs)
-					case "eq":
-						stack[i] = opEq(stack[i+1], stack[i+2])
-					case "gt":
-						stack[i] = opGt(stack[i+1], stack[i+2])
-					case "lt":
-						stack[i] = opLt(stack[i+1], stack[i+2])
-					case "and":
-						stack[i] = opAnd(stack[i+1], stack[i+2])
-					case "or":
-						stack[i] = opOr(stack[i+1], stack[i+2])
-					case "not":
-						stack[i] = opNot(stack[i+1])
-					case "if":
-						stack[i], returned = opIf(stack[i+1], stack[i+2], stack[i+3], envs)
-					case "isnumber":
-						stack[i] = opIsNumber(stack[i+1])
-					case "isword":
-						stack[i] = opIsWord(stack[i+1])
-					case "islist":
-						stack[i] = opIsList(stack[i+1])
-					case "isbool":
-						stack[i] = opIsBool(stack[i+1])
-					case "isempty":
-						stack[i] = opIsEmpty(stack[i+1])
-					case "return":
-						stack[i], returned = stack[i+1], true
-					case "export":
-						stack[i] = opExport(stack[i+1], envs)
-					case "readlist":
-						stack[i] = opReadList(scanner)
-					case "word":
-						stack[i] = opWord(stack[i+1], stack[i+2])
-					case "sentence":
-						stack[i] = opSentence(stack[i+1], stack[i+2])
-					case "list":
-						stack[i] = opList(stack[i+1], stack[i+2])
-					case "join":
-						stack[i] = opJoin(stack[i+1], stack[i+2])
-					case "first":
-						stack[i] = opFirst(stack[i+1])
-					case "last":
-						stack[i] = opLast(stack[i+1])
-					case "butfirst":
-						stack[i] = opButFirst(stack[i+1])
-					case "butlast":
-						stack[i] = opButLast(stack[i+1])
-					case "random":
-						stack[i] = opRandom(stack[i+1])
-					case "int":
-						stack[i] = opInt(stack[i+1])
-					case "sqrt":
-						stack[i] = opSqrt(stack[i+1])
-					case "save":
-						stack[i] = opSave(stack[i+1], envs[0])
-					case "load":
-						stack[i] = opLoad(stack[i+1], envs[0])
-					case "erall":
-						stack[i] = opErAll(envs[0])
-					case "poall":
-						stack[i] = opPoAll(envs[0])
-					}
-					stack = stack[:i+1]
-					updated = true
+					break
 				}
 				val, _ := getValue(`"`+stack[i].word, envs)
 				if val.param != nil {
-					if len(val.param) > len(stack)-1-i {
-						break
+					if len(val.param) == len(stack)-1-i {
+						for j := i + 1; j < len(stack); j++ {
+							stack[j] = toValue(stack[j], envs[0])
+						}
+						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]})
+						stack = stack[:i+1]
+						updated = true
 					}
-					for j := i + 1; j < len(stack); j++ {
-						stack[j] = toValue(stack[j], envs[0])
-					}
-					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]})
-					stack = stack[:i+1]
-					updated = true
+					break
 				}
+				panic(fmt.Errorf("func: %s (%s)", errFunctionExpected, stack[i].word))
 			}
 			if !updated {
 				break

+ 21 - 11
type.go

@@ -45,7 +45,7 @@ func toNumber(val value) float64 {
 	}
 	num, err := strconv.ParseFloat(val.word, 64)
 	if err != nil {
-		panic(fmt.Errorf("number: %s", errInvalidNumber))
+		panic(fmt.Errorf("number: %s (%s)", errInvalidNumber, toString(val)))
 	}
 	return num
 }
@@ -57,7 +57,7 @@ func toInt(val value, envs []environ) int {
 			val = newVal
 			if val.tp == typeNumber {
 				if val.num != math.Floor(val.num) {
-					panic(fmt.Errorf("int: %s", errInvalidInteger))
+					panic(fmt.Errorf("int: %s (%f)", errInvalidInteger, val.num))
 				}
 				return int(val.num)
 			}
@@ -68,7 +68,7 @@ func toInt(val value, envs []environ) int {
 	}
 	num, err := strconv.ParseInt(val.word, 10, 64)
 	if err != nil {
-		panic(fmt.Errorf("int: %s", errInvalidInteger))
+		panic(fmt.Errorf("int: %s (%s)", errInvalidInteger, toString(val)))
 	}
 	return int(num)
 }
@@ -97,7 +97,7 @@ func toBool(val value) bool {
 		val.word = val.word[1:]
 	}
 	if val.word != "true" && val.word != "false" {
-		panic(fmt.Errorf("bool: %s", errInvalidBool))
+		panic(fmt.Errorf("bool: %s (%s)", errInvalidBool, toString(val)))
 	}
 	return val.word == "true"
 }
@@ -141,7 +141,7 @@ func isName(val value) bool {
 
 func toName(val value) string {
 	if !isName(val) {
-		panic(fmt.Errorf("name: %s", errInvalidName))
+		panic(fmt.Errorf("name: %s (%s)", errInvalidName, toString(val)))
 	}
 	return val.word[1:]
 }
@@ -152,7 +152,7 @@ func isNameWithIndex(val value) bool {
 
 func toNameWithIndex(val value) (string, []string) {
 	if !isNameWithIndex(val) {
-		panic(fmt.Errorf("name: %s", errInvalidName))
+		panic(fmt.Errorf("name: %s (%s)", errInvalidName, toString(val)))
 	}
 	index := strings.Split(val.word, "[")
 	name, cnt := index[0][1:], len(index)-1
@@ -195,7 +195,7 @@ func isEmpty(val value) bool {
 	if val.tp == typeList {
 		return len(val.list) == 0
 	}
-	panic(fmt.Errorf("empty: %s", errWordOrListExpected))
+	panic(fmt.Errorf("empty: %s (%s)", errWordOrListExpected, toString(val)))
 }
 
 func toValue(val value, env environ) value {
@@ -214,7 +214,7 @@ func toValue(val value, env environ) value {
 	if isList(val) {
 		return parseFunc(val.word, env)
 	}
-	panic(fmt.Errorf("value: %s", errValueExpected))
+	panic(fmt.Errorf("value: %s (%s)", errValueExpected, val.word))
 }
 
 func toString(val value) string {
@@ -230,7 +230,7 @@ func toString(val value) string {
 	if val.tp == typeList {
 		return makeList(val.list)
 	}
-	panic(fmt.Errorf("string: %s", errValueExpected))
+	panic(fmt.Errorf("string: %s (%s)", errValueExpected, val.word))
 }
 
 func opIsNumber(val1 value) value {
@@ -245,8 +245,18 @@ func opIsWord(val1 value) value {
 	return value{tp: typeBool, b: isWord(val1)}
 }
 
-func opIsName(val1 value) value {
-	return value{tp: typeBool, b: isName(val1)}
+func opIsName(val1 value, envs []environ) value {
+	if !isName(val1) {
+		return value{tp: typeBool, b: false}
+	}
+	name := toName(val1)
+	for _, env := range envs {
+		_, ok := env[name]
+		if ok {
+			return value{tp: typeBool, b: true}
+		}
+	}
+	return value{tp: typeBool, b: false}
 }
 
 func opIsList(val1 value) value {