Files
Sean 22f30466bc
Some checks failed
Build .NET Project / build (push) Has been cancelled
Code cleanup
2026-03-19 15:37:17 -04:00

248 lines
7.9 KiB
C#
Executable File

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Axiom.Utils;
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<BinaryWriter> writeStack = new Stack<BinaryWriter>();
private Stack<CapturedCode> captureStack = new Stack<CapturedCode>();
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));
}
/// <summary>
/// EmitCapture - Later, for CONTINUE semantics, we can Peek() at the top of the captureStack to get the increment code without popping it.
/// </summary>
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; }
}
}
}