public LSLVariableDeclarationNode ResolveVariable(string name) { var local = (from scope in _scopeVariables where scope.ContainsKey(name) select scope[name]).FirstOrDefault(); if (local != null) { return(local); } if (_parameterScopeVariables.ContainsKey(name)) { var x = _parameterScopeVariables[name]; return(x); } if (GlobalVariables.ContainsKey(name)) { return(GlobalVariables[name]); } return(null); }
public void AddVariable(string name, string content) { if (!GlobalVariables.ContainsKey(name.ToLower()) && !LocalVariables.ContainsKey(name.ToLower())) { var newVar = new Variable(name, content); LocalVars.Add(newVar.Name.ToLower(), newVar); } }
public void SetVariableValue(string variableName, int targetValue) { if (GlobalVariables.ContainsKey(variableName)) { GlobalVariables[variableName] = targetValue; } else { GlobalVariables.Add(variableName, targetValue); } }
/// <summary> /// Determines if given the current scoping state, can a variable be defined without causing a conflict /// </summary> /// <param name="name">name of the variable</param> /// <param name="scope">the scope level of the variable to be defined</param> /// <returns>whether or not the variable can be defined without conflict</returns> public bool CanVariableBeDefined(string name, LSLVariableScope scope) { if (scope == LSLVariableScope.Global) { return(!GlobalVariables.ContainsKey(name)); } if (scope == LSLVariableScope.Local) { return(!_scopeVariables.Peek().ContainsKey(name)); } return(true); }
public string RenameVariable(string oldName, string newName) { string currentVarName = oldName; if (!GlobalVariables.ContainsKey(newName.ToLower()) && !LocalVariables.ContainsKey(newName.ToLower())) { LocalVars.Add(newName.ToLower(), LocalVariables[oldName.ToLower()]); LocalVars[newName.ToLower()].Name = newName; RemoveVariable(oldName.ToLower()); currentVarName = newName; } return(currentVarName); }
public void AddValueToGlobalContext(string name, Value val) { //On the other hand global variables are not constant if (Parent == null) { if (GlobalVariables.ContainsKey(name)) { GlobalVariables.Remove(name); } GlobalVariables.Add(name, val); } else { Parent.AddValueToGlobalContext(name, val); } }
public dynamic RunParagraph(string paragraphName, FiMObject paramObject = null) { if (!Paragraphs.ContainsKey(paragraphName)) { throw new Exception("Invalid Paragraph name"); } FiMParagraph paragraph = Paragraphs[paragraphName]; // Empty function if (paragraph.Lines.Count() == 0) { return(null); } List <string> paragraphLines = new List <string>(); paragraphLines.AddRange(paragraph.Lines); for (int i = 0; i < paragraphLines.Count(); i++) { if (!string.IsNullOrWhiteSpace(paragraphLines[i]) && !Regex.IsMatch(paragraphLines[i], @"( |\t)*(P\.)(P\.)*S\.($| )")) { string nl = paragraphLines[i]; if (nl.StartsWith(" ")) { nl = nl.Remove(0, " ".Length); } else if (nl.StartsWith("\t")) { nl = nl.Remove(0, 1); } else { throw new Exception("Invalid indentation at line '" + paragraph.FirstLineIndex + i + "'"); } paragraphLines[i] = nl; } } // Dictionary <string, FiMObject> LocalVariables = new Dictionary <string, FiMObject>(); if (paragraph.ParameterName != null) { LocalVariables.Add(paragraph.ParameterName, paramObject); } int lineIndex = 1; int skipTo = -1; string[] pLArray = paragraphLines.ToArray(); foreach (string line in paragraphLines) { if (lineIndex <= skipTo) { lineIndex++; continue; } //Console.WriteLine(line); if (!string.IsNullOrWhiteSpace(line) && !Regex.IsMatch(line, @"( |\t)*(P\.)(P\.)*S\.($| )")) { NetFIMMethods.FiMMethodOut method; try { method = NetFIMMethods.ScanMethod(this, line, pLArray, paragraph.FirstLineIndex + lineIndex + 1, lineIndex, paragraph, variables: NetFIMMethods.MergeLocalAndGlobalVariables(GlobalVariables, LocalVariables), paragraphs: Paragraphs); } catch (Exception e) { throw e; } // switch (method.methodType) { case "WRITE-RUN": { if (!Paragraphs.ContainsKey(method.outArgs["Method Name"])) { throw new Exception("[" + paragraph.FirstLineIndex + lineIndex + "] Paragraph '" + method.outArgs["Method Name"] + "' doesn't exist"); } if (method.outArgs["doWrite"] == true) { NetFIMMethods.WriteToScreen(RunParagraph(method.outArgs["Method Name"], method.outArgs["Parameter"])); } else { RunParagraph(method.outArgs["Method Name"], method.outArgs["Parameter"]); } } break; case "MAKE-VARIABLE": { LocalVariables.Add(method.outArgs["Variable Name"], method.outArgs["Variable"]); } break; case "MODIFY-ARRAY": { // In the case of Paragraph ScanMethod, we either put it on the Global or Local list. if (GlobalVariables.ContainsKey(method.outArgs["Variable Name"])) { var ol = GlobalVariables[method.outArgs["Variable Name"]].GetActualValue(); ol[method.outArgs["Slot"]] = method.outArgs["New Value"]; GlobalVariables[method.outArgs["Variable Name"]].Value = (object)ol; } else { var ol = LocalVariables[method.outArgs["Variable Name"]].GetActualValue(); ol[method.outArgs["Slot"]] = method.outArgs["New Value"]; LocalVariables[method.outArgs["Variable Name"]].Value = (object)ol; } } break; case "MODIFY-VARIABLE": { if (GlobalVariables.ContainsKey(method.outArgs["Variable Name"])) { GlobalVariables[method.outArgs["Variable Name"]] = method.outArgs["New Value"]; } else { LocalVariables[method.outArgs["Variable Name"]] = method.outArgs["New Value"]; } } break; case "VARIABLE-INCREMENT": { if (GlobalVariables.ContainsKey(method.outArgs["Variable Name"])) { float oldValue = GlobalVariables[method.outArgs["Variable Name"]].GetActualValue(); oldValue++; GlobalVariables[method.outArgs["Variable Name"]].Value = (object)oldValue; } else { float oldValue = LocalVariables[method.outArgs["Variable Name"]].GetActualValue(); oldValue++; LocalVariables[method.outArgs["Variable Name"]].Value = (object)oldValue; } } break; case "VARIABLE-DECREMENT": { if (GlobalVariables.ContainsKey(method.outArgs["Variable Name"])) { float oldValue = GlobalVariables[method.outArgs["Variable Name"]].GetActualValue(); oldValue--; GlobalVariables[method.outArgs["Variable Name"]].Value = (object)oldValue; } else { float oldValue = LocalVariables[method.outArgs["Variable Name"]].GetActualValue(); oldValue--; LocalVariables[method.outArgs["Variable Name"]].Value = (object)oldValue; } } break; case "WHILE": { skipTo = lineIndex + method.outArgs["Skip"] + 1; // Dictionary <string, FiMObject> changed = method.outArgs["Changed Variables"]; if (changed.Count() > 0) { changed.Keys.ToList().ForEach(x => { FiMObject obj = changed[x]; if (GlobalVariables.ContainsKey(x)) { GlobalVariables[x] = obj; } else { LocalVariables[x] = obj; } }); } if (method.outArgs.ContainsKey("Returned Variable")) { return(method.outArgs["Returned Variable"]); } } break; case "IF-ELSE": { skipTo = lineIndex + method.outArgs["Skip"] + 1; // if (method.outArgs.ContainsKey("Statement")) { NetFIMMethods.FiMStatement statement = method.outArgs["Statement"]; statement.changedVariables.Keys.ToList().ForEach(x => { FiMObject obj = statement.changedVariables[x]; if (GlobalVariables.ContainsKey(x)) { GlobalVariables[x] = obj; } else { LocalVariables[x] = obj; } }); if (statement.hasReturned) { return(statement.returnedObject); } } } break; case "RETURN": return(method.outArgs["Variable"]); case "WRITE-WRITE": default: break; } } lineIndex++; } return(null); }
public bool GlobalVariableDefined(string name) { return(GlobalVariables.ContainsKey(name)); }
//gets the next value Value NextValue(FunctionFrame current) { Value val = Value.Null; if (lastToken == Token.Value) //raw value { val = lexer.TokenValue; ReadNextToken(); } else if (lastToken == Token.Identifier) { if (GlobalVariables.ContainsKey(lexer.TokenIdentifier)) //see if it's a variable { string vid = lexer.TokenIdentifier; if (PeekNextToken() == Token.OpenBracket) { ReadNextToken(); ReadNextToken(); Value v = EvaluateNextExpression(0, current); if (v == null) { return(null); } if (v.Type != ValueType.Double) { throw new Exception("Indicie's must be of type double."); } if (GlobalVariables[vid].Type == ValueType.String) { val = new Value(GlobalVariables[vid].String[(int)v.Double]); } else if (GlobalVariables[vid].Type == ValueType.Array) { val = GlobalVariables[vid].Array[(int)v.Double]; } else { throw new Exception("Only arrays and strings can be indexed."); } MatchToken(Token.CloseBracket); } else { val = GlobalVariables[vid]; } } else if (functions.ContainsKey(lexer.TokenIdentifier) || builtInFunctions.ContainsKey(lexer.TokenIdentifier)) //see if it's a function { ReadNextToken(); MatchToken(Token.OpenParenthesis); string fid = lexer.TokenIdentifier; int aid = lexer.Position.Index; List <Value> arguments = new List <Value>(); int argno = 0; //current argument index while (lastToken != Token.CloseParenthesis) //collect all the arguments { ReadNextToken(); if (lastToken == Token.Comma || lastToken == Token.CloseParenthesis) { continue; //just skip the comma's } else { if (argno >= arguments.Count) { Value v = EvaluateNextExpression(0, current); if (v == null) { return(null); //this is how to escape the recursive function when a function needs to be evaluated through the main loop first } arguments.Add(v); } else { int paramCount = 0; //skip open params, close params till it balances out do { ReadNextToken(); if (lastToken == Token.OpenParenthesis) { paramCount++; } else if (lastToken == Token.CloseParenthesis) { paramCount--; } }while (paramCount >= 0 && lastToken != Token.Comma); } } argno++; } //bracket_counter++; if (current.functionResults.Count > 0) { Value value = current.functionResults.Dequeue(); current.processedFunctionResults.Enqueue(value); ReadNextToken(); return(value); } if (functions.ContainsKey(fid)) { if (CallStack.Count > 1000) { throw new StackOverflowException("The call stack's size has exceeded the 1000 item limit."); } FunctionFrame f = functions[fid].CloneTemplate(); f.SetArguments(arguments); f.ReturnPosition = (Marker)keywordMarker.Clone(); f.ReturnResult = Value.Null; CallStack.Push(f); lexer.ShiftCurrentPosition(functions[fid].StartPosition); ReadNextToken(); return(null); } else { val = builtInFunctions[fid].Invoke(arguments); ReadNextToken(); if (val == null) { return(null); } current.processedFunctionResults.Enqueue(val); return(val); } } else { val = null; FunctionFrame function = GetCurrentContext(); if (function.LocalVariables.ContainsKey(lexer.TokenIdentifier)) { string fid = lexer.TokenIdentifier; if (PeekNextToken() == Token.OpenBracket) { ReadNextToken(); ReadNextToken(); Value v = EvaluateNextExpression(0, current); if (v == null) { return(null); } if (v.Type != ValueType.Double) { throw new Exception("Indicie's must be of type double."); } if (function.LocalVariables[fid].Type == ValueType.String) { val = new Value(function.LocalVariables[fid].String[(int)v.Double]); } else if (function.LocalVariables[fid].Type == ValueType.Array) { val = function.LocalVariables[fid].Array[(int)v.Double]; } else { throw new Exception("Only arrays and strings can be indexed."); } MatchToken(Token.CloseBracket); } else { val = function.LocalVariables[fid]; } } if (val == null) { throw new UnidentifiedTokenExcepion(); } } ReadNextToken(); } else if (lastToken == Token.OpenParenthesis) //it's an expression { ReadNextToken(); val = EvaluateNextExpression(0, current); //call the evaluate function if (val == null) { return(null); } MatchToken(Token.CloseParenthesis); ReadNextToken(); } else if (lastToken == Token.OpenBracket) { List <Value> values = new List <Value>(); while (lastToken != Token.CloseBracket) //collect all the arguments { ReadNextToken(); if (lastToken == Token.Comma || lastToken == Token.CloseBracket) { continue; //just skip the comma's } else { Value v = EvaluateNextExpression(0, current); if (v == null) { return(null); //this is how to escape the recursive function when a function needs to be evaluated through the main loop first } values.Add(v); } } ReadNextToken(); val = new Value(values); } //this part handles uniary operations else { Token tok = lastToken; ReadNextToken(); if (tok == Token.Refrence) { val = new Value(lexer.TokenIdentifier); } else { Value val1 = NextValue(current); if (val1 == null) { return(null); } val = val1.PerformUniaryOperation(tok); } } return(val); }
//executes a single statement void ExecuteNextStatement() { Token keyword = lastToken; expressionMarker = (Marker)lexer.Position.Clone(); ReadNextToken(); Value expr; IfElifFrame prevElifFrame; FunctionFrame functionFrame; switch (keyword) { case Token.Global: MatchToken(Token.Identifier); GlobalVariables.Add(lexer.TokenIdentifier, Value.Null); ReadNextToken(); break; case Token.Abstract: MatchToken(Token.Identifier); GlobalVariables.Add(lexer.TokenIdentifier, new Value(new Expression(lexer.TokenIdentifier))); ReadNextToken(); break; case Token.Identifier: string id = lexer.TokenIdentifier; if (lastToken == Token.Set) { if (ReadOnlyVariables.Contains(id)) { throw new Exception("FastCode cannot write to a read only variable."); } ReadNextToken(); expr = EvaluateNextExpression(); if (expr == null) { return; } if (GlobalVariables.ContainsKey(id)) { GlobalVariables[id] = expr; break; } else { functionFrame = GetCurrentContext(); if (functionFrame.LocalVariables.ContainsKey(id)) { functionFrame.LocalVariables[id] = expr; } else { functionFrame.LocalVariables.Add(id, expr); } } break; } else if (lastToken == Token.OpenParenthesis) { if (functions.ContainsKey(id) || builtInFunctions.ContainsKey(id)) { lexer.ShiftCurrentPosition(keywordMarker); ReadNextToken(); EvaluateNextExpression(); break; } } else if (lastToken == Token.OpenBracket) { ReadNextToken(); Value indexValue = EvaluateNextExpression(); if (indexValue == null) { return; } if (indexValue.Type != ValueType.Double) { throw new Exception("Indicie's must be of type double."); } MatchToken(Token.CloseBracket); ReadNextToken(); MatchToken(Token.Set); ReadNextToken(); Value setval = EvaluateNextExpression(); if (setval == null) { return; } if (GlobalVariables.ContainsKey(id)) { if (GlobalVariables[id].Type == ValueType.Array) { GlobalVariables[id].Array[(int)indexValue.Double] = setval; break; } else if (GlobalVariables[id].Type == ValueType.String) { if (setval.Type != ValueType.Character) { throw new Exception("Strings can only index characters."); } char[] str = GlobalVariables[id].String.ToCharArray(); str[(int)indexValue.Double] = setval.Character; GlobalVariables[id] = new Value(new string(str)); break; } } else { functionFrame = GetCurrentContext(); if (functionFrame.LocalVariables[id].Type == ValueType.Array) { functionFrame.LocalVariables[id].Array[(int)indexValue.Double] = setval; break; } else if (functionFrame.LocalVariables[id].Type == ValueType.String) { if (setval.Type != ValueType.Character) { throw new Exception("Strings can only index characters."); } char[] str = functionFrame.LocalVariables[id].String.ToCharArray(); str[(int)indexValue.Double] = setval.Character; functionFrame.LocalVariables[id] = new Value(new string(str)); break; } } } throw new Exception("Identifier \"" + id + "\" cannot stand alone without a keyword."); case Token.Break: int i = 0; while (!(CallStack.Peek().GetType() == typeof(WhileFrame) || CallStack.Peek().GetType() == typeof(ForFrame))) { if (CallStack.Peek().GetType() == typeof(FunctionFrame)) { throw new UnexpectedStatementException(Token.Break.ToString()); } i++; prevCallFrame = CallStack.Pop(); } prevCallFrame = CallStack.Pop(); SkipCallFrame(i); break; case Token.Return: functionFrame = null; int j = 0; while (CallStack.Count != 0) { if (CallStack.Peek().GetType() == typeof(FunctionFrame)) { functionFrame = (FunctionFrame)CallStack.Pop(); if (functionFrame.Identifier == "MAINSTRUCTURE") { throw new Exception("Only functions may return values."); } break; } CallStack.Pop(); j++; } if (PeekNextToken() != Token.Newline && PeekNextToken() != Token.Semicolon) { CallStack.Push(functionFrame); expr = EvaluateNextExpression(); if (expr == null) { return; } functionFrame = (FunctionFrame)CallStack.Pop(); functionFrame.ReturnResult = expr; } CallStack.Push(functionFrame); SkipCallFrame(j, true); ExecuteNextStatement(); break; case Token.Stop: Exit = true; return; case Token.Import: MatchToken(Token.Value); if (lexer.TokenValue.Type != ValueType.String) { throw new Exception("Expected string, got " + lexer.TokenValue.Type); } ReadNextToken(); break; case Token.EndOfFile: Exit = true; return; case Token.If: IfElifFrame ifFrame = new IfElifFrame(); expr = EvaluateNextExpression(); if (expr == null) { return; } ifFrame.Result = (expr.PerformBinaryOperation(Token.Equals, new Value(0)).Double == 1); //not not the actual result, it just checks if the condition failed so it can skip that section. Kinda misleading if you didn't know - just refer to the assertion token's case. CallStack.Push(ifFrame); readTillCallFrameStart(); //read till open bracket if (ifFrame.Result == true) //skip till close bracket. { SkipCallFrame(); prevCallFrame = CallStack.Pop(); } break; case Token.Else: //not if results are inverted if (prevCallFrame.GetType() != typeof(IfElifFrame)) { throw new UnexpectedStatementException(keyword.ToString()); } prevElifFrame = (IfElifFrame)prevCallFrame; if (prevElifFrame.Result == true) //skip all the crap { CallStack.Push(new ElseFrame()); readTillCallFrameStart(); } else if (prevElifFrame.Result == false) { CallStack.Push(new ElseFrame()); readTillCallFrameStart(); SkipCallFrame(); prevCallFrame = CallStack.Pop(); } break; case Token.Elif: if (prevCallFrame.GetType() != typeof(IfElifFrame)) { throw new UnexpectedStatementException(keyword.ToString()); } IfElifFrame elifFrame = new IfElifFrame(); prevElifFrame = (IfElifFrame)prevCallFrame; if (prevElifFrame.Result == true) { expr = EvaluateNextExpression(); if (expr == null) { return; } elifFrame.Result = (expr.PerformBinaryOperation(Token.Equals, new Value(0)).Double == 1); CallStack.Push(elifFrame); readTillCallFrameStart(); if (elifFrame.Result == true) { SkipCallFrame(); prevCallFrame = CallStack.Pop(); } } else { CallStack.Push(elifFrame); readTillCallFrameStart(); SkipCallFrame(); prevCallFrame = CallStack.Pop(); } break; case Token.While: WhileFrame whileFrame = new WhileFrame(); whileFrame.ExpressionMarker = (Marker)expressionMarker.Clone(); expr = EvaluateNextExpression(); if (expr == null) { return; } CallStack.Push(whileFrame); readTillCallFrameStart(); if (expr.PerformBinaryOperation(Token.Equals, new Value(0)).Double == 1) { SkipCallFrame(); prevCallFrame = CallStack.Pop(); } break; case Token.For: ForFrame forFrame = new ForFrame(); MatchToken(Token.Identifier); forFrame.IndexerIdentifier = lexer.TokenIdentifier; ReadNextToken(); MatchToken(Token.In); ReadNextToken(); expr = EvaluateNextExpression(); if (expr == null) { return; } if (expr.Type == ValueType.Array) { forFrame.Values = expr.Array; } else if (expr.Type == ValueType.String) { forFrame.Values = new List <Value>(); for (int k = 0; k < expr.String.Length; k++) { forFrame.Values.Add(new Value(expr.String[k])); } } else { throw new Exception("Fastcode can only iterate through an array or string."); } forFrame.currentIndex = 0; functionFrame = GetCurrentContext(); if (forFrame.Values.Count > 0) { if (functionFrame.LocalVariables.ContainsKey(forFrame.IndexerIdentifier)) { functionFrame.LocalVariables[forFrame.IndexerIdentifier] = forFrame.Values[0]; } else { functionFrame.LocalVariables.Add(forFrame.IndexerIdentifier, forFrame.Values[0]); } } CallStack.Push(forFrame); readTillCallFrameStart(); if (forFrame.currentIndex >= forFrame.Values.Count) { SkipCallFrame(); prevCallFrame = CallStack.Pop(); } break; case Token.Function: MatchToken(Token.Identifier); string fid = lexer.TokenIdentifier; if (functions.ContainsKey(fid) || GlobalVariables.ContainsKey(fid) || builtInFunctions.ContainsKey(fid)) { throw new Exception("Identifiers must be unique"); } functionFrame = new FunctionFrame(fid); ReadNextToken(); MatchToken(Token.OpenParenthesis); List <string> argument_identifiers = new List <string>(); while (lastToken != Token.CloseParenthesis) { ReadNextToken(); if (lastToken == Token.Comma || lastToken == Token.CloseParenthesis) { continue; } else if (lastToken == Token.Identifier) { if (argument_identifiers.Contains(lexer.TokenIdentifier) || GlobalVariables.ContainsKey(lexer.TokenIdentifier)) { throw new Exception("Argument identifiers must be unique."); } argument_identifiers.Add(lexer.TokenIdentifier); } else if (lastToken == Token.CloseParenthesis) { break; } else { throw new UnexpectedStatementException("an identifier", lastToken.ToString()); } } functionFrame.SetArgumentParameters(argument_identifiers); CallStack.Push(functionFrame); readTillCallFrameStart(); functionFrame = (FunctionFrame)CallStack.Pop(); functions[fid] = functionFrame; SkipCallFrame(); break; case Token.CloseBrace: //checks to return or repeat. if (CallStack.Peek().GetType() == typeof(WhileFrame)) { Marker currentpos = (Marker)lexer.Position.Clone(); lexer.ShiftCurrentPosition(((WhileFrame)CallStack.Peek()).ExpressionMarker); ReadNextToken(); expr = EvaluateNextExpression(); if (expr == null) { return; } if (expr.PerformBinaryOperation(Token.Equals, new Value(0)).Double == 1) { prevCallFrame = CallStack.Pop(); lexer.ShiftCurrentPosition(currentpos); } else { lexer.ShiftCurrentPosition(CallStack.Peek().StartPosition); ReadNextToken(); } } else if (CallStack.Peek().GetType() == typeof(ForFrame)) { ForFrame forStructure2 = (ForFrame)CallStack.Pop(); forStructure2.currentIndex++; functionFrame = GetCurrentContext(); if (forStructure2.currentIndex < forStructure2.Values.Count) { functionFrame.LocalVariables[forStructure2.IndexerIdentifier] = forStructure2.Values[forStructure2.currentIndex]; CallStack.Push(forStructure2); lexer.ShiftCurrentPosition(CallStack.Peek().StartPosition); ReadNextToken(); } else { functionFrame.LocalVariables.Remove(forStructure2.IndexerIdentifier); } } else if (CallStack.Peek().GetType() == typeof(FunctionFrame)) { functionFrame = (FunctionFrame)CallStack.Pop(); lexer.ShiftCurrentPosition(functionFrame.ReturnPosition); GetCurrentContext().functionResults.Enqueue(functionFrame.ReturnResult); } else { prevCallFrame = CallStack.Pop(); } break; default: throw new UnexpectedStatementException(keyword.ToString()); } if (lastToken == Token.Semicolon) { keywordMarker = (Marker)lexer.Position.Clone(); ReadNextToken(); while (lastToken == Token.Newline) { ReadNextToken(); } ExecuteNextStatement(); } }