Skip to content

Commit 4f1742a

Browse files
committed
fix sl bug; cleaning; add more copy/move tests
1 parent bcc33a8 commit 4f1742a

File tree

2 files changed

+45
-33
lines changed

2 files changed

+45
-33
lines changed

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
![](https://github.com/sdingcn/clo/actions/workflows/CI.yml/badge.svg)
44

5-
**Clo** is a small, dynamically-typed, garbage-collected, functional programming language.
5+
**Clo** is a dynamically-typed garbage-collected programming language.
66
```
77
<comment> := "#" [^\n]* "\n"
88
<intrinsic> := "." [^\s]+
@@ -18,9 +18,9 @@
1818
```
1919

2020
The distinguished feature of clo is serializing
21-
the current program state as a string.
21+
the program state as a string.
2222
The built-in function `.forkstate` returns
23-
a string encoding the program state,
23+
a string encoding the current state,
2424
and when the state is resumed using `.eval` it starts
2525
right after the `.forkstate` call but with a return value of Void type.
2626
This resembles Linux's `fork`, Lisp's `call/cc`, etc.

src/main.cpp

Lines changed: 42 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ namespace utils {
5454
}
5555
return "(SourceLocation " + std::to_string(line) + " " + std::to_string(column) + ")";
5656
}
57-
void revert() {
57+
void reset() {
5858
line = 1;
5959
column = 1;
6060
}
@@ -161,13 +161,14 @@ namespace syntax {
161161
"qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM"
162162
"[]\\;',./{}|:\"<>? \t\n";
163163
std::unordered_set<char> charset(charstr.begin(), charstr.end());
164+
sl.reset();
164165
for (char c : source) {
165166
if (!charset.contains(c)) {
166167
utils::panic("lexer", "unsupported character", sl);
167168
}
168169
sl.update(c);
169170
}
170-
sl.revert();
171+
sl.reset();
171172
std::reverse(source.begin(), source.end());
172173
}
173174

@@ -200,6 +201,7 @@ namespace syntax {
200201
};
201202

202203
std::deque<Token> lex(std::string source) {
204+
// the constructor checks the character set
203205
SourceStream ss(std::move(source));
204206

205207
std::function<std::optional<Token>()> nextToken =
@@ -314,15 +316,15 @@ namespace syntax {
314316
CLASS(const CLASS &) = delete; \
315317
CLASS &operator=(const CLASS &) = delete
316318

317-
#define BASIC_INFO_PARMDECL \
319+
#define BASIC_PARMDECL \
318320
utils::SourceLocation s = utils::SourceLocation(), \
319321
std::unordered_set<std::string> f = std::unordered_set<std::string>(), \
320322
bool t = false
321323

322324
struct ExprNode {
323325
DELETE_COPY(ExprNode);
324326
virtual ~ExprNode() {}
325-
ExprNode(BASIC_INFO_PARMDECL)
327+
ExprNode(BASIC_PARMDECL)
326328
: sl(s), freeVars(f), tail(t) {}
327329

328330
virtual ExprNode* clone() const = 0;
@@ -348,7 +350,7 @@ namespace syntax {
348350
struct IntegerNode : public ExprNode {
349351
DELETE_COPY(IntegerNode);
350352
virtual ~IntegerNode() {}
351-
IntegerNode(std::string v, BASIC_INFO_PARMDECL)
353+
IntegerNode(std::string v, BASIC_PARMDECL)
352354
: ExprNode(s, f, t), val(std::move(v)) {}
353355

354356
// covariant return type for override
@@ -380,7 +382,7 @@ namespace syntax {
380382
struct StringNode : public ExprNode {
381383
DELETE_COPY(StringNode);
382384
virtual ~StringNode() {}
383-
StringNode(std::string v, BASIC_INFO_PARMDECL)
385+
StringNode(std::string v, BASIC_PARMDECL)
384386
: ExprNode(s, f, t), val(std::move(v)) {}
385387

386388
// covariant return type
@@ -411,7 +413,7 @@ namespace syntax {
411413
struct VariableNode : public ExprNode {
412414
DELETE_COPY(VariableNode);
413415
virtual ~VariableNode() {}
414-
VariableNode(std::string n, BASIC_INFO_PARMDECL)
416+
VariableNode(std::string n, BASIC_PARMDECL)
415417
: ExprNode(s, f, t), name(std::move(n)) {}
416418

417419
virtual VariableNode* clone() const override {
@@ -444,7 +446,7 @@ namespace syntax {
444446
}
445447
delete expr;
446448
}
447-
LambdaNode(std::vector<VariableNode*> v, ExprNode* e, BASIC_INFO_PARMDECL) :
449+
LambdaNode(std::vector<VariableNode*> v, ExprNode* e, BASIC_PARMDECL) :
448450
ExprNode(s, f, t), varList(std::move(v)), expr(e) {}
449451

450452
virtual LambdaNode* clone() const override {
@@ -518,7 +520,7 @@ namespace syntax {
518520
}
519521
LetrecNode(
520522
std::vector<std::pair<VariableNode*, ExprNode*>> v, ExprNode* e,
521-
BASIC_INFO_PARMDECL) :
523+
BASIC_PARMDECL) :
522524
ExprNode(s, f, t), varExprList(std::move(v)), expr(e) {}
523525

524526
virtual LetrecNode* clone() const override {
@@ -597,7 +599,7 @@ namespace syntax {
597599
delete branch1;
598600
delete branch2;
599601
}
600-
IfNode(ExprNode* c, ExprNode* b1, ExprNode* b2, BASIC_INFO_PARMDECL) :
602+
IfNode(ExprNode* c, ExprNode* b1, ExprNode* b2, BASIC_PARMDECL) :
601603
ExprNode(s, f, t), cond(c), branch1(b1), branch2(b2) {}
602604

603605
virtual IfNode* clone() const override {
@@ -654,7 +656,7 @@ namespace syntax {
654656
delete e;
655657
}
656658
}
657-
SequenceNode(std::vector<ExprNode*> e, BASIC_INFO_PARMDECL) :
659+
SequenceNode(std::vector<ExprNode*> e, BASIC_PARMDECL) :
658660
ExprNode(s, f, t), exprList(std::move(e)) {}
659661

660662
virtual SequenceNode* clone() const override {
@@ -720,7 +722,7 @@ namespace syntax {
720722
delete a;
721723
}
722724
}
723-
IntrinsicCallNode(std::string i, std::vector<ExprNode*> a, BASIC_INFO_PARMDECL):
725+
IntrinsicCallNode(std::string i, std::vector<ExprNode*> a, BASIC_PARMDECL):
724726
ExprNode(s, f, t), intrinsic(std::move(i)), argList(std::move(a)) {}
725727

726728
virtual IntrinsicCallNode* clone() const override {
@@ -784,7 +786,7 @@ namespace syntax {
784786
delete a;
785787
}
786788
}
787-
ExprCallNode(ExprNode* e, std::vector<ExprNode*> a, BASIC_INFO_PARMDECL) :
789+
ExprCallNode(ExprNode* e, std::vector<ExprNode*> a, BASIC_PARMDECL) :
788790
ExprNode(s, f, t), expr(e), argList(std::move(a)) {}
789791

790792
virtual ExprCallNode* clone() const override {
@@ -850,7 +852,7 @@ namespace syntax {
850852
delete var;
851853
delete expr;
852854
}
853-
AtNode(VariableNode* v, ExprNode* e, BASIC_INFO_PARMDECL) :
855+
AtNode(VariableNode* v, ExprNode* e, BASIC_PARMDECL) :
854856
ExprNode(s, f, t), var(v), expr(e) {}
855857

856858
virtual AtNode* clone() const override {
@@ -892,7 +894,7 @@ namespace syntax {
892894
}
893895
};
894896

895-
#undef BASIC_INFO_PARMDECL
897+
#undef BASIC_PARMDECL
896898
#undef DELETE_COPY
897899

898900
ExprNode* parse(std::deque<Token> tokens) {
@@ -1122,7 +1124,6 @@ namespace runtime {
11221124
using Value = std::variant<Void, Integer, String, Closure>;
11231125

11241126
// stack layer
1125-
11261127
struct Layer {
11271128
// a default argument is evaluated each time the function is called without
11281129
// that argument (not important here)
@@ -2688,6 +2689,17 @@ class State {
26882689
auto ret = "|" + serializedSource + " " + serializedState + "|";
26892690
return ret;
26902691
}
2692+
void clear() {
2693+
source.clear();
2694+
if (expr != nullptr) {
2695+
delete expr;
2696+
expr = nullptr;
2697+
}
2698+
stack.clear();
2699+
heap.clear();
2700+
numLiterals = 0;
2701+
resultLoc = -1;
2702+
}
26912703
private:
26922704
// states
26932705
std::string source;
@@ -2706,7 +2718,7 @@ std::string readSource(const std::string& spath) {
27062718
if (!std::filesystem::exists(spath)) {
27072719
utils::panic("reader", spath + " does not exist.");
27082720
}
2709-
static constexpr std::size_t BLOCK = 1024;
2721+
static constexpr std::size_t BLOCK = 8192;
27102722
std::ifstream in(spath);
27112723
in.exceptions(std::ios_base::badbit);
27122724
std::string source;
@@ -2731,23 +2743,23 @@ int main(int argc, char** argv) {
27312743
<< serialization::join(
27322744
serialization::valueToSentence(state.getResult(), state.getExpr())) << std::endl;
27332745
#else
2734-
// test the copy / move assignment operators for State
2746+
// test the (copy & move) (constructors & assignment operators) for State
27352747
std::string source = readSource(argv[1]);
27362748
State state1(source);
2737-
{
2738-
State state2(source);
2739-
{
2740-
State state3(source);
2741-
state2 = state3;
2742-
// destruct state3
2743-
}
2744-
state1 = std::move(state2);
2745-
// destruct state2
2746-
}
2747-
state1.execute();
2749+
State state2(state1); // copy constructor
2750+
state1.clear();
2751+
State state3(std::move(state2)); // move constructor
2752+
state2.clear();
2753+
State state4(source);
2754+
state4 = state3; // copy assignment operator
2755+
state3.clear();
2756+
State state5(source);
2757+
state5 = std::move(state4); // move assignment operator
2758+
state4.clear();
2759+
state5.execute();
27482760
std::cout << "<end-of-stdout>\n"
27492761
<< serialization::join(
2750-
serialization::valueToSentence(state1.getResult(), state1.getExpr())) << std::endl;
2762+
serialization::valueToSentence(state5.getResult(), state5.getExpr())) << std::endl;
27512763
#endif
27522764
}
27532765
catch (const std::runtime_error& e) {

0 commit comments

Comments
 (0)