- Timestamp:
- Aug 1, 2024, 10:47:04 PM (4 months ago)
- Location:
- branches/bigint
- Files:
-
- 4 added
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/bigint/Assembler.pas
r2 r4 4 4 5 5 uses 6 Classes, SysUtils; 6 Classes, SysUtils, Instructions, Cpu, Generics.Collections, 7 Memory, Message, Parser, Int; 7 8 8 9 type 10 { TLabelRef } 11 12 TLabelRef = record 13 LabelName: string; 14 RefPos: Integer; 15 TextPos: TPoint; 16 class function Create(LabelName: string; RefPos: Integer): TLabelRef; static; 17 end; 9 18 10 19 { TAssembler } 11 20 12 21 TAssembler = class 13 Lines: TStringList; 14 procedure Assemble; 22 private 23 FOnError: TErrorEvent; 24 Parser: TParser; 25 function ParseVar: Boolean; 26 function ParseDb: Boolean; 27 function ParseOrg: Boolean; 28 function ParseInstruction: Boolean; 29 function ParseLabel: Boolean; 30 procedure UpdateLabelRefs; 31 procedure ParseNumParam(Token: TToken); 32 public 33 InstructionSet: TInstructionSet; 34 Memory: TMemory; 35 Labels: TDictionary<string, TInt>; 36 LabelRefs: TList<TLabelRef>; 37 Variables: TDictionary<string, TInt>; 38 Message: TMessages; 39 procedure Error(Text: string; Pos: TPoint); 40 procedure Compile(Source: string); 41 procedure LoadFromFile(FileName: string); 42 function ParseStr(var Text: string; Separator: string): string; 15 43 constructor Create; 16 44 destructor Destroy; override; 45 property OnError: TErrorEvent read FOnError write FOnError; 17 46 end; 18 47 … … 20 49 implementation 21 50 51 { TLabelRef } 52 53 class function TLabelRef.Create(LabelName: string; RefPos: Integer): TLabelRef; 54 begin 55 Result.LabelName := LabelName; 56 Result.RefPos := RefPos; 57 end; 58 22 59 { TAssembler } 23 60 24 procedure TAssembler.Assemble; 25 begin 26 61 procedure TAssembler.UpdateLabelRefs; 62 var 63 I: Integer; 64 Addr: TInt; 65 begin 66 for I := 0 to LabelRefs.Count - 1 do begin 67 if Labels.TryGetValue(LabelRefs[I].LabelName, Addr) then 68 Memory[LabelRefs[I].RefPos] := Addr 69 else Error('Label ' + LabelRefs[I].LabelName + ' referenced but not defined.', LabelRefs[I].TextPos); 70 end; 71 end; 72 73 procedure TAssembler.ParseNumParam(Token: TToken); 74 var 75 Addr: TInt; 76 begin 77 if Token.Kind = tkNumber then begin 78 if TryStrToInt64(Token.Value, Addr) then begin 79 Memory.WritePos(Addr); 80 end; 81 end else 82 if Token.Kind = tkIdentifier then begin; 83 if Variables.TryGetValue(Token.Value, Addr) then begin 84 Memory.WritePos(Addr); 85 end else 86 if Labels.TryGetValue(Token.Value, Addr) then begin 87 Memory.WritePos(Addr); 88 end else begin 89 LabelRefs.Add(TLabelRef.Create(Token.Value, Memory.Position)); 90 Memory.WritePos(0); 91 end; 92 end else Error('Unexpected token ' + Token.Value + '.', Token.Pos); 93 end; 94 95 procedure TAssembler.Error(Text: string; Pos: TPoint); 96 begin 97 Message.AddMessage(Text, Pos); 98 if Assigned(FOnError) then 99 FOnError(Text, Pos); 100 end; 101 102 procedure TAssembler.Compile(Source: string); 103 begin 104 Message.Clear; 105 Memory.Size := 10000; 106 Labels.Clear; 107 LabelRefs.Clear; 108 Parser.Reset; 109 Parser.Source := Source; 110 while not Parser.CheckNextKind(tkEof) do begin 111 ParseLabel; 112 if ParseVar then begin 113 end else 114 if ParseDb then begin 115 end else 116 if ParseOrg then begin 117 end else 118 if ParseInstruction then begin 119 end; 120 if Parser.CheckNextKind(tkEof) then begin 121 end else Parser.Expect(tkEol); 122 end; 123 Parser.Expect(tkEof); 124 UpdateLabelRefs; 125 Memory.Size := Memory.Position; 126 Error('Compilation finished.', Point(0, 0)); 127 end; 128 129 function TAssembler.ParseVar: Boolean; 130 var 131 TokenName: TToken; 132 TokenValue: TToken; 133 Number: TInt; 134 begin 135 Result := False; 136 if Parser.CheckNextAndRead(tkIdentifier, 'VAR') then begin 137 Result := True; 138 while True do begin 139 TokenName := Parser.ReadNext; 140 if TokenName.Kind = tkIdentifier then begin 141 TokenValue := Parser.ReadNext; 142 if TokenValue.Kind = tkNumber then begin 143 if not Labels.ContainsKey(TokenName.Value) and not Variables.ContainsKey(TokenName.Value) then begin 144 if TryStrToInt64(TokenValue.Value, Number) then 145 Variables.Add(TokenName.Value, Number) 146 else Error('Expected number', TokenValue.Pos); 147 end else Error('Duplicate variable name ' + TokenName.Value, TokenName.Pos); 148 end else Error('Expected variable value.', TokenValue.Pos); 149 end else Error('Expected variable name.', TokenName.Pos); 150 if Parser.CheckNextAndRead(tkSpecialSymbol, ',') then begin 151 Continue; 152 end; 153 Break; 154 end; 155 end; 156 end; 157 158 function TAssembler.ParseDb: Boolean; 159 var 160 Token: TToken; 161 begin 162 Result := False; 163 if Parser.CheckNextAndRead(tkIdentifier, 'DB') then begin 164 Result := True; 165 while True do begin 166 Token := Parser.ReadNext; 167 if Token.Kind = tkString then begin 168 Memory.WriteStringPos(Token.Value); 169 end else 170 ParseNumParam(Token); 171 if Parser.CheckNextAndRead(tkSpecialSymbol, ',') then begin 172 Continue; 173 end; 174 Break; 175 end; 176 end; 177 end; 178 179 function TAssembler.ParseOrg: Boolean; 180 var 181 Token: TToken; 182 begin 183 Result := False; 184 if Parser.CheckNextAndRead(tkIdentifier, 'ORG') then begin 185 Result := True; 186 Token := Parser.ReadNext; 187 if Token.Kind = tkNumber then begin 188 Memory.Position := StrToInt(Token.Value); 189 end else Error('Expected number but ' + Token.Value + ' found.', Token.Pos); 190 end; 191 end; 192 193 function TAssembler.ParseInstruction: Boolean; 194 var 195 InstructionInfo: TInstructionInfo; 196 I: Integer; 197 Token: TToken; 198 LastPos: TParserPos; 199 Number: Integer; 200 begin 201 Result := False; 202 LastPos := Parser.Pos; 203 Token := Parser.ReadNext; 204 InstructionInfo := InstructionSet.SearchName(Token.Value); 205 if Assigned(InstructionInfo) then begin 206 Result := True; 207 Memory.WritePos(TInt(InstructionInfo.Instruction)); 208 for I := 0 to Length(InstructionInfo.Params) - 1 do begin 209 if I > 0 then 210 Parser.Expect(tkSpecialSymbol, ','); 211 if InstructionInfo.Params[I] = ptNumber then begin 212 Token := Parser.ReadNext; 213 ParseNumParam(Token); 214 end else 215 if InstructionInfo.Params[I] = ptIndirect then begin 216 Parser.Expect(tkSpecialSymbol, '('); 217 Token := Parser.ReadNext; 218 if TryStrToInt(Token.Value, Number) then 219 Memory.WritePos(Number) 220 else Error('Expected numeric index error', Token.Pos); 221 Parser.Expect(tkSpecialSymbol, ')'); 222 end else raise Exception.Create('Unsupported parameter type'); 223 end; 224 end; 225 if not Result then Parser.Pos := LastPos; 226 end; 227 228 function TAssembler.ParseLabel: Boolean; 229 var 230 LastPos: TParserPos; 231 Token: TToken; 232 Addr: TInt; 233 begin 234 Result := False; 235 LastPos := Parser.Pos; 236 Token := Parser.ReadNext; 237 if Parser.CheckNextAndRead(tkSpecialSymbol, ':') then begin 238 Result := True; 239 if not Labels.TryGetValue(Token.Value, Addr) then begin 240 Labels.Add(Token.Value, Memory.Position); 241 end else Error('Duplicate label ' + Token.Value + '.', Token.Pos); 242 end; 243 if not Result then Parser.Pos := LastPos; 244 end; 245 246 procedure TAssembler.LoadFromFile(FileName: string); 247 var 248 Lines: TStringList; 249 begin 250 Lines := TStringList.Create; 251 try 252 Lines.LoadFromFile(FileName); 253 Compile(Lines.Text); 254 finally 255 Lines.Free; 256 end; 257 end; 258 259 function TAssembler.ParseStr(var Text: string; Separator: string): string; 260 var 261 P: Integer; 262 begin 263 P := Pos(Separator, Text); 264 if P > 0 then begin 265 Result := Trim(Copy(Text, 1, P - 1)); 266 Text := Trim(Copy(Text, P + 1, MaxInt)); 267 end else begin 268 Result := Trim(Text); 269 Text := ''; 270 end; 27 271 end; 28 272 29 273 constructor TAssembler.Create; 30 274 begin 31 Lines := TStringList.Create; 275 Parser := TParser.Create; 276 Parser.OnError := Error; 277 Message := TMessages.Create; 278 Memory := TMemory.Create; 279 InstructionSet := TInstructionSet.Create; 280 Labels := TDictionary<string, TInt>.Create; 281 LabelRefs := TList<TLabelRef>.Create; 282 Variables := TDictionary<string, TInt>.Create; 32 283 end; 33 284 34 285 destructor TAssembler.Destroy; 35 286 begin 36 FreeAndNil(Lines); 287 FreeAndNil(Variables); 288 FreeAndNil(Labels); 289 FreeAndNil(LabelRefs); 290 FreeAndNil(InstructionSet); 291 FreeAndNil(Memory); 292 FreeAndNil(Message); 293 FreeAndNil(Parser); 37 294 inherited; 38 295 end; -
branches/bigint/BigIntVM.lpi
r2 r4 118 118 <IsPartOfProject Value="True"/> 119 119 </Unit> 120 <Unit> 121 <Filename Value="Instructions.pas"/> 122 <IsPartOfProject Value="True"/> 123 </Unit> 124 <Unit> 125 <Filename Value="Parser.pas"/> 126 <IsPartOfProject Value="True"/> 127 </Unit> 128 <Unit> 129 <Filename Value="Message.pas"/> 130 <IsPartOfProject Value="True"/> 131 </Unit> 132 <Unit> 133 <Filename Value="Example.asm"/> 134 <IsPartOfProject Value="True"/> 135 </Unit> 120 136 </Units> 121 137 </ProjectOptions> -
branches/bigint/BigIntVM.lpr
r2 r4 10 10 Interfaces, // this includes the LCL widgetset 11 11 Forms, FormMain, Cpu, Memory, Int, Machine, DeviceManager, Screen, Console, 12 Device, Assembler 12 Device, Assembler, Instructions, Parser, Message 13 13 { you can add units after this }; 14 14 -
branches/bigint/FormMain.pas
r3 r4 5 5 uses 6 6 Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, Machine, Int, 7 Cpu ;7 Cpu, Assembler; 8 8 9 9 type … … 45 45 procedure TFormMain.FormShow(Sender: TObject); 46 46 var 47 Label1: TInt; 47 Assembler: TAssembler; 48 Lines: TStringList; 48 49 begin 49 with Machine.Memory do begin 50 WritePos(TInt(inLoadConst)); 51 WritePos(1000); 52 WritePos(Ord('A')); 50 Lines := TStringList.Create; 51 Lines.LoadFromFile('Example.asm'); 53 52 54 WritePos(TInt(inLoadConst)); 55 WritePos(1001); 56 WritePos(20); 53 Assembler := TAssembler.Create; 54 with Assembler do begin 55 Compile(Lines.Text); 56 Machine.Memory.CopyFrom(Memory, 0, 0, Memory.Size); 57 Free; 58 end; 57 59 58 Label1 := Position;60 Lines.Free; 59 61 60 WritePos(TInt(inOutput));61 WritePos(0);62 WritePos(1000);63 64 WritePos(TInt(inInc));65 WritePos(1000);66 67 WritePos(TInt(inDec));68 WritePos(1001);69 70 WritePos(TInt(inJumpNotZero));71 WritePos(1001);72 WritePos(Label1);73 74 WritePos(TInt(inHalt));75 end;76 62 Machine.Run; 77 63 end; -
branches/bigint/Memory.pas
r3 r4 21 21 procedure WritePos(Data: TInt); 22 22 function ReadPos: TInt; 23 procedure CopyFrom(Source: TMemory; Dst, Src, Count: TInt); 24 procedure WriteStringPos(Value: string); 23 25 property Size: TInt read GetSize write SetSize; 24 26 property Position: TInt read FPosition write FPosition; 27 property Items[Index: TInt]: TInt read Read write Write; default; 25 28 end; 26 29 … … 62 65 end; 63 66 67 procedure TMemory.CopyFrom(Source: TMemory; Dst, Src, Count: TInt); 68 var 69 I: Integer; 70 begin 71 for I := 0 to Count - 1 do begin 72 Write(Dst, Source.Read(Src)); 73 Inc(Dst); 74 Inc(Src); 75 end; 76 end; 77 78 procedure TMemory.WriteStringPos(Value: string); 79 var 80 I: Integer; 81 begin 82 if Length(Value) > 0 then begin 83 if Position + Length(Value) > Size then Size := Position + Length(Value); 84 for I := 0 to Length(Value) - 1 do 85 Items[Position + I] := Ord(Value[I + 1]); 86 Inc(FPosition, Length(Value)); 87 end; 88 end; 89 64 90 end. 65 91
Note:
See TracChangeset
for help on using the changeset viewer.