diff --git a/src/SVM.Assembler.Core/Assembler.cs b/src/SVM.Assembler.Core/Assembler.cs index 1887fda..ca61290 100644 --- a/src/SVM.Assembler.Core/Assembler.cs +++ b/src/SVM.Assembler.Core/Assembler.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; namespace SVM.Assembler.Core { + public delegate OperationResult AssemblerFunction(ILexer lexer, IntermediateInstruction instruction, LexSegment leadingSegment); public class Assembler { public const string LexDefinition = @@ -54,6 +55,7 @@ LabelData InternalLbl LabelConstant InternalLbl "; LexerDefinition? definition; + public Dictionary assemblerFunctions = new Dictionary(); public Assembler() { if (LexerDefinition.TryParse(LexDefinition, out definition)) @@ -61,17 +63,73 @@ LabelConstant InternalLbl definition.Substitute(); } } - public OperationResult Assemble(string input, string ID = "main.asm") + public OperationResult Lex(ILexer lexer) + { + while (true) + { + var r = lexer.Lex(); + if (r.HasError()) return r; + if (r.Result == null) return r; + if (r.Result.LexSegmentId != null && r.Result.LexMatchedItemId != null) + { + return r; + } + } + } + public OperationResult<(string, string)?> ParseKVPair(ILexer lexer, LexSegment currentSeg) + { + OperationResult<(string, string)?> operationResult = new OperationResult<(string, string)?>(null); + var r = Lex(lexer); + if (operationResult.CheckAndInheritErrorAndWarnings(r)) { return operationResult; } + if (currentSeg.Content == null) return operationResult; + if (r.Result == null) return operationResult; + if (r.Result.Content == null) return operationResult; + return (currentSeg.Content, r.Result.Content); + } + private OperationResult ParseInstruction(StringLexer lexer, LexSegment CurrentSeg, LexSegment? Label) + { + OperationResult operationResult = new OperationResult(null); + IntermediateInstruction intermediateInstruction = new IntermediateInstruction(); + intermediateInstruction.Label = Label; + LexSegment LexDef; + if (Label is null) + { + LexDef = CurrentSeg; + } + else + { + var next = Lex(lexer); + if (operationResult.CheckAndInheritErrorAndWarnings(next)) + { + return operationResult; + } + if (next.Result is null) + { + return operationResult; + } + LexDef = next.Result; + } + if (LexDef.LexMatchedItemId == null) + { + return operationResult; + } + if (!assemblerFunctions.TryGetValue(LexDef.LexMatchedItemId, out var assemblerFunction)) + { + return operationResult; + } + return assemblerFunction(lexer, intermediateInstruction, LexDef); + } + public OperationResult AssembleIntermediateObject(string input, string ID = "main.asm") { StringLexer lexer = new StringLexer(); lexer.SetDefinition(definition); lexer.Content = input; lexer.SourceID = ID; - OperationResult operationResult = new OperationResult(); + OperationResult operationResult = new OperationResult(new IntermediateObject()); InternalLabel CurrentLabel = InternalLabel.Code; while (true) { - var lexResult = lexer.Lex(); + var lexResult = Lex(lexer); if (lexResult.Result == null) break; var r = lexResult.Result; switch (r.LexSegmentId) @@ -96,17 +154,47 @@ LabelConstant InternalLbl switch (CurrentLabel) { case InternalLabel.Code: - switch (r.LexSegmentId) { - case "GenericLabel": - break; - default: - break; + OperationResult instR = r.LexSegmentId switch + { + "GenericLabel" => ParseInstruction(lexer, r, r), + _ => ParseInstruction(lexer, r, null), + }; + if (operationResult.CheckAndInheritErrorAndWarnings(instR)) + { + return operationResult; + } + if (instR.Result is null) return operationResult; + operationResult.Result.instructions.Add(instR.Result); } break; case InternalLabel.Data: + { + var KV = ParseKVPair(lexer, r); + if (operationResult.CheckAndInheritErrorAndWarnings(KV)) + { + return operationResult; + } + if (KV.Result == null) + { + return operationResult; + } + operationResult.Result.data.Add(KV.Result.Value.Item1, KV.Result.Value.Item2); + } break; case InternalLabel.Const: + { + var KV = ParseKVPair(lexer, r); + if (operationResult.CheckAndInheritErrorAndWarnings(KV)) + { + return operationResult; + } + if (KV.Result == null) + { + return operationResult; + } + operationResult.Result.consts.Add(KV.Result.Value.Item1, KV.Result.Value.Item2); + } break; default: break; @@ -132,7 +220,7 @@ LabelConstant InternalLbl [Serializable] public class IntermediateInstruction { - public string? Label = null; + public LexSegment? Label = null; public PrimaryInstruction inst; public List Parameters = new List(); } diff --git a/src/SVM.Assembler.Core/Linker.cs b/src/SVM.Assembler.Core/Linker.cs new file mode 100644 index 0000000..168caf3 --- /dev/null +++ b/src/SVM.Assembler.Core/Linker.cs @@ -0,0 +1,43 @@ +using LibCLCC.NET.Operations; +using SVM.Core; +using System.Collections.Generic; + +namespace SVM.Assembler.Core +{ + public class Linker + { + public static OperationResult Link(List objs) + { + OperationResult operationResult = new OperationResult(null); + IntermediateObject intermediateObject = new IntermediateObject(); + foreach (var item in objs) + { + foreach (var inst in item.instructions) + { + intermediateObject.instructions.Add(inst); + } + foreach (var data in item.data) + { + if (!intermediateObject.data.TryAdd(data.Key, data.Value)) + { + intermediateObject.data[data.Key] = data.Value; + } + } + foreach (var kv in item.consts) + { + if (!intermediateObject.consts.TryAdd(kv.Key, kv.Value)) + { + intermediateObject.consts[kv.Key] = kv.Value; + } + } + } + return operationResult; + } + public static OperationResult Freeze(List objs) + { + OperationResult operationResult = new OperationResult(null); + + return operationResult; + } + } +} diff --git a/src/SVM.Core/SVMProgram.cs b/src/SVM.Core/SVMProgram.cs index 4e5b027..9fba929 100644 --- a/src/SVM.Core/SVMProgram.cs +++ b/src/SVM.Core/SVMProgram.cs @@ -1,9 +1,15 @@ using SVM.Core.Utils; using System; +using System.Collections.Generic; using System.IO; using static SVM.Core.stdc.stdlib; namespace SVM.Core { + public unsafe class ManagedSVMProgram + { + public List instructions = new List(); + public List Datas = new List(); + } public unsafe struct SVMProgram : IDisposable { public UInt64 InstructionCount;