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); }
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); } } }
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); } }
private void Statement(ref bool execute) { 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 || currentLexer.TokenType == ScriptLex.LexTypes.RConst) { //creating variables //TODO: make this less shit var readOnly = currentLexer.TokenType == ScriptLex.LexTypes.RConst; currentLexer.Match(currentLexer.TokenType); while (currentLexer.TokenType != (ScriptLex.LexTypes) ';') { ScriptVarLink a = null; if (execute) { a = scopes.Back().FindChildOrCreate(currentLexer.TokenString, ScriptVar.Flags.Undefined, readOnly); } currentLexer.Match(ScriptLex.LexTypes.Id); //get through the dots while (currentLexer.TokenType == (ScriptLex.LexTypes) '.') { currentLexer.Match((ScriptLex.LexTypes) '.'); if (execute) { var 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) '='); var 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) '('); var varLink = Base(ref execute); currentLexer.Match((ScriptLex.LexTypes) ')'); bool condition = execute && varLink.Var.Bool; 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) '('); var whileConditionStart = currentLexer.TokenStart; var noExecute = false; var condition = Base(ref execute); var loopCondition = execute && condition.Var.Bool; var whileCond = currentLexer.GetSubLex(whileConditionStart); currentLexer.Match((ScriptLex.LexTypes) ')'); var whileBodyStart = currentLexer.TokenStart; if (loopCondition) { Statement(ref execute); } else { Statement(ref noExecute); } var whileBody = currentLexer.GetSubLex(whileBodyStart); var oldLex = currentLexer; //TODO: possible maximum itteration limit? while (loopCondition) { whileCond.Reset(); currentLexer = whileCond; condition = Base(ref execute); loopCondition = execute && condition.Var.Bool; 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 var forConditionStart = currentLexer.TokenStart; var condition = Base(ref execute); var noExecute = false; var loopCondition = execute && condition.Var.Bool; var forCondition = currentLexer.GetSubLex(forConditionStart); currentLexer.Match((ScriptLex.LexTypes) ';'); var forIterStart = currentLexer.TokenStart; Base(ref noExecute); var forIter = currentLexer.GetSubLex(forIterStart); currentLexer.Match((ScriptLex.LexTypes) ')'); var forBodyStart = currentLexer.TokenStart; if (loopCondition) { Statement(ref execute); } else { Statement(ref noExecute); } var forBody = currentLexer.GetSubLex(forBodyStart); var 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.Bool; 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) { var resultVar = scopes.Back().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 var funcVar = ParseFunctionDefinition(); if (execute) { if (funcVar.Name == string.Empty) { //functions must have a name at statement level } else { var v = scopes.Back(); v.AddChildNoDup(funcVar.Name, funcVar.Var); } } } else if (currentLexer.TokenType == ScriptLex.LexTypes.RTry) { var tryBlock = ParseDefinition(ScriptLex.LexTypes.RTry); ScriptVarLink catchBlock = null, finallyBlock = null; var originalLexer = currentLexer; if (currentLexer.TokenType == ScriptLex.LexTypes.RCatch) { catchBlock = ParseDefinition(ScriptLex.LexTypes.RCatch); } if (currentLexer.TokenType == ScriptLex.LexTypes.RFinally) { finallyBlock = ParseDefinition(ScriptLex.LexTypes.RFinally); } try { var oldLex = currentLexer; var newLex = new ScriptLex(tryBlock.Var.String); currentLexer = newLex; Block(ref execute); execute = true; currentLexer = oldLex; } catch (JITException ex) { if (catchBlock != null) { var catchScope = new ScriptVar(null, ScriptVar.Flags.Object); var v = catchBlock?.Var?.FirstChild; if (v != null) { catchScope.AddChild(v.Name, ex.VarObj); } var oldLex = currentLexer; var newLex = new ScriptLex(catchBlock.Var.String); currentLexer = newLex; scopes.PushBack(catchScope); Block(ref execute); scopes.PopBack(); execute = true; currentLexer = oldLex; } else { throw new ScriptException(ex.Message, ex); } } finally { if (finallyBlock != null) { var oldLex = currentLexer; var newLex = new ScriptLex(finallyBlock.Var.String); currentLexer = newLex; Block(ref execute); execute = true; currentLexer = oldLex; } } currentLexer = originalLexer; } else if (currentLexer.TokenType == ScriptLex.LexTypes.RThrow) { currentLexer.Match(ScriptLex.LexTypes.RThrow); ScriptVar message = new ScriptVar(); if (currentLexer.TokenType == (ScriptLex.LexTypes) ';') { currentLexer.Match((ScriptLex.LexTypes) ';'); } else { var res = Base(ref execute); message = res.Var; } throw new JITException(message); } else { //execute a basic statement Base(ref execute); currentLexer.Match((ScriptLex.LexTypes) ';'); } }