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
/
pair.go
130 lines (118 loc) · 2.47 KB
/
pair.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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
//-----------------------------------------------------------------------------
// 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 "bytes"
// Pair is a type with two values. In other lisps it is often called "cons",
// "cons-cell", or "cell".
type Pair struct {
first, second Value
}
// NewPair creates a new pair from two values.
func NewPair(first, second Value) *Pair {
return &Pair{first, second}
}
// NewPairFromSlice creates a new pair list from the given Value slice.
func NewPairFromSlice(values []Value) *Pair {
if len(values) == 0 {
return Nil()
}
var p *Pair
for i := len(values); i > 0; {
i--
p = NewPair(values[i], p)
}
return p
}
// GetFirst returns the first value of a pair
func (p *Pair) GetFirst() Value {
if p != nil {
return p.first
}
return nil
}
// GetSecond returns the second value of a pair
func (p *Pair) GetSecond() Value {
if p != nil {
return p.second
}
return nil
}
// GetSlice returns the pair list elements as a slice of Values.
func (p *Pair) GetSlice() []Value {
if p == nil {
return nil
}
var result []Value
cp := p
for {
result = append(result, cp.first)
second := cp.second
np, ok := second.(*Pair)
if !ok {
result = append(result, second)
return result
}
if np == nil {
return result
}
cp = np
}
}
// Nil() returns the empty pair.
func Nil() *Pair { return nilPair }
var nilPair *Pair
func (p *Pair) Equal(other Value) bool {
if p == nil || other == nil {
return p == other
}
if o, ok := other.(*Pair); ok {
return p.first.Equal(o.first) && p.second.Equal(o.second)
}
return false
}
func (p *Pair) String() string {
if p == nil {
return "()"
}
var buf bytes.Buffer
buf.WriteByte('(')
for cp := p; ; {
if cp != p {
buf.WriteByte(' ')
}
if first := cp.first; first != nil {
if s := first.String(); s != "" {
buf.WriteString(s)
} else {
buf.WriteString("()")
}
} else {
buf.WriteString("()")
}
sval := cp.second
if sval == nil {
break
}
if np, ok := sval.(*Pair); ok {
if np == nil {
break
}
cp = np
continue
}
if s := sval.String(); s != "" {
buf.WriteString(" . ")
buf.WriteString(s)
}
break
}
buf.WriteByte(')')
return buf.String()
}