-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathListOperations.cpp
More file actions
103 lines (79 loc) · 2.56 KB
/
ListOperations.cpp
File metadata and controls
103 lines (79 loc) · 2.56 KB
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
#include "ListOperations.h"
#include "Evaluator.h"
#include "SValue.h"
#include <algorithm>
// v is an expression containing { 1 2 3 }
SValue* head( SValue* v )
{
Cells& args = v->cellsRequired();
REQUIRE( v, args.size() == 1, "head requires 1 argument" );
SValue* qexpr = args.front();
REQUIRE( v, qexpr->isQExpression(), "head expects a QExpression" );
REQUIRE( v, !qexpr->isEmpty(), "head expects a non-empty QExpression" );
Cells& qexprCells = qexpr->cellsRequired();
// Take the front only for the Q-expression children.
qexprCells.drop( qexprCells.begin() + 1, qexprCells.end() );
// V becomes Q-expression.
std::swap( *v, *qexpr );
return v;
}
// v is an expression containing { 1 2 3 }
SValue* tail( SValue* v )
{
Cells& args = v->cellsRequired();
REQUIRE( v, args.size() == 1, "tail requires 1 argument" );
SValue* qexpr = args.front();
REQUIRE( v, qexpr->isQExpression(), "tail expects a QExpression" );
Cells& qexprCells = qexpr->cellsRequired();
if ( qexprCells.isEmpty() )
{
v->value = QExpr();
return v;
}
// Remove the front.
qexprCells.drop( qexprCells.begin() );
// V becomes Q-expression.
//std::swap( *v, *qexpr );
v->value = QExpr( std::move( qexprCells ) );
return v;
}
SValue* list( SValue* v )
{
REQUIRE( v, v->isSExpression(), "list expects an S-expression" );
v->value = QExpr{ std::move( v->cellsRequired() ) }; // Move the S-expression cells into a Q-expression.
return v;
}
// v is an s-expression containing "qexpr qexpr ... "
// sexpr
// qexpr
// qexpr
SValue* join( SValue* v )
{
Cells& cells = v->cellsRequired();
const bool allQexprs =
std::all_of( cells.begin(), cells.end(), []( const auto& child ) { return child->isQExpression(); } );
REQUIRE( v, allQexprs, "join must take Q-expressions" );
std::unique_ptr< SValue > joined = cells.takeFront();
Cells& joinedCells = joined->cellsRequired();
// Join rest of the cells.
std::for_each( cells.begin(), cells.end(), [ &joinedCells ]( auto& child ) {
Cells& otherCells = child->cellsRequired();
while ( !otherCells.isEmpty() )
{
joinedCells.append( otherCells.takeFront() );
}
} );
// v now becomes a Q-expression.
std::swap( *v, *joined );
return v;
}
SValue* length( SValue* v )
{
Cells& args = v->cellsRequired();
REQUIRE( v, args.size() == 1, "length requires 1 argument" );
SValue* qexpr = args.front();
REQUIRE( v, qexpr->isQExpression(), "length expects a QExpression" );
Cells& qexprCells = qexpr->cellsRequired();
v->value = static_cast< int >( qexprCells.size() );
return v;
}