コード例 #1
0
ファイル: MacroLibrary.cs プロジェクト: nerai/nibbler
		public MacroTransition GetMacro (State state, byte read, bool facingRight)
		{
			var store = facingRight ? _MacroDeltaR : _MacroDeltaL;
			MacroTransition trans;
			if (store.TryGetValue (state, read, out trans)) {
				trans.UsageCount++;
			}
			return trans;
		}
コード例 #2
0
ファイル: MacroTransition.cs プロジェクト: nerai/nibbler
		public MacroTransition (
			State source,
			byte read,
			bool facingRight,
			State q,
			byte write,
			short d,
			ulong shifts,
			byte[] readUnpacked,
			byte[] writeUnpacked)
		{
			if (source == null)
				throw new ArgumentNullException ();
			if (readUnpacked == null)
				throw new ArgumentNullException ();
			if (writeUnpacked == null)
				throw new ArgumentNullException ();

			Source = source;
			Read = read;
			StartFacingRight = facingRight;
			Next = q;
			Write = write;
			Direction = d;
			Shifts = shifts;

			_ReadUnpacked = readUnpacked;
			_WriteUnpacked = writeUnpacked;

			if (Next != null) {
				if (false
					|| (StartFacingRight && Direction == readUnpacked.Length)
					|| (!StartFacingRight && Direction == +1)
					) {
					EndFacingRight = true;
				}
				else if (false
				       || (!StartFacingRight && Direction == -readUnpacked.Length)
				       || (StartFacingRight && Direction == -1)
					) {
					EndFacingRight = false;
				}
				else {
					EndFacingRight = null;
				}
			}
		}
コード例 #3
0
ファイル: TmDefinition.cs プロジェクト: nerai/nibbler
		public TmDefinition (JsonTmDefinition def)
		{
			if (def == null)
				throw new ArgumentNullException ();

			Gamma = MapSymbols (def.Gamma, 0);
			Sigma = new Dictionary<byte, string> ();
			foreach (var sig in def.Sigma) {
				Sigma.Add (Gamma.Where (p => p.Value == sig).First ().Key, sig);
			}

			Func<string, State> createState = name => {
				var halting = false
					|| def.AcceptingState == name
					|| def.RefusingState == name;
				var ts = halting ? null : new SimpleTransition[Gamma.Count];
				var q = new State (Q.Count, name, ts);
				Q.Add (name, q);
				return q;
			};

			Q0 = createState (def.InitialState);

			foreach (var qs in def.NonfinalStates) {
				if (qs == def.InitialState) {
					continue;
				}
				createState (qs);
			}

			if (def.AcceptingState != null) {
				createState (def.AcceptingState);
			}
			if (def.RefusingState != null) {
				createState (def.RefusingState);
			}

			foreach (var t in def.Delta) {
				var qin = Q[t.From];
				byte gin = Gamma.First (p => p.Value == t.Read).Key;
				var qout = Q[t.To];
				byte gout = Gamma.First (p => p.Value == t.Write).Key;
				short dir;
				switch (t.Dir) {
					case "R":
						dir = 1;
						break;

					case "L":
						dir = -1;
						break;

					case "S":
						dir = 0;
						break;

					default:
						throw new Exception ();
				}

				var st = new SimpleTransition (qin, gin, qout, gout, dir);
				qin.Delta[gin] = st;
				qout.Sources.Add (st);
			}

			SuggestedMacroSize = def.SuggestedMacroSize;

			UpdateShortDefinitionString ();
		}
