Пример #1
0
 protected void CopySimpleData(ScriptVar val)
 {
     data       = val.data;
     intData    = val.intData;
     doubleData = val.doubleData;
     flags      = (flags & ~Flags.VarTypeMask) | (val.flags & Flags.VarTypeMask);
 }
Пример #2
0
        public void ReplaceWith(ScriptVar newVar)
        {
            ScriptVar oldVar = Var;

            Var = newVar.Ref();
            oldVar.UnRef();
        }
Пример #3
0
        public void AddNativeProperty(string propertyDesc, ScriptCallbackCB callbackCB, object userData)
        {
            var oldLex = currentLexer;

            currentLexer = new ScriptLex(propertyDesc);

            var baseVar = Root;

            var propName = currentLexer.TokenString;

            currentLexer.Match(ScriptLex.LexTypes.Id);

            while (currentLexer.TokenType == (ScriptLex.LexTypes) '.')
            {
                currentLexer.Match((ScriptLex.LexTypes) '.');

                var link = baseVar.FindChild(propName);
                if (link == null)
                {
                    link = baseVar.AddChild(propName, new ScriptVar(null, ScriptVar.Flags.Object));
                }
                baseVar  = link.Var;
                propName = currentLexer.TokenString;
                currentLexer.Match(ScriptLex.LexTypes.Id);
            }
            var propVar = new ScriptVar();

            callbackCB.Invoke(propVar, null);

            currentLexer = oldLex;

            baseVar.AddChild(propName, propVar);
        }
Пример #4
0
        public ScriptVarLink AddChild(string childName, ScriptVar child, bool readOnly = false)
        {
            if (IsUndefined)
            {
                flags = Flags.Object;
            }

            var c = child ?? new ScriptVar();

            var link = new ScriptVarLink(c, childName, readOnly)
            {
                Owned = true
            };

            if (LastChild != null)
            {
                LastChild.Next = link;
                link.Prev      = LastChild;
                LastChild      = link;
            }
            else
            {
                FirstChild = link;
                LastChild  = link;
            }

            return(link);
        }
Пример #5
0
 protected void CopySimpleData(ScriptVar val)
 {
     _data       = val._data;
     _intData    = val._intData;
     _doubleData = val._doubleData;
     _flags      = (_flags & ~Flags.VarTypeMask) | (val._flags & Flags.VarTypeMask);
 }
Пример #6
0
        public ScriptVarLink AddChild(String childName, ScriptVar child)
        {
            if (IsUndefined)
            {
                _flags = Flags.Object;
            }

            ScriptVar c = child ?? new ScriptVar();

            ScriptVarLink link = new ScriptVarLink(c, childName)
            {
                Owned = true
            };

            if (LastChild != null)
            {
                LastChild.Next = link;
                link.Prev      = LastChild;
                LastChild      = link;
            }
            else
            {
                FirstChild = link;
                LastChild  = link;
            }

            return(link);
        }
Пример #7
0
 public ScriptVarLink(ScriptVar var, String name)
 {
     Name  = name;
     Var   = var.Ref();
     Next  = null;
     Prev  = null;
     Owned = false;
 }
Пример #8
0
 public ScriptVarLink(ScriptVar var, string name, bool readOnly = false)
 {
     Name    = name;
     Var     = var.Ref();
     Next    = null;
     Prev    = null;
     Owned   = false;
     IsConst = readOnly;
 }
Пример #9
0
        public bool Equal(ScriptVar v)
        {
            bool res;

            using (ScriptVar resV = MathsOp(v, ScriptLex.LexTypes.Equal))
            {
                res = resV.GetBool();
            }

            return(res);
        }
Пример #10
0
 private void CreateLink(ref ScriptVarLink link, ScriptVar res)
 {
     if (link == null || link.Owned)
     {
         link = new ScriptVarLink(res, null);
     }
     else
     {
         link.ReplaceWith(res);
     }
 }
Пример #11
0
        public void ReplaceWith(ScriptVar newVar)
        {
            if (IsConst && Var?.IsUndefined == false)
            {
                throw new JITException(string.Format("{0} is const, cannot assign a new value", Name));
            }

            var oldVar = Var;

            Var = newVar.Ref();
            oldVar.UnRef();
        }
