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
|
#include "statementref.hpp"
#include "concepts.hpp"
#include "ref.hpp"
using namespace intellect;
using namespace level2;
using namespace concepts;
// so, anonymous-assignment is both a statement and an expression.
// multiple-member-assignment is only an expression: it is an error to evaluate it
// the submember operator will be both a statement and an expression, but doesn't need to be held as a ref
// single-member-assignment is mostly a statement: using it as an expression should be an error.
static statementref makebinary(
ref lhs, ref kind, ref rhs,
std::function<ref(ref)> expraction,
std::function<void(ref)> stmtaction
)
{
a(statement-expresion, kind-expression);
ref r = a(kind-expression);
r.set(left-operand, lhs);
r.set(right-operand, rhs);
r.vset(expression-action, expraction);
r.vset(statement-action, stmtaction);
return r;
}
statementref::statementref(ref r)
: r(r.ptr())
{
if (!r.isa(statement-expression)) {
throw std::logic_error("that is not a statement expression");
}
}
static void de(ref & r)
{
ref lhs, rhs, expraction, stmtaction;
try { lhs = r.get(left-operand); } catch(level0::no_such_link_type&) {}
try { rhs = r.get(right-operand); } catch(level0::no_such_link_type&) {}
expraction = r.get(expression-action);
stmtaction = r.get(statement-action);
dealloc(r);
if (lhs != nothing) { dealloc(lhs); }
if (rhs != nothing) { dealloc(rhs); }
dealloc(expraction);
dealloc(stmtaction);
r = 0;
}
statementref::~statementref()
{
if (r == 0) { return; }
r.vget<std::function<void(ref)>>(statement-action)(r);
de(r);
}
statementref::operator ref()
{
if (r == 0) { throw std::logic_error("doubly evaluated expression"); }
auto ret = r.vget<std::function<void(ref)>>(expression-action)(r);
de(r);
return ret;
}
|