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
/
Copy pathsexpr.go
90 lines (78 loc) · 2.72 KB
/
sexpr.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
//-----------------------------------------------------------------------------
// 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 allows to work with symbolic expressions, s-expressions.
package sxpf
import "fmt"
// Value is a generic value, the set of all possible values of a s-expression.
type Value interface {
Equal(Value) bool
String() string
}
// Atom is a Value that cannot be further decomposed.
type Atom interface {
Value
Value() string
}
// Sequence is a generic value that is a sequence of values.
type Sequence interface {
Value
GetSlice() []Value
}
// NewSequence stores the slice of Values in a pair list or in a vector,
// depending on its length.
func NewSequence(values ...Value) Sequence {
// A pair list has an overhead of four words per list element (both first
// and second value is a reference to an interface, two words each).
// A vector has a constant overhead of 4 words (the Vector struct) +
// 3 words (for the slice) and a linear overhead of two words per
// list element (for the interface reference to the value).
// Let x be the number of list elements. Then we need a x where
// 4*x > 2*x + 7 <=> x+x+x+x > x+x+7 <=> x+x > 7 <=> x > 3.
if len(values) > 3 {
return NewVector(values...)
}
return NewPairFromSlice(values)
}
// GetSymbol returns the idx value of args as a Symbol.
func GetSymbol(args []Value, idx int) (*Symbol, error) {
if idx < 0 || len(args) <= idx {
return nil, makeErrIndexOutOfBounds(args, idx)
}
if val, ok := args[idx].(*Symbol); ok {
return val, nil
}
return nil, fmt.Errorf("%v / %d is not a symbol", args[idx], idx)
}
// GetString returns the idx value of args as a String.
func GetString(args []Value, idx int) (string, error) {
if idx < 0 || len(args) <= idx {
return "", makeErrIndexOutOfBounds(args, idx)
}
if val, ok := args[idx].(*String); ok {
return val.GetValue(), nil
}
if val, ok := args[idx].(*Symbol); ok {
return val.GetValue(), nil
}
return "", fmt.Errorf("%v / %d is not a string", args[idx], idx)
}
// GetSequence returns the idx value of args as a sequence.
func GetSequence(args []Value, idx int) (Sequence, error) {
if idx < 0 || len(args) <= idx {
return nil, makeErrIndexOutOfBounds(args, idx)
}
if val, ok := args[idx].(Sequence); ok {
return val, nil
}
return nil, fmt.Errorf("%v / %d is not a sequence", args[idx], idx)
}
func makeErrIndexOutOfBounds(args []Value, idx int) error {
return fmt.Errorf("index %d out of bounds: %v", idx, args)
}