Пример #12
0
        private void ParseFunctionArguments(ScriptVar funcVar)
        {
            _currentLexer.Match((ScriptLex.LexTypes) '(');
            while (_currentLexer.TokenType != (ScriptLex.LexTypes) ')')
            {
                funcVar.AddChildNoDup(_currentLexer.TokenString, null);
                _currentLexer.Match(ScriptLex.LexTypes.Id);

                if (_currentLexer.TokenType != (ScriptLex.LexTypes) ')')
                {
                    _currentLexer.Match((ScriptLex.LexTypes) ',');
                }
            }

            _currentLexer.Match((ScriptLex.LexTypes) ')');
        }
Пример #13
0
        public void RemoveChild(ScriptVar child)
        {
            ScriptVarLink link = FirstChild;

            while (link != null)
            {
                if (link.Var == child)
                {
                    break;
                }

                link = link.Next;
            }

            RemoveLink(link);
        }
Пример #14
0
        public ScriptEngine()
        {
            currentLexer = null;

            scopes    = new List <ScriptVar>();
            callStack = new Stack <ScriptVarLink>();

            Root = (new ScriptVar(null, ScriptVar.Flags.Object)).Ref();

            objectClass = (new ScriptVar(null, ScriptVar.Flags.Object)).Ref();
            stringClass = (new ScriptVar(null, ScriptVar.Flags.Object)).Ref();
            arrayClass  = (new ScriptVar(null, ScriptVar.Flags.Object)).Ref();

            Root.AddChild("Object", objectClass);
            Root.AddChild("String", stringClass);
            Root.AddChild("Array", arrayClass);
        }
Пример #15
0
        public void AddMethod(String funcName, String[] args, ScriptCallbackCB callback, Object userdata)
        {
            ScriptVar funcVar = new ScriptVar(null, ScriptVar.Flags.Function | ScriptVar.Flags.Native);

            funcVar.SetCallback(callback, userdata);

            //do we have any arguments to create?
            if (args != null)
            {
                foreach (string arg in args)
                {
                    funcVar.AddChildNoDup(arg, null);
                }
            }

            Root.AddChild(funcName, funcVar);
        }
Пример #16
0
        public ScriptVarLink AddChildNoDup(String childName, ScriptVar child)
        {
            ScriptVar c = child ?? new ScriptVar();

            ScriptVarLink v = FindChild(childName);

            if (v != null)
            {
                v.ReplaceWith(c);
            }
            else
            {
                v = AddChild(childName, c);
            }

            return(v);
        }
Пример #17
0
        public ScriptVar DeepCopy()
        {
            ScriptVar newVar = new ScriptVar();

            newVar.CopySimpleData(this);

            ScriptVarLink link = FirstChild;

            while (link != null)
            {
                ScriptVar copied = link.Name != PrototypeClassName?link.Var.DeepCopy() : link.Var;

                newVar.AddChild(link.Name, copied);

                link = link.Next;
            }

            return(newVar);
        }
Пример #18
0
        private ScriptVarLink FindInParentClasses(ScriptVar obj, String name)
        {
            ScriptVarLink implementation;
            ScriptVarLink parentClass = obj.FindChild(ScriptVar.PrototypeClassName);

            while (parentClass != null)
            {
                implementation = parentClass.Var.FindChild(name);
                if (implementation != null)
                {
                    return(implementation);
                }
                parentClass = parentClass.Var.FindChild(ScriptVar.PrototypeClassName);
            }

            if (obj.IsString)
            {
                implementation = _stringClass.FindChild(name);
                if (implementation != null)
                {
                    return(implementation);
                }
            }

            if (obj.IsArray)
            {
                implementation = _arrayClass.FindChild(name);
                if (implementation != null)
                {
                    return(implementation);
                }
            }

            implementation = _objectClass.FindChild(name);
            if (implementation != null)
            {
                return(implementation);
            }

            return(null);
        }
