示例#1
0
文件: CallStack.cs 项目: inkle/ink
 public Element(PushPopType type, Container container, int contentIndex, bool inExpressionEvaluation = false) {
     this.currentContainer = container;
     this.currentContentIndex = contentIndex;
     this.inExpressionEvaluation = inExpressionEvaluation;
     this.temporaryVariables = new Dictionary<string, Object>();
     this.type = type;
 }
示例#2
0
 public void Push(PushPopType type)
 {
     // When pushing to callstack, maintain the current content path, but jump out of expressions by default
     callStack.Add(new Element(type, currentElement.currentContainer, currentElement.currentContentIndex, inExpressionEvaluation: false));
 }
示例#3
0
 public Divert(PushPopType stackPushType)
 {
     pushesToStack      = true;
     this.stackPushType = stackPushType;
 }
示例#4
0
        // ----------------------
        // JSON ENCODING SCHEME
        // ----------------------
        //
        // Glue:           "<>", "G<", "G>"
        //
        // ControlCommand: "ev", "out", "/ev", "du" "pop", "->->", "~ret", "str", "/str", "nop",
        //                 "choiceCnt", "turns", "visit", "seq", "thread", "done", "end"
        //
        // NativeFunction: "+", "-", "/", "*", "%" "~", "==", ">", "<", ">=", "<=", "!=", "!"... etc
        //
        // Void:           "void"
        //
        // Value:          "^string value", "^^string value beginning with ^"
        //                 5, 5.2
        //                 {"^->": "path.target"}
        //                 {"^var": "varname", "ci": 0}
        //
        // Container:      [...]
        //                 [...,
        //                     {
        //                         "subContainerName": ...,
        //                         "#f": 5,                    // flags
        //                         "#n": "containerOwnName"    // only if not redundant
        //                     }
        //                 ]
        //
        // Divert:         {"->": "path.target", "c": true }
        //                 {"->": "path.target", "var": true}
        //                 {"f()": "path.func"}
        //                 {"->t->": "path.tunnel"}
        //                 {"x()": "externalFuncName", "exArgs": 5}
        //
        // Var Assign:     {"VAR=": "varName", "re": true}   // reassignment
        //                 {"temp=": "varName"}
        //
        // Var ref:        {"VAR?": "varName"}
        //                 {"CNT?": "stitch name"}
        //
        // ChoicePoint:    {"*": pathString,
        //                  "flg": 18 }
        //
        // Choice:         Nothing too clever, it's only used in the save state,
        //                 there's not likely to be many of them.
        //
        // Tag:            {"#": "the tag text"}
        public static Runtime.Object JTokenToRuntimeObject(object token)
        {
            if (token is int || token is float)
            {
                return(Value.Create(token));
            }

            if (token is string)
            {
                string str = (string)token;

                // String value
                char firstChar = str[0];
                if (firstChar == '^')
                {
                    return(new StringValue(str.Substring(1)));
                }
                else if (firstChar == '\n' && str.Length == 1)
                {
                    return(new StringValue("\n"));
                }

                // Glue
                if (str == "<>")
                {
                    return(new Runtime.Glue(GlueType.Bidirectional));
                }
                else if (str == "G<")
                {
                    return(new Runtime.Glue(GlueType.Left));
                }
                else if (str == "G>")
                {
                    return(new Runtime.Glue(GlueType.Right));
                }

                // Control commands (would looking up in a hash set be faster?)
                for (int i = 0; i < _controlCommandNames.Length; ++i)
                {
                    string cmdName = _controlCommandNames [i];
                    if (str == cmdName)
                    {
                        return(new Runtime.ControlCommand((ControlCommand.CommandType)i));
                    }
                }

                // Native functions
                // "^" conflicts with the way to identify strings, so now
                // we know it's not a string, we can convert back to the proper
                // symbol for the operator.
                if (str == "L^")
                {
                    str = "^";
                }
                if (NativeFunctionCall.CallExistsWithName(str))
                {
                    return(NativeFunctionCall.CallWithName(str));
                }

                // Pop
                if (str == "->->")
                {
                    return(Runtime.ControlCommand.PopTunnel());
                }
                else if (str == "~ret")
                {
                    return(Runtime.ControlCommand.PopFunction());
                }

                // Void
                if (str == "void")
                {
                    return(new Runtime.Void());
                }
            }

            if (token is Dictionary <string, object> )
            {
                var    obj = (Dictionary <string, object>)token;
                object propValue;

                // Divert target value to path
                if (obj.TryGetValue("^->", out propValue))
                {
                    return(new DivertTargetValue(new Path((string)propValue)));
                }

                // VariablePointerValue
                if (obj.TryGetValue("^var", out propValue))
                {
                    var varPtr = new VariablePointerValue((string)propValue);
                    if (obj.TryGetValue("ci", out propValue))
                    {
                        varPtr.contextIndex = (int)propValue;
                    }
                    return(varPtr);
                }

                // Divert
                bool        isDivert      = false;
                bool        pushesToStack = false;
                PushPopType divPushType   = PushPopType.Function;
                bool        external      = false;
                if (obj.TryGetValue("->", out propValue))
                {
                    isDivert = true;
                }
                else if (obj.TryGetValue("f()", out propValue))
                {
                    isDivert      = true;
                    pushesToStack = true;
                    divPushType   = PushPopType.Function;
                }
                else if (obj.TryGetValue("->t->", out propValue))
                {
                    isDivert      = true;
                    pushesToStack = true;
                    divPushType   = PushPopType.Tunnel;
                }
                else if (obj.TryGetValue("x()", out propValue))
                {
                    isDivert      = true;
                    external      = true;
                    pushesToStack = false;
                    divPushType   = PushPopType.Function;
                }
                if (isDivert)
                {
                    var divert = new Divert();
                    divert.pushesToStack = pushesToStack;
                    divert.stackPushType = divPushType;
                    divert.isExternal    = external;

                    string target = propValue.ToString();

                    if (obj.TryGetValue("var", out propValue))
                    {
                        divert.variableDivertName = target;
                    }
                    else
                    {
                        divert.targetPathString = target;
                    }

                    divert.isConditional = obj.TryGetValue("c", out propValue);

                    if (external)
                    {
                        if (obj.TryGetValue("exArgs", out propValue))
                        {
                            divert.externalArgs = (int)propValue;
                        }
                    }

                    return(divert);
                }

                // Choice
                if (obj.TryGetValue("*", out propValue))
                {
                    var choice = new ChoicePoint();
                    choice.pathStringOnChoice = propValue.ToString();

                    if (obj.TryGetValue("flg", out propValue))
                    {
                        choice.flags = (int)propValue;
                    }

                    return(choice);
                }

                // Variable reference
                if (obj.TryGetValue("VAR?", out propValue))
                {
                    return(new VariableReference(propValue.ToString()));
                }
                else if (obj.TryGetValue("CNT?", out propValue))
                {
                    var readCountVarRef = new VariableReference();
                    readCountVarRef.pathStringForCount = propValue.ToString();
                    return(readCountVarRef);
                }

                // Variable assignment
                bool isVarAss    = false;
                bool isGlobalVar = false;
                if (obj.TryGetValue("VAR=", out propValue))
                {
                    isVarAss    = true;
                    isGlobalVar = true;
                }
                else if (obj.TryGetValue("temp=", out propValue))
                {
                    isVarAss    = true;
                    isGlobalVar = false;
                }
                if (isVarAss)
                {
                    var varName   = propValue.ToString();
                    var isNewDecl = !obj.TryGetValue("re", out propValue);
                    var varAss    = new VariableAssignment(varName, isNewDecl);
                    varAss.isGlobal = isGlobalVar;
                    return(varAss);
                }

                // Tag
                if (obj.TryGetValue("#", out propValue))
                {
                    return(new Runtime.Tag((string)propValue));
                }

                // List value
                if (obj.TryGetValue("list", out propValue))
                {
                    var listContent = (Dictionary <string, object>)propValue;
                    var rawList     = new InkList();
                    if (obj.TryGetValue("origins", out propValue))
                    {
                        var namesAsObjs = (List <object>)propValue;
                        rawList.SetInitialOriginNames(namesAsObjs.Cast <string>().ToList());
                    }
                    foreach (var nameToVal in listContent)
                    {
                        var item = new InkListItem(nameToVal.Key);
                        var val  = (int)nameToVal.Value;
                        rawList.Add(item, val);
                    }
                    return(new ListValue(rawList));
                }

                // Used when serialising save state only
                if (obj ["originalChoicePath"] != null)
                {
                    return(JObjectToChoice(obj));
                }
            }

            // Array is always a Runtime.Container
            if (token is List <object> )
            {
                return(JArrayToContainer((List <object>)token));
            }

            if (token == null)
            {
                return(null);
            }

            throw new System.Exception("Failed to convert token to runtime object: " + token);
        }
