using System; using System.Collections.Generic; using System.IO; using System.Linq; using MarketData; namespace Axiom.Interpreter { public class Emitter { private bool emitting = true; private int lastSymbol; private BinaryReader inputStream; private BinaryWriter outputStream; // the assigned output stream private BinaryWriter activeStream; // the active stream private Stack writeStack = new Stack(); private Stack captureStack = new Stack(); private bool isCapturing = false; private bool debug = true; public Emitter(BinaryReader inputStream, BinaryWriter outputStream) { this.inputStream = inputStream; this.outputStream = outputStream; this.activeStream = outputStream; } public bool Debug { get { return debug; } set { debug = value; } } public void BeginCapture() { writeStack.Push(activeStream); activeStream = new BinaryWriter(new MemoryStream()); isCapturing = true; } public void EndCapture() { if (!isCapturing)throw new InvalidOperationException("EndCapture called without a matching BeginCapture."); activeStream.Flush(); MemoryStream memoryStream = (MemoryStream)activeStream.BaseStream; byte[] capturedBytes = memoryStream.ToArray(); activeStream.Close(); activeStream.Dispose(); activeStream = writeStack.Pop(); isCapturing = writeStack.Count > 0; captureStack.Push(new CapturedCode(capturedBytes)); } /// /// EmitCapture - Later, for CONTINUE semantics, we can Peek() at the top of the captureStack to get the increment code without popping it. /// public void EmitCapture() { if(0==captureStack.Count)throw new InvalidOperationException("The CaptureList is empty."); CapturedCode code = captureStack.Pop(); activeStream.Write(code.Bytes,0,code.Length); } public void Emit(String literalValue) { if (!emitting) return; activeStream.Write(literalValue.Length); activeStream.Write(literalValue); } public void Emit(Scanner.ScanSymbols code) { if (!emitting) return; activeStream.Write((int)code); if (Debug) MDTrace.WriteLine(LogLevel.DEBUG, Scanner.SymbolToString(code)); } public void Emit(Scanner.ScanSymbols code,int value) { if (!emitting) return; activeStream.Write((int)code); activeStream.Write(value); if (Debug) MDTrace.WriteLine(LogLevel.DEBUG, Scanner.SymbolToString(code) + "," + value.ToString()); } public void Emit(Scanner.ScanSymbols code,double value) { if (!emitting) return; activeStream.Write((int)code); activeStream.Write(value); if (Debug) MDTrace.WriteLine(LogLevel.DEBUG, Scanner.SymbolToString(code) + "," + value.ToString()); } public void Emit(Scanner.ScanSymbols code,String value) { if (!emitting) return; activeStream.Write((int)code); activeStream.Write(value); if (Debug) MDTrace.WriteLine(LogLevel.DEBUG, Scanner.SymbolToString(code) + "," + value.ToString()); } public long CodePointer() { return activeStream.BaseStream.Position; } public void Seek(long position) { activeStream.BaseStream.Seek(position, SeekOrigin.Begin); } public void Emit(Parser.ParserSymbols code) { if (!emitting) return; long positionBefore = activeStream.BaseStream.Position; activeStream.Write((int)code); long positionAfter = activeStream.BaseStream.Position; if (Debug) MDTrace.WriteLine(LogLevel.DEBUG, Parser.SymbolToString(code) + "[" + positionBefore + "," + positionAfter + "]"); } public void Emit(Parser.ParserSymbols code,Object value) { if (!emitting) return; long positionBefore = activeStream.BaseStream.Position; activeStream.Write((int)code); Type type = value.GetType(); activeStream.Write(type.ToString()); activeStream.Write(value.ToString()); long positionAfter = activeStream.BaseStream.Position; if (Debug) MDTrace.WriteLine(LogLevel.DEBUG, Parser.SymbolToString(code) + "," + type.ToString() + "," + value.ToString() + "[" + positionBefore + "," + positionAfter + "]"); } public void Emit(Parser.ParserSymbols code,Object value,int intValue) { if (!emitting) return; long positionBefore = activeStream.BaseStream.Position; activeStream.Write((int)code); Type type = value.GetType(); activeStream.Write(type.ToString()); activeStream.Write(value.ToString()); activeStream.Write(intValue); long positionAfter = activeStream.BaseStream.Position; if (Debug) MDTrace.WriteLine(LogLevel.DEBUG, Parser.SymbolToString(code) + "," + type.ToString() + "," + value.ToString() + "," + intValue + "[" + positionBefore + "," + positionAfter + "]"); } public void Emit(Parser.ParserSymbols code,long value) { if (!emitting) return; long positionBefore = activeStream.BaseStream.Position; activeStream.Write((int)code); activeStream.Write(value); long positionAfter = activeStream.BaseStream.Position; if (Debug) MDTrace.WriteLine(LogLevel.DEBUG, Parser.SymbolToString(code) + "," + value.ToString() + "," + value.ToString() + "[" + positionBefore + "," + positionAfter + "]"); } public void EmitAsNull(Parser.ParserSymbols code) { if (!emitting) return; long positionBefore = activeStream.BaseStream.Position; activeStream.Write((int)code); Type type = typeof(System.Nullable); activeStream.Write(type.ToString()); activeStream.Write("null".ToString()); long positionAfter = activeStream.BaseStream.Position; if (Debug) MDTrace.WriteLine(LogLevel.DEBUG, Parser.SymbolToString(code) + "," + type.ToString() + "," + "null" + "[" + positionBefore + "," + positionAfter + "]"); } public void Emit(int code,int op) { if (!emitting) return; activeStream.Write(code); activeStream.Write(op); } public void Emit(int identifier) { if (!emitting) return; activeStream.Write(identifier); } public void Emit(byte value) { if (!emitting) return; activeStream.Write(value); } public int Peek(ref int value) { value = inputStream.PeekChar(); return value; } public int Peek() { int value = inputStream.PeekChar(); return value; } public int PeekIgnore(ref int value,int[] ignoreChars) { long streamPosition = inputStream.BaseStream.Position; while (true) { int readValue = (int)inputStream.ReadChar(); value = readValue; if (!ignoreChars.Any(x => x.Equals(readValue))) break; } inputStream.BaseStream.Seek(streamPosition, SeekOrigin.Begin); return value; } public int Read() { lastSymbol = inputStream.Read(); return lastSymbol; } public int Read(ref String literal) { literal = inputStream.ReadString(); return 0; } public int Read(ref byte value) { try { value = inputStream.ReadByte(); return 0; } catch (EndOfStreamException) { return 0xFFFF; } } public int Read(ref int value) { try { value = inputStream.ReadInt32(); return 0; } catch (EndOfStreamException) { return 0xFFFF; } } public int Read(ref double value) { try { value = inputStream.ReadDouble(); return 0; } catch (EndOfStreamException) { return 0xFFFF; } } public bool Emitting { get { return emitting; } set { emitting = value; } } } }