Пример #19
0
        public void AddObject(String[] ns, String objectName, ScriptVar val)
        {
            ScriptVar baseVar = Root;

            if (ns != null)
            {
                int x = 0;
                for (; x < ns.Length; x++)
                {
                    ScriptVarLink link = baseVar.FindChild(ns[x]);

                    if (link == null)
                    {
                        link = baseVar.AddChild(ns[x], new ScriptVar(null, ScriptVar.Flags.Object));
                    }

                    baseVar = link.Var;
                }
            }

            baseVar.AddChild(objectName, val);
        }
Пример #20
0
        public ScriptEngine(bool loadProviders = true)
        {
            _currentLexer = null;

            _scopes    = new Stack <ScriptVar>();
            _callStack = new Stack <string>();

            Root = (new ScriptVar(null, ScriptVar.Flags.Object)).Ref();

            _stringClass = (new ScriptVar(null, ScriptVar.Flags.Object)).Ref();
            _objectClass = (new ScriptVar(null, ScriptVar.Flags.Object)).Ref();
            _arrayClass  = (new ScriptVar(null, ScriptVar.Flags.Object)).Ref();

            Root.AddChild("String", _stringClass);
            Root.AddChild("Object", _objectClass);
            Root.AddChild("Array", _arrayClass);

            if (loadProviders)
            {
                LoadAllFunctionProviders();
            }
        }
Пример #21
0
        public void CopyValue(ScriptVar val)
        {
            if (val != null)
            {
                CopySimpleData(val);
                RemoveAllChildren();

                ScriptVarLink link = val.FirstChild;

                while (link != null)
                {
                    ScriptVar copied = link.Name != PrototypeClassName?link.Var.DeepCopy() : link.Var;

                    AddChild(link.Name, copied);

                    link = link.Next;
                }
            }
            else
            {
                SetUndefined();
            }
        }
Пример #22
0
        public void SetArrayIndex(Int32 idx, ScriptVar value)
        {
            ScriptVarLink link = FindChild(String.Format("{0}", idx));

            if (link != null)
            {
                if (value.IsUndefined)
                {
                    RemoveLink(link);
                }
                else
                {
                    link.ReplaceWith(value);
                }
            }
            else
            {
                if (!value.IsUndefined)
                {
                    AddChild(String.Format("{0}", idx), value);
                }
            }
        }
Пример #23
0
        public void AddMethod(String funcProto, ScriptCallbackCB callback, Object userdata)
        {
            ScriptLex oldLex = _currentLexer;

            using (_currentLexer = new ScriptLex(funcProto))
            {
                ScriptVar baseVar = Root;

                _currentLexer.Match(ScriptLex.LexTypes.RFunction);
                String funcName = _currentLexer.TokenString;
                _currentLexer.Match(ScriptLex.LexTypes.Id);

                while (_currentLexer.TokenType == (ScriptLex.LexTypes) '.')
                {
                    _currentLexer.Match((ScriptLex.LexTypes) '.');
                    ScriptVarLink link = baseVar.FindChild(funcName);

                    if (link == null)
                    {
                        link = baseVar.AddChild(funcName, new ScriptVar(null, ScriptVar.Flags.Object));
                    }

                    baseVar  = link.Var;
                    funcName = _currentLexer.TokenString;
                    _currentLexer.Match(ScriptLex.LexTypes.Id);
                }

                ScriptVar funcVar = new ScriptVar(null, ScriptVar.Flags.Function | ScriptVar.Flags.Native);
                funcVar.SetCallback(callback, userdata);

                ParseFunctionArguments(funcVar);

                baseVar.AddChild(funcName, funcVar);
            }

            _currentLexer = oldLex;
        }
Пример #24
0
        public void AddMethod(String[] ns, String funcName, String[] args, ScriptCallbackCB callback, Object userdata)
        {
            String    fName   = funcName;
            ScriptVar baseVar = Root;

            if (ns != null)
            {
                int x = 0;
                for (; x < ns.Length; x++)
                {
                    ScriptVarLink link = baseVar.FindChild(ns[x]);

                    if (link == null)
                    {
                        link = baseVar.AddChild(ns[x], new ScriptVar(null, ScriptVar.Flags.Object));
                    }

                    baseVar = link.Var;
                }
            }


            ScriptVar funcVar = new ScriptVar(null, ScriptVar.Flags.Function | ScriptVar.Flags.Native);

            funcVar.SetCallback(callback, userdata);

            //do we have any arguments to create?
            if (args != null)
            {
                foreach (string arg in args)
                {
                    funcVar.AddChildNoDup(arg, null);
                }
            }

            baseVar.AddChild(fName, funcVar);
        }
