private static bool IfDef(VM vm, RantPattern source, Stringe tagname, Argument[] args) { if (vm.Engine.Flags.Contains(args[0])) { vm.PushState(VM.State.CreateSub(source, args[1].AsPattern(), vm, vm.CurrentState.Output)); return(true); } vm.SetElse(); return(false); }
public void PackageModules() { var package = new RantPackage(); var pattern = RantPattern.FromString("[$[.hello_world]:Hello World]"); pattern.Name = "pkg_test"; package.AddPattern(pattern); rant.LoadPackage(package); Assert.AreEqual("Hello World", rant.Do("[use:pkg_test][$pkg_test.hello_world]").Main); }
private static bool GenerationSet(VM vm, RantPattern source, Stringe tagName, Argument[] args) { var gStr = args[0].AsString(); long g; if (!Int64.TryParse(gStr, out g)) { throw Error(source, tagName, "Invalid generation value '\{gStr}'"); } vm.RNG.Generation = g; return(false); }
/// <summary> /// Adds a RantPattern containing a subroutine to this module. /// </summary> /// <param name="name">The name of the function to add.</param> /// <param name="pattern">The pattern that will make up the body of the function.</param> public void AddSubroutineFunction(string name, RantPattern pattern) { var action = (pattern.Action.GetType() == typeof(RASequence) ? ((RASequence)pattern.Action).Actions[0] : pattern.Action); if (action.GetType() != typeof(RADefineSubroutine)) { throw new RantRuntimeException(pattern, pattern.Code, "Attempted to add non-subroutine pattern to a module."); } _objects[name] = new RantObject(action); }
private static bool BranchScope(VM vm, RantPattern source, Stringe tagName, Argument[] args) { vm.RNG.Branch(args[0].AsString().Hash()); var state = VM.State.CreateSub(source, args[1].AsPattern(), vm, vm.CurrentState.Output); state.Post(new DelegateBlueprint(vm, _ => { vm.RNG.Merge(); return(false); })); vm.PushState(state); return(true); }
private static bool DefineFlag(VM vm, RantPattern source, Stringe tagname, Argument[] args) { foreach (var flag in args.Where(flag => !String.IsNullOrEmpty(flag))) { if (!ValidateName(flag)) { throw Error(source, tagname, "Invalid flag name '\{flag}'"); } vm.Engine.Flags.Add(flag); } return(false); }
private static bool CharacterMulti(VM vm, RantPattern source, Stringe tagname, Argument[] args) { int count; if (!ParseInt(args[1], out count) || count < 0) { throw Error(source, tagname, "Invalid character count specified. Must be a non-negative number greater than zero."); } for (int i = 0; i < count; i++) { vm.Print(SelectFromRanges(args[0], vm.RNG)); } return(false); }
private static bool Break(VM vm, RantPattern source, Stringe tagname, Argument[] args) { if (vm.CurrentRepeater == null) { return(false); } vm.CurrentRepeater.Finish(); VM.State state = null; while (!vm.BaseStates.Contains(state = vm.CurrentState)) { vm.PopState(); } vm.BaseStates.Remove(state); return(true); }
private static bool Quote(VM vm, RantPattern source, Stringe tagname, Argument[] args) { vm.PushState(VM.State.CreateSub(source, args[0].AsPattern(), vm, vm.CurrentState.Output) .Pre(new DelegateBlueprint(vm, _ => { vm.OpenQuote(); return(false); })) .Post(new DelegateBlueprint(vm, _ => { vm.CloseQuote(); return(false); }))); return(true); }
public FuncTagBlueprint(VM interpreter, RantPattern source, Stringe name, IEnumerable <Token <R> >[] argData = null) : base(interpreter) { Source = source; Name = name.Trim(); RantFuncSigs defs; if (!RantFuncs.F.TryGetValue(Name.Value, out defs)) { throw new RantException(Source, Name, "A function of the name '" + Name.Value + "' does not exist."); } if ((_tagDef = defs.GetSignature((argData == null ? 0 : argData.Length))) == null) { throw new RantException(Source, Name, "The function '" + Name.Value + "' has no signature that accepts " + (argData == null ? 0 : argData.Length) + " argument(s)."); } if (argData == null) { _args = new Argument[0]; } else { var lastType = _tagDef.Parameters.Last(); // Insert token arguments into the array, set string args to null. _args = argData.Select((a, i) => (i >= _tagDef.ParamCount ? (lastType & ParamFlags.Code) == ParamFlags.Code // Covers multi params : (_tagDef.Parameters[i] & ParamFlags.Code) == ParamFlags.Code) ? Argument.FromTokens(a) : null).ToArray(); // Queue string arguments on the stack. for (int i = 0; i < argData.Length; i++) { if ((i >= _tagDef.ParamCount && (lastType & ParamFlags.Code) != ParamFlags.Code) || (_tagDef.Parameters[i] & ParamFlags.Code) != ParamFlags.Code) { interpreter.PushState(VM.State.CreateSub(source, argData[i], interpreter)); } } } }
private static bool Compare(VM vm, RantPattern source, Stringe tagname, Argument[] args) { var cmp = new Comparison(args[0].AsString(), args[1].AsString()); vm.Comparisons.Push(cmp); var state = VM.State.CreateSub(source, args[2].AsPattern(), vm, vm.CurrentState.Output); state.Post(new DelegateBlueprint(vm, I => { I.Comparisons.Pop(); return(false); })); vm.PushState(state); return(true); }
public override bool Use() { if (!_inputCollected) { // Get the replacer's input string _input = I.PopResultString(); _inputCollected = true; // Queue this blueprint for after the matches are evaluated I.CurrentState.Pre(this); // Get the matches for the pattern in the input _matches = _regex.Matches(_input); RantPattern source = I.CurrentState.Reader.Source; var state = CreateMatchEvaluatorState(source, I, _matches, _matches.Count - 1); I.PushState(state); return(true); } else { int start = 0; var sb = new StringBuilder(); // Replace stuff foreach (Match match in _matches) { sb.Append(_input.Substring(start, match.Index - start)); sb.Append(I.PopResultString()); start = match.Index + match.Length; } // Toss on any leftover string sb.Append(_input.Substring(start, _input.Length - start)); // Print the result I.Print(sb.ToString()); } return(false); }
/// <summary> /// Creates a new RantObject instance from the specified object. /// </summary> /// <param name="obj">The value to assign to the object.</param> public RantObject(object obj) { if (obj == null) { return; } if (obj is string) { _string = obj.ToString(); Type = RantObjectType.String; } else if (obj is bool) { _boolean = (bool)obj; Type = RantObjectType.Boolean; } else if (IsNumber(obj)) { _number = (double)obj; Type = RantObjectType.Number; } else if (obj is List <RantObject> ) { _list = (List <RantObject>)obj; Type = RantObjectType.List; } else if (obj.GetType().IsArray) { _list = ((object[])obj).Select(o => new RantObject(o)).ToList(); Type = RantObjectType.List; } else if (obj is RantPattern) { _pattern = (RantPattern)obj; } else if (obj is RantAction) { _action = (RantAction)obj; Type = RantObjectType.Action; } }
private static void Pack(RantPackage package, string contentPath) { foreach (var path in Directory.EnumerateFiles(contentPath, "*.*", SearchOption.AllDirectories) .Where(p => p.EndsWith(".rant") || p.EndsWith(".rants"))) { var pattern = RantPattern.FromFile(path); string relativePath; TryGetRelativePath(contentPath, path, out relativePath, true); pattern.Name = relativePath; package.AddPattern(pattern); Console.WriteLine("+ " + pattern.Name); } foreach (var path in Directory.GetFiles(contentPath, "*.dic", SearchOption.AllDirectories)) { Console.WriteLine("+ " + path); var table = RantDictionaryTable.FromFile(path); package.AddTable(table); } }
public SubCallBlueprint(VM interpreter, RantPattern source, Subroutine subroutine, IEnumerable <Token <R> >[] args) : base(interpreter) { _subroutine = subroutine; if (args == null) { _args = Enumerable.Empty <Argument>().ToArray(); } else { // Insert token arguments into the array, set string args to null. _args = args.Select((a, i) => _subroutine.Parameters[i].Item2 == ParamFlags.Code ? Argument.FromTokens(a) : null).ToArray(); // Queue string arguments on the stack. for (int i = 0; i < _subroutine.ParamCount; i++) { if (_subroutine.Parameters[i].Item2 == ParamFlags.None) { interpreter.PushState(VM.State.CreateSub(source, args[i], interpreter)); } } } }
public Sandbox(RantEngine engine, RantPattern pattern, RNG rng, int sizeLimit = 0, RantPatternArgs args = null) { _engine = engine; _format = engine.Format; _sizeLimit = new Limit(sizeLimit); _baseOutput = new OutputWriter(this); _outputs = new Stack <OutputWriter>(); _outputs.Push(_baseOutput); _rng = rng; _startingGen = rng.Generation; _pattern = pattern; _objects = new ObjectStack(engine.Objects); _blocks = new Stack <BlockState>(); _matches = new Stack <Match>(); _queryState = new QueryState(); _subroutineArgs = new Stack <Dictionary <string, RantAction> >(); _syncManager = new SyncManager(this); _blockManager = new BlockManager(); _scriptObjectStack = new Stack <object>(); _patternArgs = args; _stopwatch = new Stopwatch(); }
private static void Use(Sandbox sb, string name) { if (sb.UserModules.ContainsKey(name)) { sb.Modules[name] = sb.UserModules[name]; return; } if (sb.PackageModules.ContainsKey(name)) { sb.Modules[name] = sb.PackageModules[name]; return; } string file; if (File.Exists(name + ".module.rant")) { file = name + ".module.rant"; } else if (File.Exists(name + ".rant")) { file = name + ".rant"; } else if (File.Exists(name)) { file = name; } else { throw new RantRuntimeException(sb.Pattern, sb.CurrentAction.Range, $"Could not find module '{name}'."); } var pattern = RantPattern.FromFile(file); if (pattern.Module == null) { throw new RantRuntimeException(sb.Pattern, sb.CurrentAction.Range, $"No module is defined in {file}."); } sb.Modules[Path.GetFileNameWithoutExtension(name)] = pattern.Module; }
private static bool CmpIs(VM vm, RantPattern source, Stringe tagname, Argument[] args) { var cmp = vm.Comparisons.Peek(); var conStrings = args[0].AsString() .Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); ComparisonResult e; foreach (var conString in conStrings) { if (!Enum.TryParse(NameToCamel(conString), true, out e)) { continue; } if (!cmp.Result.HasFlag(e)) { continue; } vm.PushState(VM.State.CreateSub(source, args[1].AsPattern(), vm, vm.CurrentState.Output)); return(true); } return(false); }
public void UnexpectedTagTerminator() { RantPattern.FromString(@"]"); }
public void EmptyTag() { RantPattern.FromString(@"[]"); }
public void MissingReplacerArgument() { RantPattern.FromString(@"[`\s*`:this is a test]"); }
private void CreatePattern() { _pattern = new RantPattern("pattern string", RantPatternSource.String, Value); }
public void TooManyCarrierOperators() { RantPattern.FromString(@"<noun::!A::@B>"); }
public void MissingQuerySubtype() { RantPattern.FromString(@"<noun.>"); }
public void InvalidQueryTableName(string name) { RantPattern.FromString($"<{name}>"); }
public RantOutput Run(double timeout, RantPattern pattern = null) { if (pattern == null) pattern = _pattern; LastTimeout = timeout; _scriptObjectStack.Clear(); _objects.Clear(); var callStack = new Stack<IEnumerator<RantAction>>(); var actionStack = new Stack<RantAction>(); IEnumerator<RantAction> action; long timeoutMS = (long)(timeout * 1000); bool timed = timeoutMS > 0; bool stopwatchAlreadyRunning = _stopwatch.IsRunning; if (!_stopwatch.IsRunning) _stopwatch.Restart(); // Push the AST root CurrentAction = pattern.Action; actionStack.Push(CurrentAction); callStack.Push(pattern.Action.Run(this)); top: while (callStack.Any()) { // Get the topmost call stack item action = callStack.Peek(); // Execute the node until it runs out of children while (action.MoveNext()) { if (timed && _stopwatch.ElapsedMilliseconds >= timeoutMS) throw new RantRuntimeException(pattern, action.Current.Range, $"The pattern has timed out ({timeout}s)."); if (callStack.Count >= RantEngine.MaxStackSize) throw new RantRuntimeException(pattern, action.Current.Range, $"Exceeded the maximum stack size ({RantEngine.MaxStackSize})."); if (action.Current == null) break; // i'm sorry to put this here but it's the only way to do it!! if (action.Current is REABreak) { // move back up the call stack until we pass something "breakable" while ( callStack.Any() && (callStack.Peek().Current is RantExpressionAction) && !(callStack.Peek().Current as RantExpressionAction).Breakable) { actionStack.Pop(); callStack.Pop(); } // there was nothing to break from if (!callStack.Any() || !(callStack.Peek().Current is RantExpressionAction)) throw new RantRuntimeException(Pattern, (action.Current as REABreak).Range, "Nothing to break from."); goto top; } // Push child node onto stack and start over CurrentAction = action.Current; actionStack.Push(CurrentAction); callStack.Push(action.Current.Run(this)); goto top; } var lastAction = actionStack.Peek(); // Special processing for scripts if (lastAction is RantExpressionAction) { var val = (lastAction as RantExpressionAction).GetValue(this); if(val != null) _scriptObjectStack.Push(val); } // i also wish this could be moved to somewhere else // but someone else figure out how to do that for me if (lastAction is REAReturn) { // same thing as the processing for break // todo: abstract this, DRY while ( actionStack.Any() && (actionStack.Peek() is RantExpressionAction) && !(actionStack.Peek() as RantExpressionAction).Returnable) { actionStack.Pop(); callStack.Pop(); } if (!(lastAction as REAReturn).HasReturnValue) _scriptObjectStack.Push(new RantObject(RantObjectType.Undefined)); // if we're not returning from anything, we've returned ourself from the Richard scope goto top; } // Remove node once finished callStack.Pop(); actionStack.Pop(); } if(!stopwatchAlreadyRunning) _stopwatch.Stop(); return Return(); }
private void CreatePattern() { _pattern = new RantPattern("pattern string", RantPatternOrigin.String, Value); }
public IEnumerable<RantOutput> RunSerial(double timeout, RantPattern pattern = null) { lock(_patternArgs ?? fallbackArgsLockObj) { if (pattern == null) pattern = _pattern; LastTimeout = timeout; long timeoutMS = (long)(timeout * 1000); bool timed = timeoutMS > 0; bool stopwatchAlreadyRunning = _stopwatch.IsRunning; if (!_stopwatch.IsRunning) { _stopwatch.Reset(); _stopwatch.Start(); } _scriptObjectStack.Clear(); var callStack = new Stack<IEnumerator<RantAction>>(); var actionStack = new Stack<RantAction>(); IEnumerator<RantAction> action; // Push the AST root CurrentAction = pattern.Action; actionStack.Push(CurrentAction); callStack.Push(pattern.Action.Run(this)); top: while (callStack.Any()) { // Get the topmost call stack item action = callStack.Peek(); // Execute the node until it runs out of children while (action.MoveNext()) { if (timed && _stopwatch.ElapsedMilliseconds >= timeoutMS) throw new RantRuntimeException(pattern, action.Current.Range, $"The pattern has timed out ({timeout}s)."); if (callStack.Count >= RantEngine.MaxStackSize) throw new RantRuntimeException(pattern, action.Current.Range, $"Exceeded the maximum stack size ({RantEngine.MaxStackSize})."); if (action.Current == null) break; if (HandleRichardBreak(callStack, actionStack, action)) goto top; // Push child node onto stack and start over CurrentAction = action.Current; actionStack.Push(CurrentAction); callStack.Push(CurrentAction.Run(this)); goto top; } if (shouldYield) { shouldYield = false; yield return Return(); AddOutputWriter(); } if (HandleRichardReturn(callStack, actionStack)) continue; // Remove node once finished callStack.Pop(); actionStack.Pop(); } if (!stopwatchAlreadyRunning) _stopwatch.Stop(); } }
public void UnexpectedQueryTerminator() { RantPattern.FromString(@">"); }
public void UnterminatedQuery() { RantPattern.FromString(@"<noun"); }
public void UnterminatedConstantLiteral() { RantPattern.FromString("\""); }
public void InvalidQuerySubtype() { RantPattern.FromString(@"<noun.???>"); }
public RantOutput EvalPattern(double timeout, RantPattern pattern) { _outputs.Push(new ChannelWriter(_format, _sizeLimit)); return Run(timeout, pattern); }
public void MissingQueryClassFilter() { RantPattern.FromString(@"<noun->"); }
public UnmanagedPattern(RantPattern pattern) { Pattern = pattern; _handle = GCHandle.Alloc(this); }
public void MissingQuantifierComma() { RantPattern.FromString(@"\123a"); }
public RantOutput EvalPattern(double timeout, RantPattern pattern) { _outputs.Push(new OutputWriter(this)); return Run(timeout, pattern); }
/// <summary> /// Creates a new RantObject instance from the specified object. /// </summary> /// <param name="obj">The value to assign to the object.</param> public RantObject(object obj) { if (obj == null) return; if (obj is string) { _string = obj.ToString(); Type = RantObjectType.String; } else if (obj is bool) { _boolean = (bool)obj; Type = RantObjectType.Boolean; } else if (IsNumber(obj)) { _number = (double)obj; Type = RantObjectType.Number; } else if (obj is List<RantObject>) { _list = (List<RantObject>)obj; Type = RantObjectType.List; } else if (obj.GetType().IsArray) { _list = ((object[])obj).Select(o => new RantObject(o)).ToList(); Type = RantObjectType.List; } else if (obj is RantPattern) { _pattern = (RantPattern)obj; } else if (obj is RantAction) { _action = (RantAction)obj; Type = RantObjectType.Action; } }
internal static RantRuntimeException Error(IEnumerable<Token<R>> tokens, RantPattern source, string message = "A generic syntax error was encountered.") { return new RantRuntimeException(tokens, source, message); }
internal static RantRuntimeException Error(RantPattern source, Stringe token, string message = "A generic syntax error was encountered.") { return new RantRuntimeException(source, token, message); }
public Sandbox(RantEngine engine, RantPattern pattern, RNG rng, int sizeLimit = 0) { _engine = engine; _format = engine.Format; _sizeLimit = new Limit(sizeLimit); _mainOutput = new ChannelWriter(_format, _sizeLimit); _outputs = new Stack<ChannelWriter>(); _outputs.Push(_mainOutput); _rng = rng; _startingGen = rng.Generation; _pattern = pattern; _objects = new ObjectStack(engine.Objects); _blocks = new Stack<BlockState>(); _matches = new Stack<Match>(); _queryState = new QueryState(); _subroutineArgs = new Stack<Dictionary<string, RantAction>>(); _syncManager = new SyncManager(this); _blockManager = new BlockManager(); _scriptObjectStack = new Stack<object>(); _stopwatch = new Stopwatch(); }