-
Notifications
You must be signed in to change notification settings - Fork 477
/
DivertTarget.cs
119 lines (98 loc) · 4.56 KB
/
DivertTarget.cs
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
namespace Ink.Parsed
{
internal class DivertTarget : Expression
{
public Divert divert;
public DivertTarget (Divert divert)
{
this.divert = AddContent(divert);
}
public override void GenerateIntoContainer (Runtime.Container container)
{
divert.GenerateRuntimeObject();
_runtimeDivert = (Runtime.Divert) divert.runtimeDivert;
_runtimeDivertTargetValue = new Runtime.DivertTargetValue ();
container.AddContent (_runtimeDivertTargetValue);
}
public override void ResolveReferences (Story context)
{
base.ResolveReferences (context);
Parsed.Object usageContext = this;
while (usageContext && usageContext is Expression) {
bool badUsage = false;
bool foundUsage = false;
var usageParent = usageContext.parent;
if (usageParent is BinaryExpression) {
// Only allowed to compare for equality
var binaryExprParent = usageParent as BinaryExpression;
if (binaryExprParent.opName != "==") {
badUsage = true;
} else {
if (!(binaryExprParent.leftExpression is DivertTarget || binaryExprParent.leftExpression is VariableReference)) {
badUsage = true;
}
if (!(binaryExprParent.rightExpression is DivertTarget || binaryExprParent.rightExpression is VariableReference)) {
badUsage = true;
}
}
foundUsage = true;
}
else if( usageParent is FunctionCall ) {
var funcCall = usageParent as FunctionCall;
if( !funcCall.isTurnsSince && !funcCall.isReadCount ) {
badUsage = true;
}
foundUsage = true;
}
else if (usageParent is Expression) {
badUsage = true;
foundUsage = true;
}
else if (usageParent is MultipleConditionExpression) {
badUsage = true;
foundUsage = true;
} else if (usageParent is Choice && ((Choice)usageParent).condition == usageContext) {
badUsage = true;
foundUsage = true;
} else if (usageParent is Conditional || usageParent is ConditionalSingleBranch) {
badUsage = true;
foundUsage = true;
}
if (badUsage) {
Error ("Can't use a divert target like that. Did you intend to call '" + divert.target + "' as a function: likeThis(), or check the read count: likeThis, with no arrows?", this);
}
if (foundUsage)
break;
usageContext = usageParent;
}
// Example ink for this class:
//
// VAR x = -> blah
//
// ...which means that "blah" is expected to be a literal stitch target rather
// than a variable name. We can't really intelligently recover from this (e.g. if blah happens to
// contain a divert target itself) since really we should be generating a variable reference
// rather than a concrete DivertTarget, so we list it as an error.
if (_runtimeDivert.hasVariableTarget)
Error ("Since '"+divert.target.dotSeparatedComponents+"' is a variable, it shouldn't be preceded by '->' here.");
_runtimeDivertTargetValue.targetPath = _runtimeDivert.targetPath;
}
// Equals override necessary in order to check for CONST multiple definition equality
public override bool Equals (object obj)
{
var otherDivTarget = obj as DivertTarget;
if (otherDivTarget == null) return false;
var targetStr = this.divert.target.dotSeparatedComponents;
var otherTargetStr = otherDivTarget.divert.target.dotSeparatedComponents;
return targetStr.Equals (otherTargetStr);
}
public override int GetHashCode ()
{
var targetStr = this.divert.target.dotSeparatedComponents;
return targetStr.GetHashCode ();
}
Runtime.DivertTargetValue _runtimeDivertTargetValue;
Runtime.Divert _runtimeDivert;
}
}