Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion compiler/InkParser/InkParser_Expressions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ protected Expression ExpressionUnary()

// - Since we allow numbers at the start of variable names, variable names are checked before literals
// - Function calls before variable names in case we see parentheses
var expr = OneOf (ExpressionList, ExpressionParen, ExpressionFunctionCall, ExpressionVariableName, ExpressionLiteral) as Expression;
var expr = OneOf (ExpressionList, ExpressionParen, ExpressionFunctionCall, ExpressionVariableName, ExpressionLiteral, ExpressionStack) as Expression;

// Only recurse immediately if we have one of the (usually optional) unary ops
if (expr == null && prefixOp != null) {
Expand Down Expand Up @@ -415,6 +415,17 @@ private InfixOperator ParseInfixOperator()
return null;
}


protected Parsed.Stack ExpressionStack() {
Whitespace();
if(ParseString ("[") == null) { return null; };
Whitespace();
List<Expression> contents = SeparatedList(Expression, Spaced(String(",")));
Whitespace();
if (ParseString("]") == null) { return null;};
return new Stack(contents);
}

protected Parsed.List ExpressionList ()
{
Whitespace ();
Expand Down
17 changes: 15 additions & 2 deletions compiler/InkParser/InkParser_Logic.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,8 @@ protected Parsed.Object VariableDeclaration()
var expr = definition as Parsed.Expression;

if (expr) {
if (!(expr is Number || expr is StringExpression || expr is DivertTarget || expr is VariableReference || expr is List)) {
Error ("initial value for a variable must be a number, constant, list or divert target");
if (!(validInitialValue(expr) || expr is Stack)) {
Error ("initial value for a variable must be a number, constant, list, stack or divert target");
}

if (Parse (ListElementDefinitionSeparator) != null)
Expand All @@ -110,13 +110,26 @@ protected Parsed.Object VariableDeclaration()
if (!strExpr.isSingleString)
Error ("Constant strings cannot contain any logic.");
}
// Ensure stack literals don't contain invalid values for initial value
else if (expr is Stack) {
var stackExpr = expr as Stack;
foreach(var value in stackExpr.contents) {
if(!(validInitialValue(value))) {
Error ("initial values in a stack variable must be a number, constant, list or divert target");
}
}
}

var result = new VariableAssignment (varName, expr);
result.isGlobalDeclaration = true;
return result;
}

return null;

bool validInitialValue(Expression expression) {
return (expression is Number || expression is StringExpression || expression is DivertTarget || expression is VariableReference || expression is List);
}
}