コード例 #4
0
ファイル: TmDefinition.cs プロジェクト: nerai/nibbler
		/// <summary>
		/// </summary>
		/// <param name="s">
		/// Format:
		/// q0,q1,...; Q
		/// s0,s1,...; Sigma
		/// g0,g1,...; Gamma without Sigma
		/// q,i -> q',o,d; Single Delta transition, repeatable
		/// K=n; Suggested macro width, optional
		/// /* anywhere: comments in old C style allowed */
		/// </param>
		public TmDefinition (string s)
		{
			if (s == null)
				throw new ArgumentNullException ();

			if (s.Count (c => c == ';') <= 1) { // todo: bug when ';' in comments
				s = DefinitionLibrary.CreateBeaverFromNote (s);
			}
			FullDefinitionString = s;

			s = StripComments (s);

			var split = s.Split (';').Select (x => x.Trim ()).ToList ();

			var sStates = split[0];
			split.RemoveAt (0);
			var sHalting = split[0];
			split.RemoveAt (0);
			var sSigma = split[0];
			split.RemoveAt (0);
			var sGamma = split[0];
			split.RemoveAt (0);

			/*
			 * Sigma/Gamma
			 */
			var sigmasplit = sSigma.Split (',');
			var gammasplit = sGamma.Split (',');
			Sigma = MapSymbols (sigmasplit, 1);
			Gamma = MapSymbols (gammasplit.Skip (1), 1 + Sigma.Count);
			Gamma.Add (0, gammasplit[0]);
			foreach (var sig in Sigma) {
				Gamma.Add (sig.Key, sig.Value);
			}

			/*
			 * Q
			 * (can only be constructed once Gamma is known)
			 */
			var statessplit = sStates.Split (',');
			foreach (var p in statessplit.Select (x => x.Trim ())) {
				if (p == "") {
					continue;
				}

				if (Q.Count >= 255) {
					throw new Exception ();
				}

				var q = new State ((byte) Q.Count, p, new SimpleTransition[Gamma.Count]);
				Q.Add (p, q);

				if (Q0 == null) {
					Q0 = q;
				}
			}
			foreach (var p in sHalting.Split (',').Select (x => x.Trim ())) {
				if (p == "") {
					continue;
				}

				if (Q.Count >= 255) {
					throw new Exception ();
				}

				var q = new State ((byte) Q.Count, p, null);
				Q.Add (p, q);

				if (Q0 == null) {
					Q0 = q;
				}
			}

			var haltingStates = Q.Values.Where (q => q.Delta == null).ToArray ();
			if (haltingStates.Length == 0) {
				var nonhaltingStates = Q.OrderBy (x => x.Key).Select (x => x.Value).ToArray ();
				Qa = nonhaltingStates[nonhaltingStates.Length - 2];
				Qr = nonhaltingStates[nonhaltingStates.Length - 1];
			}
			else if (haltingStates.Length == 1) {
				Qa = haltingStates[0];
				Qr = null;
			}
			else {
				Qa = haltingStates[0];
				Qr = haltingStates[1];
			}

			// Here be dragons

			/*
			 * Delta
			 */
			while (split.Any ()) {
				var d = split[0];
				d = d.TrimStart (' ', '\t');
				split.RemoveAt (0);

				if (d == "") {
					continue;
				}

				if (d.StartsWith ("K=")) {
					d = d.Substring (2);
					SuggestedMacroSize = Unlog.Util.StringCutting.CutInt (ref d);
					split.Insert (0, d);
					continue;
				}

				var parts = d.Split (new[] { "->" }, 2, StringSplitOptions.None);
				var input = parts[0].Split (',').Select (x => x.Trim ()).ToArray ();
				var output = parts[1].Split (',').Select (x => x.Trim ()).ToArray ();

				var sqin = input[0];
				var stin = input[1];
				var sqout = output[0];
				var stout = output[1];
				var sd = output[2].ToUpperInvariant ();

				// Check different notation
				if (sd != "L" && sd != "R") {
					if (stout == "L" || stout == "R") {
						var tmp = sd;
						sd = stout;
						stout = sqout;
						sqout = tmp;
					}
				}

				var qin = Q[sqin];
				byte gin = Gamma.First (p => p.Value == stin).Key;
				var qout = Q[sqout];
				byte gout = Gamma.First (p => p.Value == stout).Key;
				short dir;
				switch (sd) {
					case "R":
						dir = 1;
						break;

					case "L":
						dir = -1;
						break;

					case "S":
						dir = 0;
						break;

					default:
						throw new Exception ();
				}

				var t = new SimpleTransition (qin, gin, qout, gout, dir);
				qin.Delta[gin] = t;
				qout.Sources.Add (t);
			}

			UpdateShortDefinitionString ();
		}
コード例 #5
0
ファイル: MacroTransition.cs プロジェクト: nerai/nibbler
		public static MacroTransition CreateSingleMacroTransition (
			TmDefinition def,
			State q,
			byte readPacked,
			bool facingRight,
			MacroPacker packerInfo)
		{
			if (def == null)
				throw new ArgumentNullException ();
			if (q == null)
				throw new ArgumentNullException ();
			if (packerInfo == null)
				throw new ArgumentNullException ();

			var readUnpacked = packerInfo.Decode (readPacked);
			var left = facingRight ? new byte[0] : readUnpacked.SubArray (0, readUnpacked.Length - 1);
			var right = facingRight ? readUnpacked : readUnpacked.SubArray (readUnpacked.Length - 1, 1);
			var tape = new LimitedBasicTape (left, right, def.Gamma);
			short dir;

			var tm = new SimpleTmRun (def, tape, new LimitedBasicTape (tape, def.Gamma), q);
			tm.AfterStep += new DetectTapeTooSmall ().Detect;
			tm.Options.AllowCreateMissingTransitionBranches = false;

			try {
				TmPrintOptions.Push ();
				TmPrintOptions.PrintTapeSteps = false;
				TmPrintOptions.PrintTransitionLevel = PrintTransitionLevel.None;

				var prevPos = (short) tape.Position;
				tm.Run ();
				dir = (short) (tape.Position - prevPos);
			}
			catch (TransitionNotDefinedException) {
				// Intentional throw. Let the caller handle this.
				throw;
			}
			finally {
				TmPrintOptions.Pop ();
			}

			Debug.Assert (tm.Result.Halted.HasValue != tape.ExitsOnLeftSide.HasValue);

			if (tm.Result.Halted == false) {
				return new MacroTransition (q, readPacked, facingRight, null, readPacked, 0, tm.Shifts, readUnpacked, readUnpacked);
			}
			else {
				var writeUnpacked = tape.Tape;
				var writePacked = packerInfo.Encode (writeUnpacked);
				return new MacroTransition (q, readPacked, facingRight, tm.Q, writePacked, dir, tm.Shifts, readUnpacked, writeUnpacked);
			}
		}