This repository has been archived by the owner on Jul 4, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
form.go
75 lines (63 loc) · 2 KB
/
form.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
//-----------------------------------------------------------------------------
// Copyright (c) 2022 Detlef Stern
//
// This file is part of sxpf.
//
// sxpf is licensed under the latest version of the EUPL // (European Union
// Public License). Please see file LICENSE.txt for your rights and obligations
// under this license.
//-----------------------------------------------------------------------------
package sxpf
import "fmt"
// Form is a value that can be called. Depending on IsSpecial, the arguments
// are evaluated or not before calling the form.
type Form interface {
Value
Call(Environment, []Value) (Value, error)
IsSpecial() bool
}
// Builtin is a wrapper for a builtin function.
type Builtin struct {
name string
fn BuiltinFn
minArity int
maxArity int // if maxArity < minArity ==> maxArity is unlimited
special bool
}
// BuiltinFn is a builtin form that is implemented in Go.
type BuiltinFn func(Environment, []Value) (Value, error)
// NewBuiltin returns a new builtin form.
func NewBuiltin(name string, special bool, minArity, maxArity int, f BuiltinFn) *Builtin {
return &Builtin{name, f, minArity, maxArity, special}
}
func (b *Builtin) Equal(other Value) bool {
if b == nil || other == nil {
return b == other
}
if o, ok := other.(*Builtin); ok {
return b.name == o.name
}
return false
}
func (b *Builtin) String() string { return "#" + b.name }
func (b *Builtin) IsSpecial() bool { return b != nil && b.special }
func (b *Builtin) Name() string {
if b == nil {
return ""
}
return b.name
}
func (b *Builtin) Call(env Environment, args []Value) (Value, error) {
if length := len(args); length < b.minArity {
return nil, fmt.Errorf("not enough arguments (%d) for form %v (%d)", length, b.name, b.minArity)
} else if b.minArity <= b.maxArity && b.maxArity < length {
return nil, fmt.Errorf("too many arguments (%d) for form %v (%d)", length, b.name, b.maxArity)
}
return b.fn(env, args)
}
func (b *Builtin) GetValue() BuiltinFn {
if b == nil {
return nil
}
return b.fn
}