internal static void Init() { MKL.Lic("Wendicka Project - Instruction.cs", "GNU General Public License 3"); MKL.Version("Wendicka Project - Instruction.cs", "20.03.09"); Set("end", new Instruction(0, delegate(Source.Line l) { return(l.Parameters.Length == 0); })); Set("call", new Instruction(1, delegate(Source.Line l) { //var ret = true; var p = l.Parameters; if (p.Length == 0) { WASM_Main.VP("\nNothing to call"); return(false); } System.Diagnostics.Debug.WriteLine($"Checking call! Total parameters {p.Length}"); if (p[0].Kind != Source.DataKind.API && p[0].Kind != Source.DataKind.Chunk && p[0].Kind != Source.DataKind.GlobalVar && p[0].Kind != Source.DataKind.LocalVar) { WASM_Main.Error($"Uncallable call: {p[0].Kind}"); return(false); } return(true); })); Set("invoke", new Instruction(2, Get("call").Check)); Set("defer", new Instruction(3, Get("call").Check)); Set("resume", new Instruction(4, delegate { throw new Exception("resume after yield not yet implemented"); })); Set("return", new Instruction(5)); Set("yield", new Instruction(6)); }
internal Source(string file) { if (!File.Exists(file)) { WASM_Main.CRASH($"File '{file}' has not been found!"); } var fpath = qstr.ExtractDir(file).Replace("\\", "/"); try { var src = new List <Line>(); var rawsrc = QuickStream.LoadString(file); if (rawsrc.IndexOf('\r') >= 0) { WASM_Main.WARN("<CR> characters found in source! Please deliver source in <LF> only format!"); rawsrc = rawsrc.Replace("\r", ""); } var srcl = rawsrc.Split('\n'); for (int i = 0; i < srcl.Length; i++) { srcl[i] = srcl[i].Trim(); if (qstr.Left(srcl[i].ToUpper(), 8) == "INCLUDE ") { var f = srcl[i].Substring(8).Trim().Replace('\\', '/'); string ult = ""; if (IncPath.Count == 0) { if (fpath != "") { IncPath.Add(fpath); } else { IncPath.Add("."); } } if (f[0] == '/' || f[1] == ':') { ult = f; } else { foreach (string p in IncPath) { var test = $"{p}/{f}"; if (File.Exists(test)) { ult = test; break; } } if (ult == "") { WASM_Main.CRASH($"No path provided a way to find requested include file {f}"); } } WASM_Main.VP($" Including: {ult}"); var Sub = new Source(ult); foreach (Line L in Sub.Lines) { src.Add(L); } } else if (qstr.Prefixed(srcl[i], ";")) { System.Diagnostics.Debug.WriteLine($"Skipping comment: {srcl[i]}"); } else if (srcl[i] == "") { System.Diagnostics.Debug.WriteLine($"Skipping whiteline {i+1}"); } else { src.Add(new Line(srcl[i], file, i + 1)); } } Lines = src.ToArray(); } catch (Exception e) { WASM_Main.CRASH(e); } }
static void VP(string m) => WASM_Main.VP(m);
static internal void Go(string srcfile) { VP($"Assembling: {srcfile}"); var src = new Source(srcfile); var ofile = $"{qstr.StripExt(srcfile)}.WBIN"; var bo = QuickStream.WriteFile(ofile); bo.WriteString($"Wendicka Binary {(char)26}", true); var Chunks = new SortedDictionary <string, Chunk>(); Chunk CurrentChunk = null; try { var lastspace = 0; foreach (Source.Line L in src.Lines) { for (int p = 0; p < lastspace; p++) { WASM_Main.VT(" "); } WASM_Main.VT("\r"); var s = $"{L.From_File}:{L.Line_Number}"; lastspace = s.Length; WASM_Main.VT($"{s}\r"); Debug.WriteLine(s); var instr = Instruction.Get(L.Instruction); if (L.Instruction == "CHUNK") { if (!ValidID(L.ParamString)) { throw new Exception($"Illegal chunk name: {L.ParamString}"); } var CName = L.ParamString.ToUpper(); if (Chunks.ContainsKey(CName)) { WASM_Main.VP(""); WASM_Main.WARN($"Duplicate chunk name {CName}! Code will be appended to existing chunk! Is that what you wanted?"); CurrentChunk = Chunks[CName]; Debug.WriteLine($"Appending to Chunk: {CName}"); } else { Debug.WriteLine($"Creating Chunk: {CName}"); CurrentChunk = new Chunk(); Chunks[CName] = CurrentChunk; } } else if (L.Instruction.Length > 0 && (L.Instruction[0] == ':' || L.Instruction[L.Instruction.Length - 1] == ':')) { var Lab = L.Instruction.Replace(":", "").ToUpper(); if (CurrentChunk == null) { throw new Exception("Label requires chunk"); } CurrentChunk.Labels[Lab] = CurrentChunk.Length; } else if (instr == null) { throw new Exception($"Unknown instruction! \"{L.Instruction}\"!"); } else if (!instr.Check(L)) { throw new Exception($"Instruction {L.Instruction} does not provide the parameters wanted, or has otherwise bad input!"); } else if (CurrentChunk == null) { throw new Exception("No chunk!"); } else { // If all is good, let's do it! Debug.WriteLine($"Writing instruction {L.Instruction}/{Instruction.Get(L.Instruction).insnum}"); CurrentChunk.Add((byte)2); CurrentChunk.Add((byte)Instruction.Get(L.Instruction).insnum); foreach (Source.Parameter p in L.Parameters) { switch (p.Kind) { case Source.DataKind.StartChunk: case Source.DataKind.Einde: case Source.DataKind.Instruction: throw new Exception($"Internal error! Illegal instruction parameter! {p.Kind}"); case Source.DataKind.Index: CurrentChunk.Add((byte)Source.DataKind.Index); break; case Source.DataKind.Chunk: case Source.DataKind.String: case Source.DataKind.LocalVar: case Source.DataKind.GlobalVar: case Source.DataKind.API: CurrentChunk.Add((byte)p.Kind); CurrentChunk.Add(p.StrValue); break; case Source.DataKind.Label: CurrentChunk.Add((byte)Source.DataKind.Label); CurrentChunk.RequestedLabels[CurrentChunk.Length] = p.StrValue.ToString(); Debug.WriteLine($"Label {p.StrValue} requested at offset {CurrentChunk.Length}"); CurrentChunk.Add((int)0); break; case Source.DataKind.Reference: throw new Exception("No support for referrence (yet)"); case Source.DataKind.IntValue: CurrentChunk.Add((byte)Source.DataKind.IntValue); CurrentChunk.Add(p.intvalue); break; case Source.DataKind.FloatValue: throw new Exception("No support for float yet"); case Source.DataKind.Boolean: { var c = p.StrValue.ToString().ToUpper() == "TRUE" || p.StrValue.ToString().ToUpper() == "YES"; CurrentChunk.Add((byte)Source.DataKind.Boolean); CurrentChunk.Add((byte)p.intvalue); break; } case Source.DataKind.Null: CurrentChunk.Add((byte)12); break; default: throw new Exception($"Unknown datakind {p.Kind}! Source version conflict? Internal error?"); } } CurrentChunk.Add((byte)0); Debug.WriteLine($"Instruction {L.Instruction} ended"); } } for (int p = 0; p < lastspace; p++) { WASM_Main.VT(" "); } WASM_Main.VT("\r"); VP($" Saving: {ofile}"); foreach (string k in Chunks.Keys) { var Chnk = Chunks[k]; Debug.WriteLine($"Chunk: {k}"); Debug.WriteLine("= Configuring Labels"); foreach (int ofs in Chnk.RequestedLabels.Keys) { var Lab = Chnk.RequestedLabels[ofs]; var o = BitConverter.GetBytes(Chnk.Labels[Lab]); Debug.WriteLine($" = {ofs} => {Lab}"); if (!BitConverter.IsLittleEndian) { Array.Reverse(o); } for (byte i = 0; i < 4; ++i) { Chnk.buffer[ofs + i] = o[i]; } } Debug.WriteLine("= Writing Chunk Buffer"); bo.WriteByte((byte)Source.DataKind.StartChunk); bo.WriteByte(1); bo.WriteString(k); bo.WriteByte(2); bo.WriteInt(Chnk.buffer.Length); bo.WriteByte(0); bo.WriteBytes(Chnk.buffer); bo.WriteByte(0); } bo.WriteString("WBIN", true); bo.WriteInt((int)bo.Size + 4); bo.WriteString("WBIN", true); } catch (Exception e) { WASM_Main.VP("\n"); WASM_Main.Error(e); } finally { bo.Close(); } }