Merge branch 'predicate-types'
This commit is contained in:
commit
010451cfab
21
gui.go
21
gui.go
|
@ -1130,7 +1130,26 @@ func String(v expression, rawString bool) string {
|
|||
case proc:
|
||||
var b strings.Builder
|
||||
b.WriteString("(lambda ")
|
||||
b.WriteString(String(v.params, true))
|
||||
params, ok := v.params.([]expression)
|
||||
if len(v.predicates) > 0 {
|
||||
if ok {
|
||||
newParams := make([]expression, len(params))
|
||||
copy(newParams, params)
|
||||
for i := range newParams {
|
||||
if pred, ok := v.predicates[newParams[i].(symbol)]; ok {
|
||||
newParams[i] = symbol(fmt.Sprintf("%s@%s", newParams[i].(symbol), pred))
|
||||
}
|
||||
}
|
||||
b.WriteString(String(newParams, true))
|
||||
} else {
|
||||
val := String(v.params, false)
|
||||
b.WriteString(val)
|
||||
b.WriteString("@")
|
||||
b.WriteString(string(v.predicates[symbol(val)]))
|
||||
}
|
||||
} else {
|
||||
b.WriteString(String(v.params, true))
|
||||
}
|
||||
b.WriteRune(' ')
|
||||
body := String(v.body, true)
|
||||
if strings.HasPrefix(body, "(begin ") {
|
||||
|
|
|
@ -17,6 +17,7 @@ type proc struct {
|
|||
params expression
|
||||
body expression
|
||||
en *env
|
||||
predicates map[symbol]symbol
|
||||
}
|
||||
|
||||
type macro struct {
|
||||
|
@ -288,7 +289,31 @@ func eval(exp expression, en *env) (value expression) {
|
|||
}
|
||||
b := []expression{symbol("begin")}
|
||||
b = append(b, e[2:]...)
|
||||
value = proc{e[1], stringUnescapeEval(b), en}
|
||||
predicates := make(map[symbol]symbol)
|
||||
switch a := e[1].(type) {
|
||||
case []expression:
|
||||
for i, v := range a {
|
||||
s := String(v, false)
|
||||
ind := strings.LastIndex(s, "@")
|
||||
if ind < 1 {
|
||||
continue
|
||||
}
|
||||
a[i] = symbol(s[:ind])
|
||||
predicates[a[i].(symbol)] = symbol(s[ind+1:])
|
||||
}
|
||||
e[1] = a
|
||||
default:
|
||||
s := String(e[1], false)
|
||||
ind := strings.LastIndex(s, "@")
|
||||
if ind < 1 {
|
||||
e[1] = []expression{e[1]}
|
||||
break
|
||||
}
|
||||
e[1] = symbol(s[:ind])
|
||||
predicates[e[1].(symbol)] = symbol(s[ind+1:])
|
||||
e[1] = []expression{e[1]}
|
||||
}
|
||||
value = proc{e[1], stringUnescapeEval(b), en, predicates}
|
||||
case "macro":
|
||||
if len(e) < 3 {
|
||||
value = exception("'macro' expects at least three arguments")
|
||||
|
@ -724,9 +749,19 @@ func apply(procedure expression, args []expression, name expression) (value expr
|
|||
}
|
||||
break
|
||||
}
|
||||
if v, ok := p.predicates[param.(symbol)]; ok {
|
||||
if !AnythingToBool(eval([]expression{v, args[i]}, p.en)).(bool) {
|
||||
return exception(fmt.Sprintf("Type Error: Lambda %q expected argument %d to pass predicate %q, it did not", String(name, false), i+1, v))
|
||||
}
|
||||
}
|
||||
en.vars[param.(symbol)] = args[i]
|
||||
}
|
||||
default:
|
||||
if v, ok := p.predicates[params.(symbol)]; ok {
|
||||
if !AnythingToBool(eval([]expression{v, args[0]}, p.en)).(bool) {
|
||||
return exception(fmt.Sprintf("Type Error: Lambda %q expected argument %d to pass predicate %q, it did not", String(name, false), 1, v))
|
||||
}
|
||||
}
|
||||
en.vars[params.(symbol)] = args
|
||||
}
|
||||
value = eval(p.body, en)
|
||||
|
|
21
nogui.go
21
nogui.go
|
@ -35,7 +35,26 @@ func String(v expression, rawString bool) string {
|
|||
case proc:
|
||||
var b strings.Builder
|
||||
b.WriteString("(lambda ")
|
||||
b.WriteString(String(v.params, true))
|
||||
params, ok := v.params.([]expression)
|
||||
if len(v.predicates) > 0 {
|
||||
if ok {
|
||||
newParams := make([]expression, len(params))
|
||||
copy(newParams, params)
|
||||
for i := range newParams {
|
||||
if pred, ok := v.predicates[newParams[i].(symbol)]; ok {
|
||||
newParams[i] = symbol(fmt.Sprintf("%s@%s", newParams[i].(symbol), pred))
|
||||
}
|
||||
}
|
||||
b.WriteString(String(newParams, true))
|
||||
} else {
|
||||
val := String(v.params, false)
|
||||
b.WriteString(val)
|
||||
b.WriteString("@")
|
||||
b.WriteString(string(v.predicates[symbol(val)]))
|
||||
}
|
||||
} else {
|
||||
b.WriteString(String(v.params, true))
|
||||
}
|
||||
b.WriteRune(' ')
|
||||
body := String(v.body, true)
|
||||
if strings.HasPrefix(body, "(begin ") {
|
||||
|
|
Loading…
Reference in New Issue