Пример #25
0
        public void AddNative(string funcDesc, ScriptCallbackCB callbackCB, object userData)
        {
            var oldLex = currentLexer;

            currentLexer = new ScriptLex(funcDesc);

            var baseVar = Root;

            currentLexer.Match(ScriptLex.LexTypes.RFunction);
            var funcName = currentLexer.TokenString;

            currentLexer.Match(ScriptLex.LexTypes.Id);

            while (currentLexer.TokenType == (ScriptLex.LexTypes) '.')
            {
                currentLexer.Match((ScriptLex.LexTypes) '.');

                var link = baseVar.FindChild(funcName);
                if (link == null)
                {
                    link = baseVar.AddChild(funcName, new ScriptVar(null, ScriptVar.Flags.Object));
                }
                baseVar  = link.Var;
                funcName = currentLexer.TokenString;
                currentLexer.Match(ScriptLex.LexTypes.Id);
            }

            var funcVar = new ScriptVar(null, ScriptVar.Flags.Function | ScriptVar.Flags.Native);

            funcVar.SetCallback(callbackCB, userData);
            ParseFunctionArguments(funcVar);

            currentLexer = oldLex;

            baseVar.AddChild(funcName, funcVar);
        }
Пример #26
0
        public ScriptVar MathsOp(ScriptVar b, ScriptLex.LexTypes op)
        {
            ScriptVar a = this;

            char opc = (char)op;

            if (op == ScriptLex.LexTypes.TypeEqual || op == ScriptLex.LexTypes.NTypeEqual)
            {
                bool equal = ((a._flags & Flags.VarTypeMask) == (b._flags & Flags.VarTypeMask));

                if (equal)
                {
                    ScriptVar contents = a.MathsOp(b, ScriptLex.LexTypes.Equal);
                    if (!contents.GetBool())
                    {
                        equal = false;
                    }
                }

                if (op == ScriptLex.LexTypes.TypeEqual)
                {
                    return(new ScriptVar(equal));
                }

                return(new ScriptVar(!equal));
            }

            if (a.IsUndefined && b.IsUndefined)
            {
                if (op == ScriptLex.LexTypes.Equal)
                {
                    return(new ScriptVar(true));
                }
                if (op == ScriptLex.LexTypes.NEqual)
                {
                    return(new ScriptVar(false));
                }

                return(new ScriptVar());
            }

            if ((a.IsNumeric || a.IsUndefined) && (b.IsNumeric || b.IsUndefined))
            {
                if (!a.IsDouble && !b.IsDouble)
                {
                    //ints
                    int da = a.GetInt();
                    int db = b.GetInt();

                    switch (opc)
                    {
                    case '+': return(new ScriptVar(da + db));

                    case '-': return(new ScriptVar(da - db));

                    case '*': return(new ScriptVar(da * db));

                    case '/': return(new ScriptVar(da / db));

                    case '&': return(new ScriptVar(da & db));

                    case '|': return(new ScriptVar(da | db));

                    case '^': return(new ScriptVar(da ^ db));

                    case '%': return(new ScriptVar(da % db));

                    case (char)ScriptLex.LexTypes.Equal: return(new ScriptVar(da == db));

                    case (char)ScriptLex.LexTypes.NEqual: return(new ScriptVar(da != db));

                    case '<': return(new ScriptVar(da < db));

                    case (char)ScriptLex.LexTypes.LEqual: return(new ScriptVar(da <= db));

                    case '>': return(new ScriptVar(da > db));

                    case (char)ScriptLex.LexTypes.GEqual: return(new ScriptVar(da >= db));

                    default: throw new ScriptException("Operation not supported on the Int datatype");
                    }
                }
                else
                {
                    //doubles
                    double da = a.GetDouble();
                    double db = b.GetDouble();

                    switch (opc)
                    {
                    case '+': return(new ScriptVar(da + db));

                    case '-': return(new ScriptVar(da - db));

                    case '*': return(new ScriptVar(da * db));

                    case '/': return(new ScriptVar(da / db));

                    case (char)ScriptLex.LexTypes.Equal: return(new ScriptVar(da == db));

                    case (char)ScriptLex.LexTypes.NEqual: return(new ScriptVar(da != db));

                    case '<': return(new ScriptVar(da < db));

                    case (char)ScriptLex.LexTypes.LEqual: return(new ScriptVar(da <= db));

                    case '>': return(new ScriptVar(da > db));

                    case (char)ScriptLex.LexTypes.GEqual: return(new ScriptVar(da >= db));

                    default: throw new ScriptException("Operation not supported on the Int datatype");
                    }
                }
            }

            if (a.IsArray)
            {
                switch (op)
                {
                case ScriptLex.LexTypes.Equal: return(new ScriptVar(a == b));

                case ScriptLex.LexTypes.NEqual: return(new ScriptVar(a != b));

                default: throw new ScriptException("Operation not supported on the Array datatype");
                }
            }

            if (a.IsObject)
            {
                switch (op)
                {
                case ScriptLex.LexTypes.Equal: return(new ScriptVar(a == b));

                case ScriptLex.LexTypes.NEqual: return(new ScriptVar(a != b));

                default: throw new ScriptException("Operation not supported on the Object datatype");
                }
            }

            string sda = a.GetString();
            string sdb = b.GetString();

            switch (opc)
            {
            case '+': return(new ScriptVar(sda + sdb, Flags.String));

            case (char)ScriptLex.LexTypes.Equal: return(new ScriptVar(sda == sdb));

            case (char)ScriptLex.LexTypes.NEqual: return(new ScriptVar(sda != sdb));

            case '<': return(new ScriptVar(String.CompareOrdinal(sda, sdb) < 0));

            case (char)ScriptLex.LexTypes.LEqual: return(new ScriptVar((String.CompareOrdinal(sda, sdb) < 0) || sda == sdb));

            case '>': return(new ScriptVar(String.CompareOrdinal(sda, sdb) > 0));

            case (char)ScriptLex.LexTypes.GEqual: return(new ScriptVar((String.CompareOrdinal(sda, sdb) > 0) || sda == sdb));

            default: throw new ScriptException("Operation not supported on the String datatype");
            }
        }
        private ScriptVarLink FunctionCall(ref bool execute, ScriptVarLink function, ScriptVar parent)
        {
            if (execute)
            {
                if (!function.Var.IsFunction)
                {
                    throw new ScriptException(String.Format("{0} is not a function", function.Name));
                }

                _currentLexer.Match((ScriptLex.LexTypes) '(');
                ScriptVar functionRoot = new ScriptVar(null, ScriptVar.Flags.Function);

                if (parent != null)
                {
                    functionRoot.AddChildNoDup("this", parent);
                }

                ScriptVarLink v = function.Var.FirstChild;
                while (v != null)
                {
                    ScriptVarLink value = Base(ref execute);
                    if (value.Var.IsBasic)
                    {
                        //pass by val
                        functionRoot.AddChild(v.Name, value.Var.DeepCopy());
                    }
                    else
                    {
                        //pass by ref
                        functionRoot.AddChild(v.Name, value.Var);
                    }

                    if (_currentLexer.TokenType != (ScriptLex.LexTypes) ')')
                    {
                        _currentLexer.Match((ScriptLex.LexTypes) ',');
                    }

                    v = v.Next;
                }

                _currentLexer.Match((ScriptLex.LexTypes) ')');

                ScriptVarLink returnVarLink = functionRoot.AddChild(ScriptVar.ReturnVarName, null);

                _scopes.Push(functionRoot);

                _callStack.Push(String.Format("{0} from line {1}", function.Name, _currentLexer.LineNumber));

                if (function.Var.IsNative)
                {
                    ScriptCallbackCB func = function.Var.GetCallback();
                    if (func != null)
                    {
                        func(functionRoot, function.Var.GetCallbackUserData(), parent);
                    }
                }
                else
                {
                    ScriptException ex     = null;
                    ScriptLex       oldLex = _currentLexer;
                    ScriptLex       newLex = new ScriptLex(function.Var.GetString());
                    _currentLexer = newLex;

                    try
                    {
                        Block(ref execute);

                        execute = true;
                    }
                    catch (ScriptException e)
                    {
                        ex = e;
                    }

                    _currentLexer = oldLex;

                    if (ex != null)
                    {
                        throw ex;
                    }
                }

                _callStack.Pop();
                _scopes.Pop();

                ScriptVarLink returnVar = new ScriptVarLink(returnVarLink.Var, null);
                functionRoot.RemoveLink(returnVarLink);

                return(returnVar);
            }

            //not executing the function, just parsing it out
            _currentLexer.Match((ScriptLex.LexTypes) '(');

            while (_currentLexer.TokenType != (ScriptLex.LexTypes) ')')
            {
                Base(ref execute);

                if (_currentLexer.TokenType != (ScriptLex.LexTypes) ')')
                {
                    _currentLexer.Match((ScriptLex.LexTypes) ',');
                }
            }

            _currentLexer.Match((ScriptLex.LexTypes) ')');

            if (_currentLexer.TokenType == (ScriptLex.LexTypes) '{')             //WTF?
            {
                Block(ref execute);
            }

            return(function);
        }
        private void Statement(ref bool execute)
        {
            if (_currentLexer.TokenType == ScriptLex.LexTypes.Id ||
                _currentLexer.TokenType == ScriptLex.LexTypes.Int ||
                _currentLexer.TokenType == ScriptLex.LexTypes.Float ||
                _currentLexer.TokenType == ScriptLex.LexTypes.Str ||
                _currentLexer.TokenType == (ScriptLex.LexTypes) '-')
            {
                //execite a basic statement
                Base(ref execute);
                _currentLexer.Match((ScriptLex.LexTypes) ';');
            }
            else if (_currentLexer.TokenType == (ScriptLex.LexTypes) '{')
            {
                //code block
                Block(ref execute);
            }
            else if (_currentLexer.TokenType == (ScriptLex.LexTypes) ';')
            {
                //allow for multiple semi colon such as ;;;
                _currentLexer.Match((ScriptLex.LexTypes) ';');
            }
            else if (_currentLexer.TokenType == ScriptLex.LexTypes.RVar)
            {
                //creating variables
                //TODO: make this less shit

                _currentLexer.Match(ScriptLex.LexTypes.RVar);

                while (_currentLexer.TokenType != (ScriptLex.LexTypes) ';')
                {
                    ScriptVarLink a = null;
                    if (execute)
                    {
                        a = _scopes.Peek().FindChildOrCreate(_currentLexer.TokenString);
                    }

                    _currentLexer.Match(ScriptLex.LexTypes.Id);

                    //get through the dots
                    while (_currentLexer.TokenType == (ScriptLex.LexTypes) '.')
                    {
                        _currentLexer.Match((ScriptLex.LexTypes) '.');
                        if (execute)
                        {
                            ScriptVarLink aLast = a;
                            if (aLast != null)
                            {
                                a = aLast.Var.FindChildOrCreate(_currentLexer.TokenString);
                            }
                        }

                        _currentLexer.Match(ScriptLex.LexTypes.Id);
                    }

                    //initialiser
                    if (_currentLexer.TokenType == (ScriptLex.LexTypes) '=')
                    {
                        _currentLexer.Match((ScriptLex.LexTypes) '=');
                        ScriptVarLink varLink = Base(ref execute);
                        if (execute)
                        {
                            if (a != null)
                            {
                                a.ReplaceWith(varLink);
                            }
                        }
                    }

                    if (_currentLexer.TokenType != (ScriptLex.LexTypes) ';')
                    {
                        _currentLexer.Match((ScriptLex.LexTypes) ',');
                    }
                }

                _currentLexer.Match((ScriptLex.LexTypes) ';');
            }
            else if (_currentLexer.TokenType == ScriptLex.LexTypes.RIf)
            {
                //if condition
                _currentLexer.Match(ScriptLex.LexTypes.RIf);
                _currentLexer.Match((ScriptLex.LexTypes) '(');
                ScriptVarLink varLink = Base(ref execute);
                _currentLexer.Match((ScriptLex.LexTypes) ')');

                bool condition = execute && varLink.Var.GetBool();
                bool noExecute = false;
                if (condition)
                {
                    Statement(ref execute);
                }
                else
                {
                    Statement(ref noExecute);
                }

                if (_currentLexer.TokenType == ScriptLex.LexTypes.RElse)
                {
                    //else part of an if
                    _currentLexer.Match(ScriptLex.LexTypes.RElse);

                    if (condition)
                    {
                        Statement(ref noExecute);
                    }
                    else
                    {
                        Statement(ref execute);
                    }
                }
            }
            else if (_currentLexer.TokenType == ScriptLex.LexTypes.RWhile)
            {
                //while loop
                _currentLexer.Match(ScriptLex.LexTypes.RWhile);
                _currentLexer.Match((ScriptLex.LexTypes) '(');

                Int32         whileConditionStart = _currentLexer.TokenStart;
                ScriptVarLink condition           = Base(ref execute);
                bool          loopCondition       = execute && condition.Var.GetBool();

                ScriptLex whileCond = _currentLexer.GetSubLex(whileConditionStart);
                _currentLexer.Match((ScriptLex.LexTypes) ')');

                Int32 whileBodyStart = _currentLexer.TokenStart;

                Statement(ref loopCondition);

                ScriptLex whileBody = _currentLexer.GetSubLex(whileBodyStart);
                ScriptLex oldLex    = _currentLexer;

                //TODO: possible maximum itteration limit?
                while (loopCondition)
                {
                    whileCond.Reset();

                    _currentLexer = whileCond;

                    condition = Base(ref execute);

                    loopCondition = condition.Var.GetBool();

                    if (loopCondition)
                    {
                        whileBody.Reset();
                        _currentLexer = whileBody;
                        Statement(ref execute);
                    }
                }

                _currentLexer = oldLex;
            }
            else if (_currentLexer.TokenType == ScriptLex.LexTypes.RFor)
            {
                //for loop
                _currentLexer.Match(ScriptLex.LexTypes.RFor);
                _currentLexer.Match((ScriptLex.LexTypes) '(');

                Statement(ref execute);                 //init

                int           forConditionStart = _currentLexer.TokenStart;
                ScriptVarLink condition         = Base(ref execute);
                bool          noExecute         = false;
                bool          loopCondition     = execute && condition.Var.GetBool();

                ScriptLex forCondition = _currentLexer.GetSubLex(forConditionStart);

                _currentLexer.Match((ScriptLex.LexTypes) ';');

                int forIterStart = _currentLexer.TokenStart;

                Base(ref noExecute);

                ScriptLex forIter = _currentLexer.GetSubLex(forIterStart);

                _currentLexer.Match((ScriptLex.LexTypes) ')');

                int forBodyStart = _currentLexer.TokenStart;

                if (loopCondition)
                {
                    Statement(ref execute);
                }
                else
                {
                    Statement(ref noExecute);
                }

                ScriptLex forBody = _currentLexer.GetSubLex(forBodyStart);
                ScriptLex oldLex  = _currentLexer;
                if (loopCondition)
                {
                    forIter.Reset();
                    _currentLexer = forIter;

                    Base(ref execute);
                }

                //TODO: limit number of iterations?
                while (execute && loopCondition)
                {
                    forCondition.Reset();
                    _currentLexer = forCondition;

                    condition = Base(ref execute);

                    loopCondition = condition.Var.GetBool();

                    if (execute && loopCondition)
                    {
                        forBody.Reset();
                        _currentLexer = forBody;

                        Statement(ref execute);
                    }

                    if (execute && loopCondition)
                    {
                        forIter.Reset();
                        _currentLexer = forIter;

                        Base(ref execute);
                    }
                }

                _currentLexer = oldLex;
            }
            else if (_currentLexer.TokenType == ScriptLex.LexTypes.RReturn)
            {
                _currentLexer.Match(ScriptLex.LexTypes.RReturn);

                ScriptVarLink res = null;
                if (_currentLexer.TokenType != (ScriptLex.LexTypes) ';')
                {
                    res = Base(ref execute);
                }
                if (execute)
                {
                    ScriptVarLink resultVar = _scopes.Peek().FindChild(ScriptVar.ReturnVarName);
                    if (resultVar != null)
                    {
                        resultVar.ReplaceWith(res);
                    }
                    else
                    {
                        //return statement outside of function???
                        System.Diagnostics.Trace.TraceWarning("Return statement outside of a function, what is going on?");
                    }
                }

                execute = false;
                _currentLexer.Match((ScriptLex.LexTypes) ';');
            }
            else if (_currentLexer.TokenType == ScriptLex.LexTypes.RFunction)
            {
                //function
                ScriptVarLink funcVar = ParseFunctionDefinition();
                if (execute)
                {
                    if (funcVar.Name == String.Empty)
                    {
                        //functions must have a name at statement level
                    }
                    else
                    {
                        ScriptVar v = _scopes.Peek();
                        v.AddChildNoDup(funcVar.Name, funcVar.Var);
                    }
                }
            }
            else
            {
                _currentLexer.Match(ScriptLex.LexTypes.Eof);
            }
        }