示例#5
0
        // ----------------------
        // JSON ENCODING SCHEME
        // ----------------------
        //
        // Glue:           "<>", "G<", "G>"
        //
        // ControlCommand: "ev", "out", "/ev", "du" "pop", "->->", "~ret", "str", "/str", "nop",
        //                 "choiceCnt", "turns", "visit", "seq", "thread", "done", "end"
        //
        // NativeFunction: "+", "-", "/", "*", "%" "~", "==", ">", "<", ">=", "<=", "!=", "!"... etc
        //
        // Void:           "void"
        //
        // Value:          "^string value", "^^string value beginning with ^"
        //                 5, 5.2
        //                 {"^->": "path.target"}
        //                 {"^var": "varname", "ci": 0}
        //
        // Container:      [...]
        //                 [...,
        //                     {
        //                         "subContainerName": ...,
        //                         "#f": 5,                    // flags
        //                         "#n": "containerOwnName"    // only if not redundant
        //                     }
        //                 ]
        //
        // Divert:         {"->": "path.target", "c": true }
        //                 {"->": "path.target", "var": true}
        //                 {"f()": "path.func"}
        //                 {"->t->": "path.tunnel"}
        //                 {"x()": "externalFuncName", "exArgs": 5}
        //
        // Var Assign:     {"VAR=": "varName", "re": true}   // reassignment
        //                 {"temp=": "varName"}
        //
        // Var ref:        {"VAR?": "varName"}
        //                 {"CNT?": "stitch name"}
        //
        // ChoicePoint:    {"*": pathString,
        //                  "flg": 18 }
        //
        // Choice:         Nothing too clever, it's only used in the save state,
        //                 there's not likely to be many of them.
        public static Runtime.Object JTokenToRuntimeObject(JToken token)
        {
            if (token.Type == JTokenType.Integer || token.Type == JTokenType.Float)
            {
                return(Value.Create(((JValue)token).Value));
            }

            if (token.Type == JTokenType.String)
            {
                string str = token.ToString();

                // String value
                char firstChar = str[0];
                if (firstChar == '^')
                {
                    return(new StringValue(str.Substring(1)));
                }
                else if (firstChar == '\n' && str.Length == 1)
                {
                    return(new StringValue("\n"));
                }

                // Glue
                if (str == "<>")
                {
                    return(new Runtime.Glue(GlueType.Bidirectional));
                }
                else if (str == "G<")
                {
                    return(new Runtime.Glue(GlueType.Left));
                }
                else if (str == "G>")
                {
                    return(new Runtime.Glue(GlueType.Right));
                }

                // Control commands (would looking up in a hash set be faster?)
                for (int i = 0; i < _controlCommandNames.Length; ++i)
                {
                    string cmdName = _controlCommandNames [i];
                    if (str == cmdName)
                    {
                        return(new Runtime.ControlCommand((ControlCommand.CommandType)i));
                    }
                }

                // Native functions
                if (NativeFunctionCall.CallExistsWithName(str))
                {
                    return(NativeFunctionCall.CallWithName(str));
                }

                // Pop
                if (str == "->->")
                {
                    return(Runtime.ControlCommand.PopTunnel());
                }
                else if (str == "~ret")
                {
                    return(Runtime.ControlCommand.PopFunction());
                }

                // Void
                if (str == "void")
                {
                    return(new Runtime.Void());
                }
            }

            if (token.Type == JTokenType.Object)
            {
                JObject obj = (JObject)token;
                JToken  propValue;

                // Divert target value to path
                if (obj.TryGetValue("^->", out propValue))
                {
                    return(new DivertTargetValue(new Path(propValue.ToString())));
                }

                // VariablePointerValue
                if (obj.TryGetValue("^var", out propValue))
                {
                    var varPtr = new VariablePointerValue(propValue.ToString());
                    if (obj.TryGetValue("ci", out propValue))
                    {
                        varPtr.contextIndex = propValue.ToObject <int> ();
                    }
                    return(varPtr);
                }

                // Divert
                bool        isDivert      = false;
                bool        pushesToStack = false;
                PushPopType divPushType   = PushPopType.Function;
                bool        external      = false;
                if (obj.TryGetValue("->", out propValue))
                {
                    isDivert = true;
                }
                else if (obj.TryGetValue("f()", out propValue))
                {
                    isDivert      = true;
                    pushesToStack = true;
                    divPushType   = PushPopType.Function;
                }
                else if (obj.TryGetValue("->t->", out propValue))
                {
                    isDivert      = true;
                    pushesToStack = true;
                    divPushType   = PushPopType.Tunnel;
                }
                else if (obj.TryGetValue("x()", out propValue))
                {
                    isDivert      = true;
                    external      = true;
                    pushesToStack = false;
                    divPushType   = PushPopType.Function;
                }
                if (isDivert)
                {
                    var divert = new Divert();
                    divert.pushesToStack = pushesToStack;
                    divert.stackPushType = divPushType;
                    divert.isExternal    = external;

                    string target = propValue.ToString();

                    if (obj.TryGetValue("var", out propValue))
                    {
                        divert.variableDivertName = target;
                    }
                    else
                    {
                        divert.targetPathString = target;
                    }

                    divert.isConditional = obj.TryGetValue("c", out propValue);

                    if (external)
                    {
                        if (obj.TryGetValue("exArgs", out propValue))
                        {
                            divert.externalArgs = propValue.ToObject <int> ();
                        }
                    }

                    return(divert);
                }

                // Choice
                if (obj.TryGetValue("*", out propValue))
                {
                    var choice = new ChoicePoint();
                    choice.pathStringOnChoice = propValue.ToString();

                    if (obj.TryGetValue("flg", out propValue))
                    {
                        choice.flags = propValue.ToObject <int>();
                    }

                    return(choice);
                }

                // Variable reference
                if (obj.TryGetValue("VAR?", out propValue))
                {
                    return(new VariableReference(propValue.ToString()));
                }
                else if (obj.TryGetValue("CNT?", out propValue))
                {
                    var readCountVarRef = new VariableReference();
                    readCountVarRef.pathStringForCount = propValue.ToString();
                    return(readCountVarRef);
                }

                // Variable assignment
                bool isVarAss    = false;
                bool isGlobalVar = false;
                if (obj.TryGetValue("VAR=", out propValue))
                {
                    isVarAss    = true;
                    isGlobalVar = true;
                }
                else if (obj.TryGetValue("temp=", out propValue))
                {
                    isVarAss    = true;
                    isGlobalVar = false;
                }
                if (isVarAss)
                {
                    var varName   = propValue.ToString();
                    var isNewDecl = !obj.TryGetValue("re", out propValue);
                    var varAss    = new VariableAssignment(varName, isNewDecl);
                    varAss.isGlobal = isGlobalVar;
                    return(varAss);
                }

                if (obj ["originalChoicePath"] != null)
                {
                    return(JObjectToChoice(obj));
                }
            }

            // Array is always a Runtime.Container
            if (token.Type == JTokenType.Array)
            {
                return(JArrayToContainer((JArray)token));
            }

            if (token.Type == JTokenType.Null)
            {
                return(null);
            }

            throw new System.Exception("Failed to convert token to runtime object: " + token);
        }
示例#6
0
文件: Divert.cs 项目: inkle/ink
 public Divert(PushPopType stackPushType)
 {
     pushesToStack = true;
     this.stackPushType = stackPushType;
 }
示例#7
0
 // For serialisation only
 public Pop()
 {
     this.type = PushPopType.Tunnel;
 }
示例#8
0
 public Pop(PushPopType type)
 {
     this.type = type;
 }
示例#9
0
文件: CallStack.cs 项目: inkle/ink
        public void Pop(PushPopType? type = null)
        {
            if (CanPop (type)) {
                callStack.RemoveAt (callStack.Count - 1);
                return;
            } else {
				throw new System.Exception("Mismatched push/pop in Callstack");
            }
        }
示例#10
0
文件: CallStack.cs 项目: inkle/ink
        public bool CanPop(PushPopType? type = null) {

            if (!canPop)
                return false;
            
            if (type == null)
                return true;
            
            return currentElement.type == type;
        }
示例#11
0
文件: CallStack.cs 项目: inkle/ink
 public void Push(PushPopType type)
 {
     // When pushing to callstack, maintain the current content path, but jump out of expressions by default
     callStack.Add (new Element(type, currentElement.currentContainer, currentElement.currentContentIndex, inExpressionEvaluation: false));
 }