internal static void Begin(Tokenizer tokenizer, WordListBuilder wlbParent) { var wlbBegin = new WordListBuilder(); Evaluable evalCond = null; while (true) { var word = tokenizer.NextToken().ToLower(); switch (word) { case "again": wlbParent.Add(new BeginPrim(wlbBegin.Realize())); return; case "until": wlbParent.Add(new BeginPrim(wlbBegin.Realize(), true)); return; case "while": evalCond = wlbBegin.Realize(); wlbBegin.Clear(); continue; case "repeat" when evalCond == null: throw new NfException("\"begin...repeat\" with no while"); case "repeat": wlbParent.Add(new BeginPrim(wlbBegin.Realize(), false, evalCond)); return; } var evaluable = Interpreter.ParseWord(word); if (evaluable == null) { // TODO: get more robust error handling throw new NfException($"Couldn't locate word {word}"); } if (evaluable.IsImmediate) { // Only runs at compile time so no need to supply a parent here. evaluable.Eval(tokenizer, wlbBegin); continue; } wlbBegin.Add(evaluable); } }
internal static void Definition(Tokenizer tokenizer) { var wlb = new WordListBuilder(); string currentDefWord = tokenizer.NextToken().ToLower(); Evaluable execute = null; while (true) { var word = tokenizer.NextToken().ToLower(); if (word == "does>") { execute = wlb.Realize(true, currentDefWord); wlb.Clear(); continue; } if (word == ";") { if (execute == null) { Vocabulary.CurrentVocabulary.AddDefinition(currentDefWord, wlb.Realize(true, currentDefWord)); } else { var run = wlb.Realize(true, currentDefWord); var compile = execute; Vocabulary.CurrentVocabulary.AddDefinition(currentDefWord, new DoesWord(compile, run)); } Session.LastDefinedWord = null; return; } var evaluable = Interpreter.ParseWord(word); if (evaluable == null) { // TODO: get more robust error handling throw new NfException($"Couldn't locate word {word}"); } if (evaluable.IsImmediate) { evaluable.Eval(tokenizer, wlb); continue; } wlb.Add(evaluable); } }
internal static void Do(Tokenizer tokenizer, WordListBuilder wlbParent, bool isQuestDo) { var _wlbDo = new WordListBuilder(); while (true) { var word = tokenizer.NextToken().ToLower(); if (word == "loop") { wlbParent.Add(new DoPrim(_wlbDo.Realize(), false, isQuestDo)); return; } if (word == "+loop") { wlbParent.Add(new DoPrim(_wlbDo.Realize(), true, isQuestDo)); return; } var evaluable = Interpreter.ParseWord(word); if (evaluable == null) { // TODO: get more robust error handling throw new NfException($"Couldn't locate word {word}"); } if (evaluable.IsImmediate) { evaluable.Eval(tokenizer, _wlbDo); continue; } _wlbDo.Add(evaluable); } }
internal static void If(Tokenizer tokenizer, WordListBuilder wlbParent) { var wlbThenClause = new WordListBuilder(); var wlbElseClause = (WordListBuilder)null; while (true) { var word = tokenizer.NextToken().ToLower(); // ReSharper disable once SwitchStatementMissingSomeCases switch (word) { case "then": wlbParent.Add(new IfPrim(wlbThenClause.Realize(), wlbElseClause?.Realize())); return; case "else": wlbElseClause = wlbThenClause; wlbThenClause = new WordListBuilder(); continue; } var evaluable = Interpreter.ParseWord(word); if (evaluable == null) { // TODO: get more robust error handling throw new NfException($"Couldn't locate word {word}"); } if (evaluable.IsImmediate) { evaluable.Eval(tokenizer, wlbThenClause); continue; } wlbThenClause.Add(evaluable); } }
internal static void FString(Tokenizer tokenizer, WordListBuilder wlbParent, StringType st = StringType.Forth) { var sbText = new StringBuilder(); var prependSpace = false; var done = false; // TODO: read tokenizer char by char to properly emulate white space while (!done) { var word = tokenizer.NextToken(); if (word.EndsWith("\"")) { done = true; word = word.Substring(0, word.Length - 1); } if (prependSpace) { sbText.Append(" "); } prependSpace = true; sbText.Append(word); } var text = sbText.ToString(); int finalValue = -1; switch (st) { case StringType.Forth: var pCountedString = Memory.Allocate(text.Length * sizeof(char) + Session.StringLengthSize); Memory.StoreCString(pCountedString, text); finalValue = pCountedString; break; case StringType.DotNet: var index = SaveManagedObject(text); finalValue = index; break; case StringType.Type: var type = Type.GetType(text); if (type == null) { throw new NfException($"Unrecognized .NET type in t\": {text}"); } if (type.IsGenericType) { var genericParameterCount = type.GetGenericArguments().Length; var parmTypes = CallAction.GetParmTypes($"Invalid types for generic type {text}", genericParameterCount); type = type.MakeGenericType(parmTypes); } finalValue = SaveManagedObject(type); break; case StringType.Stack: var pStackString = Memory.AllocateStackString(text.Length); Memory.StoreString(pStackString, text); finalValue = pStackString; break; } if (wlbParent == null) { Stack.Push(finalValue); if (st == StringType.Stack) { Stack.Push(text.Length); } } else { wlbParent.Add(new IntPrim(finalValue)); if (st == StringType.Stack) { wlbParent.Add(new IntPrim(text.Length)); } } }