protected Parsed.VariableAssignment ListDeclaration ()
Expand Down
4 changes: 4 additions & 0 deletions compiler/ParsedHierarchy/DivertTarget.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ public override void ResolveReferences (Story context)
}
foundUsage = true;
}
else if (usageParent is Stack) {
badUsage = false;
foundUsage = true;
}
else if (usageParent is Expression) {
badUsage = true;
foundUsage = true;
Expand Down
45 changes: 45 additions & 0 deletions compiler/ParsedHierarchy/FunctionCall.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ public class FunctionCall : Expression
public bool isListRange { get { return name == "LIST_RANGE"; } }
public bool isListRandom { get { return name == "LIST_RANDOM"; } }
public bool isReadCount { get { return name == "READ_COUNT"; } }
public bool isStackPopNewest { get { return name == "STACK_POP_NEWEST"; } }
public bool isStackPopOldest { get { return name == "STACK_POP_OLDEST"; } }
public bool isStackPopRandom { get { return name == "STACK_POP_RANDOM"; } }

public bool shouldPopReturnedValue;

Expand Down Expand Up @@ -122,6 +125,48 @@ public override void GenerateIntoContainer (Runtime.Container container)

container.AddContent (Runtime.ControlCommand.ListRandom ());

} else if (isStackPopNewest) {
if (arguments == null || arguments.Count != 2)
Error("STACK_POP_NEWEST should take 2 parameter - a stack, and a variable to assign the popped value to");

var reference = arguments[1];
if (!(reference is VariableReference))
{
Error("STACK_POP_NEWEST should take 2 parameter - a stack, and a variable to assign the popped value to");
}


arguments[0].GenerateIntoContainer(container);
container.AddContent(new Runtime.VariablePointerValue((reference as VariableReference).name));
container.AddContent(Runtime.ControlCommand.StackPopNewest());

} else if (isStackPopOldest) {
if (arguments == null || arguments.Count != 2)
Error("STACK_POP_OLDEST should take 2 parameter - a stack, and a variable to assign the popped value to");

var reference = arguments[1];
if (!(reference is VariableReference))
{
Error("STACK_POP_OLDEST should take 2 parameter - a stack, and a variable to assign the popped value to");
}

arguments[0].GenerateIntoContainer(container);
container.AddContent(new Runtime.VariablePointerValue((reference as VariableReference).name));
container.AddContent(Runtime.ControlCommand.StackPopOldest());

} else if (isStackPopRandom) {
if (arguments == null || arguments.Count != 2)
Error("STACK_POP_RANDOM should take 2 parameter - a stack, and a variable to assign the popped value to");

var reference = arguments[1];
if (!(reference is VariableReference))
{
Error("STACK_POP_RANDOM should take 2 parameter - a stack, and a variable to assign the popped value to");
}

arguments[0].GenerateIntoContainer(container);
container.AddContent(new Runtime.VariablePointerValue((reference as VariableReference).name));
container.AddContent(Runtime.ControlCommand.StackPopRandom());
} else if (Runtime.NativeFunctionCall.CallExistsWithName (name)) {

var nativeCall = Runtime.NativeFunctionCall.CallWithName (name);
Expand Down
47 changes: 47 additions & 0 deletions compiler/ParsedHierarchy/Stack.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
using System.Collections.Generic;

namespace Ink.Parsed
{
public class Stack : Parsed.Expression
{
public List<Expression> contents;

public Stack (List<Expression> expressions)
{
this.contents = expressions ?? new List<Expression>();
}

public override void ResolveReferences(Story context)
{
base.ResolveReferences(context);
foreach(var content in contents) {
content.ResolveReferences(context);
}
}

// Only known after GenerateIntoContainer has run
public bool isValidGlobalStackLiteral;

public override void GenerateIntoContainer(Runtime.Container container)
{
// Assume true until we find a counter
isValidGlobalStackLiteral = true;

if (contents != null) {
foreach (var valueExpression in contents) {
valueExpression.parent = this;
valueExpression.GenerateIntoContainer(container);
var variableReference = valueExpression as VariableReference;
if(variableReference && !variableReference.isConstantReference && !variableReference.isListItemReference) {
isValidGlobalStackLiteral = false;
}
}
}

var count = contents == null ? 0 : contents.Count;
container.AddContent(new Runtime.IntValue(count));

container.AddContent(Runtime.ControlCommand.StackLiteralEnd());
}
}
}
5 changes: 5 additions & 0 deletions compiler/ParsedHierarchy/VariableAssignment.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Linq;

namespace Ink.Parsed
{
Expand Down Expand Up @@ -89,6 +90,10 @@ public override void ResolveReferences (Story context)
if (variableReference && !variableReference.isConstantReference && !variableReference.isListItemReference) {
Error ("global variable assignments cannot refer to other variables, only literal values, constants and list items");
}
var stack = expression as Stack;
if(stack && !stack.isValidGlobalStackLiteral) {
Error ("global variable assignments cannot refer to other variables, only literal values, constants and list items");
}
}

if (!this.isNewTemporaryDeclaration) {
Expand Down
24 changes: 24 additions & 0 deletions ink-engine-runtime/ControlCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ public enum CommandType
ListRandom,
BeginTag,
EndTag,
StackPopNewest,
StackPopOldest,
StackPopRandom,
StackLiteralEnd,
//----
TOTAL_VALUES
}
Expand Down Expand Up @@ -173,6 +177,26 @@ public static ControlCommand EndTag ()
return new ControlCommand (CommandType.EndTag);
}

public static ControlCommand StackPopNewest()
{
return new ControlCommand(CommandType.StackPopNewest);
}

public static ControlCommand StackPopOldest()
{
return new ControlCommand(CommandType.StackPopOldest);
}

public static ControlCommand StackPopRandom()
{
return new ControlCommand(CommandType.StackPopRandom);
}

public static ControlCommand StackLiteralEnd()
{
return new ControlCommand(CommandType.StackLiteralEnd);
}

public override string ToString ()
{
return commandType.ToString();
Expand Down
Loading