Пример #29
0
        private ScriptVarLink FunctionCall(ref bool execute, ScriptVarLink function, ScriptVar parent)
        {
            if (execute)
            {
                if (!function.Var.IsFunction)
                {
                    throw new ScriptException(String.Format("{0} is not a function", function.Name));
                }

                currentLexer.Match((ScriptLex.LexTypes) '(');
                var functionRoot = new ScriptVar(null, ScriptVar.Flags.Function);

                if (parent != null)
                {
                    functionRoot.AddChildNoDup("this", parent);
                }

                var v = function.Var.FirstChild;
                while (v != null)
                {
                    var value = Base(ref execute);
                    if (execute)
                    {
                        if (value.Var.IsBasic)
                        {
                            //pass by val
                            functionRoot.AddChild(v.Name, value.Var.DeepCopy());
                        }
                        else
                        {
                            //pass by ref
                            functionRoot.AddChild(v.Name, value.Var);
                        }
                    }

                    if (currentLexer.TokenType != (ScriptLex.LexTypes) ')')
                    {
                        currentLexer.Match((ScriptLex.LexTypes) ',');
                    }

                    v = v.Next;
                }

                currentLexer.Match((ScriptLex.LexTypes) ')');

                var returnVarLink = functionRoot.AddChild(ScriptVar.ReturnVarName, null);

                scopes.PushBack(functionRoot);

                //callStack.PushBack(string.Format("{0} from line {1}", function.Name, currentLexer.LineNumber));

                callStack.Push(function);

                if (function.Var.IsNative)
                {
                    var func = function.Var.GetCallback();
                    func?.Invoke(functionRoot, function.Var.GetCallbackUserData());
                }
                else
                {
                    var oldLex = currentLexer;
                    var newLex = new ScriptLex(function.Var.String);
                    currentLexer = newLex;

                    try
                    {
                        Block(ref execute);

                        execute = true;
                    }
                    catch
                    {
                        throw;
                    }
                    finally
                    {
                        currentLexer = oldLex;
                    }
                }

                callStack.Pop();
                scopes.PopBack();

                var returnVar = new ScriptVarLink(returnVarLink.Var, null);
                functionRoot.RemoveLink(returnVarLink);

                return(returnVar);
            }
            else
            {
                //not executing the function, just parsing it out
                currentLexer.Match((ScriptLex.LexTypes) '(');

                while (currentLexer.TokenType != (ScriptLex.LexTypes) ')')
                {
                    Base(ref execute);

                    if (currentLexer.TokenType != (ScriptLex.LexTypes) ')')
                    {
                        currentLexer.Match((ScriptLex.LexTypes) ',');
                    }
                }

                currentLexer.Match((ScriptLex.LexTypes) ')');

                if (currentLexer.TokenType == (ScriptLex.LexTypes) '{') //WTF?
                {
                    Block(ref execute);
                }

                return(function);
            }
        }
Пример #30
0
 public void SetReturnVar(ScriptVar var)
 {
     FindChildOrCreate(ReturnVarName).ReplaceWith(var);
 }