1
1
mirror of https://github.com/kanaka/mal.git synced 2024-09-21 02:27:10 +03:00

Go: Fix panic on call to function with wrong number of arguments

This commit is contained in:
Jordi Íñigo 2018-07-06 13:01:57 +02:00
parent 810ec74a67
commit 07bd1c1ff1
12 changed files with 436 additions and 0 deletions

View File

@ -446,28 +446,52 @@ func swap_BANG(a []MalType) (MalType, error) {
// core namespace
var NS = map[string]MalType{
"=": func(a []MalType) (MalType, error) {
if e := assertArgNum(a, 2); e != nil {
return nil, e
}
return Equal_Q(a[0], a[1]), nil
},
"throw": throw,
"nil?": func(a []MalType) (MalType, error) {
if e := assertArgNum(a, 1); e != nil {
return nil, e
}
return Nil_Q(a[0]), nil
},
"true?": func(a []MalType) (MalType, error) {
if e := assertArgNum(a, 1); e != nil {
return nil, e
}
return True_Q(a[0]), nil
},
"false?": func(a []MalType) (MalType, error) {
if e := assertArgNum(a, 1); e != nil {
return nil, e
}
return False_Q(a[0]), nil
},
"symbol": func(a []MalType) (MalType, error) {
if e := assertArgNum(a, 1); e != nil {
return nil, e
}
return Symbol{a[0].(string)}, nil
},
"symbol?": func(a []MalType) (MalType, error) {
if e := assertArgNum(a, 1); e != nil {
return nil, e
}
return Symbol_Q(a[0]), nil
},
"string?": func(a []MalType) (MalType, error) {
if e := assertArgNum(a, 1); e != nil {
return nil, e
}
return (String_Q(a[0]) && !Keyword_Q(a[0])), nil
},
"keyword": func(a []MalType) (MalType, error) {
if e := assertArgNum(a, 1); e != nil {
return nil, e
}
if Keyword_Q(a[0]) {
return a[0], nil
} else {
@ -475,13 +499,22 @@ var NS = map[string]MalType{
}
},
"keyword?": func(a []MalType) (MalType, error) {
if e := assertArgNum(a, 1); e != nil {
return nil, e
}
return Keyword_Q(a[0]), nil
},
"number?": func(a []MalType) (MalType, error) {
if e := assertArgNum(a, 1); e != nil {
return nil, e
}
return Number_Q(a[0]), nil
},
"fn?": fn_q,
"macro?": func(a []MalType) (MalType, error) {
if e := assertArgNum(a, 1); e != nil {
return nil, e
}
return MalFunc_Q(a[0]) && a[0].(MalFunc).GetMacro(), nil
},
@ -490,35 +523,65 @@ var NS = map[string]MalType{
"prn": func(a []MalType) (MalType, error) { return prn(a) },
"println": func(a []MalType) (MalType, error) { return println(a) },
"read-string": func(a []MalType) (MalType, error) {
if e := assertArgNum(a, 1); e != nil {
return nil, e
}
return reader.Read_str(a[0].(string))
},
"slurp": slurp,
"readline": func(a []MalType) (MalType, error) {
if e := assertArgNum(a, 1); e != nil {
return nil, e
}
return readline.Readline(a[0].(string))
},
"<": func(a []MalType) (MalType, error) {
if e := assertArgNum(a, 2); e != nil {
return nil, e
}
return a[0].(int) < a[1].(int), nil
},
"<=": func(a []MalType) (MalType, error) {
if e := assertArgNum(a, 2); e != nil {
return nil, e
}
return a[0].(int) <= a[1].(int), nil
},
">": func(a []MalType) (MalType, error) {
if e := assertArgNum(a, 2); e != nil {
return nil, e
}
return a[0].(int) > a[1].(int), nil
},
">=": func(a []MalType) (MalType, error) {
if e := assertArgNum(a, 2); e != nil {
return nil, e
}
return a[0].(int) >= a[1].(int), nil
},
"+": func(a []MalType) (MalType, error) {
if e := assertArgNum(a, 2); e != nil {
return nil, e
}
return a[0].(int) + a[1].(int), nil
},
"-": func(a []MalType) (MalType, error) {
if e := assertArgNum(a, 2); e != nil {
return nil, e
}
return a[0].(int) - a[1].(int), nil
},
"*": func(a []MalType) (MalType, error) {
if e := assertArgNum(a, 2); e != nil {
return nil, e
}
return a[0].(int) * a[1].(int), nil
},
"/": func(a []MalType) (MalType, error) {
if e := assertArgNum(a, 2); e != nil {
return nil, e
}
return a[0].(int) / a[1].(int), nil
},
"time-ms": time_ms,
@ -527,30 +590,45 @@ var NS = map[string]MalType{
return List{a, nil}, nil
},
"list?": func(a []MalType) (MalType, error) {
if e := assertArgNum(a, 1); e != nil {
return nil, e
}
return List_Q(a[0]), nil
},
"vector": func(a []MalType) (MalType, error) {
return Vector{a, nil}, nil
},
"vector?": func(a []MalType) (MalType, error) {
if e := assertArgNum(a, 1); e != nil {
return nil, e
}
return Vector_Q(a[0]), nil
},
"hash-map": func(a []MalType) (MalType, error) {
return NewHashMap(List{a, nil})
},
"map?": func(a []MalType) (MalType, error) {
if e := assertArgNum(a, 1); e != nil {
return nil, e
}
return HashMap_Q(a[0]), nil
},
"assoc": assoc,
"dissoc": dissoc,
"get": get,
"contains?": func(a []MalType) (MalType, error) {
if e := assertArgNum(a, 2); e != nil {
return nil, e
}
return contains_Q(a[0], a[1])
},
"keys": keys,
"vals": vals,
"sequential?": func(a []MalType) (MalType, error) {
if e := assertArgNum(a, 1); e != nil {
return nil, e
}
return Sequential_Q(a[0]), nil
},
"cons": cons,
@ -568,12 +646,25 @@ var NS = map[string]MalType{
"with-meta": with_meta,
"meta": meta,
"atom": func(a []MalType) (MalType, error) {
if e := assertArgNum(a, 1); e != nil {
return nil, e
}
return &Atom{a[0], nil}, nil
},
"atom?": func(a []MalType) (MalType, error) {
if e := assertArgNum(a, 1); e != nil {
return nil, e
}
return Atom_Q(a[0]), nil
},
"deref": deref,
"reset!": reset_BANG,
"swap!": swap_BANG,
}
func assertArgNum(a []MalType, n int) error {
if len(a) != n {
return errors.New("wrong number of arguments")
}
return nil
}

View File

@ -102,19 +102,38 @@ func PRINT(exp MalType) (string, error) {
var repl_env = map[string]MalType{
"+": func(a []MalType) (MalType, error) {
if e := assertArgNum(a, 2); e != nil {
return nil, e
}
return a[0].(int) + a[1].(int), nil
},
"-": func(a []MalType) (MalType, error) {
if e := assertArgNum(a, 2); e != nil {
return nil, e
}
return a[0].(int) - a[1].(int), nil
},
"*": func(a []MalType) (MalType, error) {
if e := assertArgNum(a, 2); e != nil {
return nil, e
}
return a[0].(int) * a[1].(int), nil
},
"/": func(a []MalType) (MalType, error) {
if e := assertArgNum(a, 2); e != nil {
return nil, e
}
return a[0].(int) / a[1].(int), nil
},
}
func assertArgNum(a []MalType, n int) error {
if len(a) != n {
return errors.New("wrong number of arguments")
}
return nil
}
// repl
func rep(str string) (MalType, error) {
var exp MalType

View File

@ -164,15 +164,27 @@ func rep(str string) (MalType, error) {
func main() {
repl_env.Set(Symbol{"+"}, func(a []MalType) (MalType, error) {
if e := assertArgNum(a, 2); e != nil {
return nil, e
}
return a[0].(int) + a[1].(int), nil
})
repl_env.Set(Symbol{"-"}, func(a []MalType) (MalType, error) {
if e := assertArgNum(a, 2); e != nil {
return nil, e
}
return a[0].(int) - a[1].(int), nil
})
repl_env.Set(Symbol{"*"}, func(a []MalType) (MalType, error) {
if e := assertArgNum(a, 2); e != nil {
return nil, e
}
return a[0].(int) * a[1].(int), nil
})
repl_env.Set(Symbol{"/"}, func(a []MalType) (MalType, error) {
if e := assertArgNum(a, 2); e != nil {
return nil, e
}
return a[0].(int) / a[1].(int), nil
})
@ -195,3 +207,10 @@ func main() {
fmt.Printf("%v\n", out)
}
}
func assertArgNum(a []MalType, n int) error {
if len(a) != n {
return errors.New("wrong number of arguments")
}
return nil
}

34
go/tests/step2_eval.mal Normal file
View File

@ -0,0 +1,34 @@
;; Testing evaluation of excessive arguments
(+ 1 2 3)
;=>Error: wrong number of arguments
;; Valid call
(+ 1 2)
;=>3
;; Testing evaluation of missing arguments
(+ 1)
;=>Error: wrong number of arguments
;; Testing evaluation of missing arguments
(+)
;=>Error: wrong number of arguments
;; Testing evaluation of excessive arguments
(- 1 2 3)
;=>Error: wrong number of arguments
;; Valid call
(- 1 2)
;=>-1
;; Testing evaluation of missing arguments
(- 1)
;=>Error: wrong number of arguments
;; Testing evaluation of missing arguments
(-)
;=>Error: wrong number of arguments

34
go/tests/step3_env.mal Normal file
View File

@ -0,0 +1,34 @@
;; Testing evaluation of excessive arguments
(+ 1 2 3)
;=>Error: wrong number of arguments
;; Valid call
(+ 1 2)
;=>3
;; Testing evaluation of missing arguments
(+ 1)
;=>Error: wrong number of arguments
;; Testing evaluation of missing arguments
(+)
;=>Error: wrong number of arguments
;; Testing evaluation of excessive arguments
(- 1 2 3)
;=>Error: wrong number of arguments
;; Valid call
(- 1 2)
;=>-1
;; Testing evaluation of missing arguments
(- 1)
;=>Error: wrong number of arguments
;; Testing evaluation of missing arguments
(-)
;=>Error: wrong number of arguments

View File

@ -0,0 +1,34 @@
;; Testing evaluation of excessive arguments
(+ 1 2 3)
;=>Error: wrong number of arguments
;; Valid call
(+ 1 2)
;=>3
;; Testing evaluation of missing arguments
(+ 1)
;=>Error: wrong number of arguments
;; Testing evaluation of missing arguments
(+)
;=>Error: wrong number of arguments
;; Testing evaluation of excessive arguments
(= 1 2 3)
;=>Error: wrong number of arguments
;; Valid call
(= 1 2)
;=>false
;; Testing evaluation of missing arguments
(= 1)
;=>Error: wrong number of arguments
;; Testing evaluation of missing arguments
(=)
;=>Error: wrong number of arguments

View File

@ -1,2 +1,37 @@
;; Go: skipping non-TCO recursion
;; Reason: completes even at 100,000
;; Testing evaluation of excessive arguments
(+ 1 2 3)
;=>Error: wrong number of arguments
;; Valid call
(+ 1 2)
;=>3
;; Testing evaluation of missing arguments
(+ 1)
;=>Error: wrong number of arguments
;; Testing evaluation of missing arguments
(+)
;=>Error: wrong number of arguments
;; Testing evaluation of excessive arguments
(= 1 2 3)
;=>Error: wrong number of arguments
;; Valid call
(= 1 2)
;=>false
;; Testing evaluation of missing arguments
(= 1)
;=>Error: wrong number of arguments
;; Testing evaluation of missing arguments
(=)
;=>Error: wrong number of arguments

34
go/tests/step6_file.mal Normal file
View File

@ -0,0 +1,34 @@
;; Testing evaluation of excessive arguments
(+ 1 2 3)
;=>Error: wrong number of arguments
;; Valid call
(+ 1 2)
;=>3
;; Testing evaluation of missing arguments
(+ 1)
;=>Error: wrong number of arguments
;; Testing evaluation of missing arguments
(+)
;=>Error: wrong number of arguments
;; Testing evaluation of excessive arguments
(= 1 2 3)
;=>Error: wrong number of arguments
;; Valid call
(= 1 2)
;=>false
;; Testing evaluation of missing arguments
(= 1)
;=>Error: wrong number of arguments
;; Testing evaluation of missing arguments
(=)
;=>Error: wrong number of arguments

34
go/tests/step7_quote.mal Normal file
View File

@ -0,0 +1,34 @@
;; Testing evaluation of excessive arguments
(+ 1 2 3)
;=>Error: wrong number of arguments
;; Valid call
(+ 1 2)
;=>3
;; Testing evaluation of missing arguments
(+ 1)
;=>Error: wrong number of arguments
;; Testing evaluation of missing arguments
(+)
;=>Error: wrong number of arguments
;; Testing evaluation of excessive arguments
(= 1 2 3)
;=>Error: wrong number of arguments
;; Valid call
(= 1 2)
;=>false
;; Testing evaluation of missing arguments
(= 1)
;=>Error: wrong number of arguments
;; Testing evaluation of missing arguments
(=)
;=>Error: wrong number of arguments

34
go/tests/step8_macros.mal Normal file
View File

@ -0,0 +1,34 @@
;; Testing evaluation of excessive arguments
(+ 1 2 3)
;=>Error: wrong number of arguments
;; Valid call
(+ 1 2)
;=>3
;; Testing evaluation of missing arguments
(+ 1)
;=>Error: wrong number of arguments
;; Testing evaluation of missing arguments
(+)
;=>Error: wrong number of arguments
;; Testing evaluation of excessive arguments
(= 1 2 3)
;=>Error: wrong number of arguments
;; Valid call
(= 1 2)
;=>false
;; Testing evaluation of missing arguments
(= 1)
;=>Error: wrong number of arguments
;; Testing evaluation of missing arguments
(=)
;=>Error: wrong number of arguments

34
go/tests/step9_try.mal Normal file
View File

@ -0,0 +1,34 @@
;; Testing evaluation of excessive arguments
(+ 1 2 3)
;=>Error: wrong number of arguments
;; Valid call
(+ 1 2)
;=>3
;; Testing evaluation of missing arguments
(+ 1)
;=>Error: wrong number of arguments
;; Testing evaluation of missing arguments
(+)
;=>Error: wrong number of arguments
;; Testing evaluation of excessive arguments
(= 1 2 3)
;=>Error: wrong number of arguments
;; Valid call
(= 1 2)
;=>false
;; Testing evaluation of missing arguments
(= 1)
;=>Error: wrong number of arguments
;; Testing evaluation of missing arguments
(=)
;=>Error: wrong number of arguments

34
go/tests/stepA_mal.mal Normal file
View File

@ -0,0 +1,34 @@
;; Testing evaluation of excessive arguments
(+ 1 2 3)
;=>Error: wrong number of arguments
;; Valid call
(+ 1 2)
;=>3
;; Testing evaluation of missing arguments
(+ 1)
;=>Error: wrong number of arguments
;; Testing evaluation of missing arguments
(+)
;=>Error: wrong number of arguments
;; Testing evaluation of excessive arguments
(= 1 2 3)
;=>Error: wrong number of arguments
;; Valid call
(= 1 2)
;=>false
;; Testing evaluation of missing arguments
(= 1)
;=>Error: wrong number of arguments
;; Testing evaluation of missing arguments
(=)
;=>Error: wrong number of arguments