diff --git a/STCompiler.Common/Bytecode.cs b/STCompiler.Common/Bytecode.cs index 993aeb1..830ce0e 100644 --- a/STCompiler.Common/Bytecode.cs +++ b/STCompiler.Common/Bytecode.cs @@ -40,6 +40,9 @@ public static class Bytecode { public const byte JZ = 0x70; public const byte JMP = 0x71; + // Array operations + public const byte ARRAY_BOUNDS_CHECK = 0xE0; + public const byte HALT = 0xF0; } @@ -63,6 +66,7 @@ public static class Bytecode { { OpCodes.LT_U, "LT_U" }, { OpCodes.GT_U, "GT_U" }, { OpCodes.LE_U, "LE_U" }, { OpCodes.GE_U, "GE_U" }, { OpCodes.EQ_U, "EQ_U" }, { OpCodes.NEQ_U, "NEQ_U" }, { OpCodes.LT_F, "LT_F" }, { OpCodes.GT_F, "GT_F" }, { OpCodes.LE_F, "LE_F" }, { OpCodes.GE_F, "GE_F" }, { OpCodes.EQ_F, "EQ_F" }, { OpCodes.NEQ_F, "NEQ_F" }, { OpCodes.JZ, "JZ" }, { OpCodes.JMP, "JMP" }, + { OpCodes.ARRAY_BOUNDS_CHECK, "ARRAY_BOUNDS_CHECK" }, { OpCodes.HALT, "HALT" } }; diff --git a/STCompiler.Common/VarType.cs b/STCompiler.Common/VarType.cs index e2d1b8c..15dfa24 100644 --- a/STCompiler.Common/VarType.cs +++ b/STCompiler.Common/VarType.cs @@ -18,5 +18,24 @@ public enum VarType { TIME_OF_DAY = 18, // Tageszeit (TOD) -> TimeSpan / DateTime TOD = TIME_OF_DAY, DATE_AND_TIME = 19,// Datum + Uhrzeit (DT) -> DateTime - DT = DATE_AND_TIME + DT = DATE_AND_TIME, + // Array marker - actual array types use ArrayType class + ARRAY = 20 +} + +// Represents an array type in structured text +public class ArrayType { + public VarType ElementType { get; set; } // Type of array elements + public int Start { get; set; } // Start index + public int End { get; set; } // End index + public int Length => End - Start + 1; // Number of elements + + public ArrayType(VarType elementType, int start, int end) { + ElementType = elementType; + Start = start; + End = end; + if (end < start) throw new System.ArgumentException("Array end index must be greater than or equal to start index"); + } + + public override string ToString() => $"ARRAY [{Start}..{End}] OF {ElementType}"; } diff --git a/STCompiler.Common/bin/Debug/net8.0/STCompiler.Common.dll b/STCompiler.Common/bin/Debug/net8.0/STCompiler.Common.dll index ea9b04b..f181d40 100644 Binary files a/STCompiler.Common/bin/Debug/net8.0/STCompiler.Common.dll and b/STCompiler.Common/bin/Debug/net8.0/STCompiler.Common.dll differ diff --git a/STCompiler.Common/bin/Debug/net8.0/STCompiler.Common.pdb b/STCompiler.Common/bin/Debug/net8.0/STCompiler.Common.pdb index 8486650..ba33997 100644 Binary files a/STCompiler.Common/bin/Debug/net8.0/STCompiler.Common.pdb and b/STCompiler.Common/bin/Debug/net8.0/STCompiler.Common.pdb differ diff --git a/STCompiler.Common/obj/Debug/net8.0/STCompiler.Common.AssemblyInfo.cs b/STCompiler.Common/obj/Debug/net8.0/STCompiler.Common.AssemblyInfo.cs index 84adce7..8578b27 100644 --- a/STCompiler.Common/obj/Debug/net8.0/STCompiler.Common.AssemblyInfo.cs +++ b/STCompiler.Common/obj/Debug/net8.0/STCompiler.Common.AssemblyInfo.cs @@ -13,10 +13,10 @@ using System.Reflection; [assembly: System.Reflection.AssemblyCompanyAttribute("STCompiler.Common")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] -[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+ec4d7dc26ee2fd96db003ab3a6c1af70e02894b9")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+3cb63739152cd26ec43993953c7b93d4ab9bcce7")] [assembly: System.Reflection.AssemblyProductAttribute("STCompiler.Common")] [assembly: System.Reflection.AssemblyTitleAttribute("STCompiler.Common")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] -// Von der MSBuild WriteCodeFragment-Klasse generiert. +// Generated by the MSBuild WriteCodeFragment class. diff --git a/STCompiler.Common/obj/Debug/net8.0/STCompiler.Common.AssemblyInfoInputs.cache b/STCompiler.Common/obj/Debug/net8.0/STCompiler.Common.AssemblyInfoInputs.cache index e00287e..f1af4aa 100644 --- a/STCompiler.Common/obj/Debug/net8.0/STCompiler.Common.AssemblyInfoInputs.cache +++ b/STCompiler.Common/obj/Debug/net8.0/STCompiler.Common.AssemblyInfoInputs.cache @@ -1 +1 @@ -8cfdc237030ec5222d5f9b3cae794a2e89120fd57c83b878660304653c51962d +72a5aa37f3f499d7234a1ea9f8597714d83c5061f8d255b5e45126805bf484a2 diff --git a/STCompiler.Common/obj/Debug/net8.0/STCompiler.Common.dll b/STCompiler.Common/obj/Debug/net8.0/STCompiler.Common.dll index ea9b04b..f181d40 100644 Binary files a/STCompiler.Common/obj/Debug/net8.0/STCompiler.Common.dll and b/STCompiler.Common/obj/Debug/net8.0/STCompiler.Common.dll differ diff --git a/STCompiler.Common/obj/Debug/net8.0/STCompiler.Common.pdb b/STCompiler.Common/obj/Debug/net8.0/STCompiler.Common.pdb index 8486650..ba33997 100644 Binary files a/STCompiler.Common/obj/Debug/net8.0/STCompiler.Common.pdb and b/STCompiler.Common/obj/Debug/net8.0/STCompiler.Common.pdb differ diff --git a/STCompiler.Common/obj/Debug/net8.0/ref/STCompiler.Common.dll b/STCompiler.Common/obj/Debug/net8.0/ref/STCompiler.Common.dll index 6187086..e562ae5 100644 Binary files a/STCompiler.Common/obj/Debug/net8.0/ref/STCompiler.Common.dll and b/STCompiler.Common/obj/Debug/net8.0/ref/STCompiler.Common.dll differ diff --git a/STCompiler.Common/obj/Debug/net8.0/refint/STCompiler.Common.dll b/STCompiler.Common/obj/Debug/net8.0/refint/STCompiler.Common.dll index 6187086..e562ae5 100644 Binary files a/STCompiler.Common/obj/Debug/net8.0/refint/STCompiler.Common.dll and b/STCompiler.Common/obj/Debug/net8.0/refint/STCompiler.Common.dll differ diff --git a/STCompiler.Compiler/Ast.cs b/STCompiler.Compiler/Ast.cs index 2aa2789..66ef028 100644 --- a/STCompiler.Compiler/Ast.cs +++ b/STCompiler.Compiler/Ast.cs @@ -13,8 +13,9 @@ public class VarDecl:StNode{ public abstract class Stmt:StNode{} public class AssignStmt:Stmt{ - required public string Target; - required public Expr Expr; + required public string Target; // Variable name + public Expr? Index; // Array index if this is an array assignment + required public Expr Expr; // Value to assign } public class IfStmt:Stmt{ required public Expr Cond; @@ -81,3 +82,13 @@ public class BinaryExpr:Expr { return right; } } +public class ArrayAccessExpr : Expr { + public string ArrayName; + public Expr Index; + + public ArrayAccessExpr(string name, Expr idx, VarType elementType) { + ArrayName = name; + Index = idx; + Type = elementType; + } +} diff --git a/STCompiler.Compiler/Lexer.cs b/STCompiler.Compiler/Lexer.cs index 369b7b4..6cf416c 100644 --- a/STCompiler.Compiler/Lexer.cs +++ b/STCompiler.Compiler/Lexer.cs @@ -13,6 +13,7 @@ public enum TokType { WHILE, DO, END_WHILE, FOR, TO, BY, END_FOR, PROGRAM, VAR, END_VAR, END_PROGRAM, + ARRAY, OF, LBRACKET, RBRACKET, DOTS, EOF } @@ -83,6 +84,8 @@ public class StLexer { "TO"=>new Token(TokType.TO,s,startLine), "BY"=>new Token(TokType.BY,s,startLine), "END_FOR"=>new Token(TokType.END_FOR,s,startLine), + "ARRAY"=>new Token(TokType.ARRAY,s,startLine), + "OF"=>new Token(TokType.OF,s,startLine), _=>new Token(TokType.IDENT,s,startLine) }; } @@ -92,16 +95,23 @@ public class StLexer { int startLine = currentLine; bool isFloat = false; - // Ganze Zahl vor dem Dezimalpunkt + // Ganze Zahl vor dem Dezimalpunkt oder Bereichsoperator while(char.IsDigit(Peek())) sb.Append(Next()); - // Optional: Dezimalpunkt und Nachkommastellen + // Prüfe auf Bereichsoperator (..) oder Dezimalpunkt (.) if (Peek() == '.') { - isFloat = true; - sb.Append(Next()); - while(char.IsDigit(Peek())) + if (Peek2() == '.') { + // Es ist ein Bereichsoperator (..) + // Don't consume the dots, just return the number + return new Token(TokType.INT, sb.ToString(), startLine); + } else { + // Es ist ein Dezimalpunkt + isFloat = true; sb.Append(Next()); + while(char.IsDigit(Peek())) + sb.Append(Next()); + } } // Optional: Exponentialdarstellung @@ -150,10 +160,21 @@ public class StLexer { if (c == ';') return new Token(TokType.SEMI,";",tokenLine); if (c == '(') return new Token(TokType.LPAREN,"(",tokenLine); if (c == ')') return new Token(TokType.RPAREN,")",tokenLine); + if (c == '[') return new Token(TokType.LBRACKET,"[",tokenLine); + if (c == ']') return new Token(TokType.RBRACKET,"]",tokenLine); if (c == '+') return new Token(TokType.PLUS,"+",tokenLine); if (c == '-') return new Token(TokType.MINUS,"-",tokenLine); if (c == '*') return new Token(TokType.MUL,"*",tokenLine); if (c == '/') return new Token(TokType.DIV,"/",tokenLine); + if (c == '.') { + if (Peek() == '.') { + Next(); + return new Token(TokType.DOTS,"..",tokenLine); + } + // Put back the dot for floating point numbers + i--; + return NextToken(); + } AddError($"Unexpected character '{c}'"); return new Token(TokType.EOF,"",tokenLine); // Skip invalid character diff --git a/STCompiler.Compiler/Parser.cs b/STCompiler.Compiler/Parser.cs index ea715e8..411d3b2 100644 --- a/STCompiler.Compiler/Parser.cs +++ b/STCompiler.Compiler/Parser.cs @@ -14,6 +14,7 @@ public class StParser { StLexer lex; Token cur; Dictionary syms = new(); + public Dictionary arrayTypes = new(); // Add dictionary for array types public List Errors => lex.Errors; public bool HasErrors => Errors.Count > 0; @@ -61,42 +62,96 @@ public class StParser { return p; } + VarType? ParseType(string varName) { + if (cur.Type == TokType.ARRAY) { + Next(); // Skip ARRAY + if (!Expect(TokType.LBRACKET)) return null; + var start = ParseExpr(); + if (start == null || start is not IntExpr startInt) { + AddError("Array start index must be an integer constant"); + return null; + } + if (!Expect(TokType.DOTS)) return null; + var end = ParseExpr(); + if (end == null || end is not IntExpr endInt) { + AddError("Array end index must be an integer constant"); + return null; + } + if (!Expect(TokType.RBRACKET)) return null; + if (!Expect(TokType.OF)) return null; + if (cur.Type != TokType.IDENT) { + AddError("Expected element type name after OF"); + return null; + } + string elemTypeName = cur.Text.ToLowerInvariant(); + Next(); + + VarType? elementType = elemTypeName switch { + "bool" => VarType.BOOL, + "byte" => VarType.BYTE, + "word" => VarType.WORD, + "dword" => VarType.DWORD, + "lword" => VarType.LWORD, + "sint" => VarType.SINT, + "int" => VarType.INT, + "dint" => VarType.DINT, + "lint" => VarType.LINT, + "usint" => VarType.USINT, + "uint" => VarType.UINT, + "udint" => VarType.UDINT, + "ulint" => VarType.ULINT, + "real" => VarType.REAL, + "lreal" => VarType.LREAL, + _ => null + }; + + if (elementType == null) { + AddError($"Unknown element type '{elemTypeName}'"); + return null; + } + + arrayTypes[varName] = new ArrayType(elementType.Value, (int)startInt.Value, (int)endInt.Value); + return VarType.ARRAY; + } + else if (cur.Type == TokType.IDENT) { + string typeName = cur.Text.ToLowerInvariant(); + Next(); + + return typeName switch { + "bool" => VarType.BOOL, + "byte" => VarType.BYTE, + "word" => VarType.WORD, + "dword" => VarType.DWORD, + "lword" => VarType.LWORD, + "sint" => VarType.SINT, + "int" => VarType.INT, + "dint" => VarType.DINT, + "lint" => VarType.LINT, + "usint" => VarType.USINT, + "uint" => VarType.UINT, + "udint" => VarType.UDINT, + "ulint" => VarType.ULINT, + "real" => VarType.REAL, + "lreal" => VarType.LREAL, + _ => null + }; + } + + AddError("Expected type name or ARRAY"); + return null; + } + VarDecl? ParseVarDecl(){ if (cur.Type != TokType.IDENT) { AddError("Expected identifier for variable declaration"); return null; } - string name=cur.Text.ToUpperInvariant(); // Variablennamen in Großbuchstaben + string name = cur.Text.ToUpperInvariant(); // Variablennamen in Großbuchstaben Next(); - if (cur.Type != TokType.IDENT) { - AddError("Expected type name"); - return null; - } - string tname=cur.Text.ToLowerInvariant(); - Next(); - - VarType? vt = tname switch { - "bool" => VarType.BOOL, - "byte" => VarType.BYTE, - "word" => VarType.WORD, - "dword" => VarType.DWORD, - "lword" => VarType.LWORD, - "sint" => VarType.SINT, - "int" => VarType.INT, - "dint" => VarType.DINT, - "lint" => VarType.LINT, - "usint" => VarType.USINT, - "uint" => VarType.UINT, - "udint" => VarType.UDINT, - "ulint" => VarType.ULINT, - "real" => VarType.REAL, - "lreal" => VarType.LREAL, - _ => null - }; - + var vt = ParseType(name); if (vt == null) { - AddError($"Unknown type '{tname}'"); + AddError($"Invalid type for variable '{name}'"); return null; } @@ -121,6 +176,26 @@ public class StParser { Stmt? ParseAssign() { string target = cur.Text.ToUpperInvariant(); Next(); // consume identifier + + // Check if this is an array assignment + Expr? index = null; + if (cur.Type == TokType.LBRACKET) { + Symbol? sym; + if (!syms.TryGetValue(target, out sym)) { + AddError($"Undeclared variable '{target}'"); + return null; + } + if (sym.Type != VarType.ARRAY) { + AddError($"Cannot use array indexing on non-array variable '{target}'"); + return null; + } + + Next(); // consume [ + index = ParseExpr(); + if (index == null) return null; + if (!Expect(TokType.RBRACKET)) return null; + } + if (cur.Type != TokType.ASSIGN) { AddError($"Expected ':=' after identifier '{target}'"); return null; @@ -129,7 +204,7 @@ public class StParser { var e = ParseExpr(); if (e == null) return null; if (!Expect(TokType.SEMI)) return null; - return new AssignStmt{Target=target, Expr=e}; + return new AssignStmt{Target=target, Index=index, Expr=e}; } Stmt? ParseStmt(){ @@ -318,6 +393,29 @@ public class StParser { AddError($"Undeclared variable '{n}'"); return null; } + + // Check for array access + if (cur.Type == TokType.LBRACKET) { + if (sym.Type != VarType.ARRAY) { + AddError($"Cannot index non-array variable '{n}'"); + return null; + } + + Next(); // consume [ + var idx = ParseExpr(); + if (idx == null) return null; + + if (!Expect(TokType.RBRACKET)) return null; + + ArrayType? arrayType; + if (!arrayTypes.TryGetValue(n, out arrayType)) { + AddError($"Internal error: Array type information missing for '{n}'"); + return null; + } + + return new ArrayAccessExpr(n, idx, arrayType.ElementType); + } + return new VarExpr(n, sym.Type); case TokType.LPAREN: @@ -332,4 +430,9 @@ public class StParser { return null; } } + + public ArrayType? GetArrayType(string name) { + ArrayType? type; + return arrayTypes.TryGetValue(name, out type) ? type : null; + } } diff --git a/STCompiler.Compiler/Program.cs b/STCompiler.Compiler/Program.cs index ff79d4f..484ed2f 100644 --- a/STCompiler.Compiler/Program.cs +++ b/STCompiler.Compiler/Program.cs @@ -33,6 +33,10 @@ class Program { try { var emitter = new BytecodeEmitter(); + // Register array types from parser + foreach (var (name, arrayType) in parser.arrayTypes) { + emitter.RegisterArrayType(name, arrayType); + } emitter.Compile(prog); File.WriteAllBytes(args[1], emitter.BuildBinary()); Console.WriteLine($"Wrote {args[1]}: consts={emitter.ConstantsCount}, vars={emitter.VarCount}, code={emitter.CodeLength}"); @@ -52,11 +56,17 @@ public class BytecodeEmitter { List consts = new(); // Kann nun int, long, float oder double speichern Dictionary syms = new(); List code = new(); + Dictionary arrayTypes = new(); class Symbol { required public string Name; public VarType Type; public int Index; + public ArrayType? ArrayInfo; // Null for non-array types + } + + public void RegisterArrayType(string name, ArrayType type) { + arrayTypes[name] = type; } public int ConstantsCount => consts.Count; @@ -65,8 +75,19 @@ public class BytecodeEmitter { public void Compile(ProgramNode p){ int idx=0; - foreach(var v in p.Vars) - syms[v.Name]=new Symbol{Name=v.Name,Type=v.Type,Index=idx++}; + foreach(var v in p.Vars) { + var symbol = new Symbol{Name=v.Name, Type=v.Type, Index=idx}; + if (v.Type == VarType.ARRAY) { + var arrayInfo = arrayTypes[v.Name]; + symbol.ArrayInfo = arrayInfo; + // For arrays, increment the index by array size + idx += arrayInfo.Length; + } else { + // For regular variables, increment by 1 + idx++; + } + syms[v.Name] = symbol; + } foreach(var v in p.Vars) if(v.Init!=null){EmitExpr(v.Init);EmitByte(Bytecode.OpCodes.STORE_VAR);EmitU16((ushort)syms[v.Name].Index);} @@ -149,8 +170,43 @@ public class BytecodeEmitter { if (!syms.TryGetValue(a.Target, out symbol)) { throw new Exception($"Undeclared variable '{a.Target}'"); } - EmitExpr(a.Expr); - EmitByte(Bytecode.OpCodes.STORE_VAR); EmitU16((ushort)symbol.Index); + + // If this is an array assignment, we need to evaluate the index and adjust the target address + if (symbol.Type == VarType.ARRAY && a.Index != null) { + // Evaluate array index + EmitExpr(a.Index); + + // Bounds check + if (symbol.ArrayInfo == null) + throw new Exception($"Internal error: Array info missing for '{a.Target}'"); + + EmitByte(Bytecode.OpCodes.ARRAY_BOUNDS_CHECK); + EmitU16((ushort)symbol.ArrayInfo.Start); + EmitU16((ushort)symbol.ArrayInfo.End); + + // Convert to zero-based index + if (symbol.ArrayInfo.Start != 0) { + EmitByte(Bytecode.OpCodes.PUSH_CONST); + EmitU16((ushort)AddConst(symbol.ArrayInfo.Start)); + EmitByte(Bytecode.OpCodes.SUB_INT); + } + + // Add base address + EmitByte(Bytecode.OpCodes.PUSH_CONST); + EmitU16((ushort)symbol.Index); + EmitByte(Bytecode.OpCodes.ADD_INT); + + // Now evaluate and store the value + EmitExpr(a.Expr); + EmitByte(Bytecode.OpCodes.STORE_VAR); + EmitU16(0); // Index is already on stack + } + else { + // Regular variable assignment + EmitExpr(a.Expr); + EmitByte(Bytecode.OpCodes.STORE_VAR); + EmitU16((ushort)symbol.Index); + } break; case IfStmt iff: @@ -226,14 +282,12 @@ public class BytecodeEmitter { int ci = AddConst(ie.Value); EmitByte(Bytecode.OpCodes.PUSH_CONST); // PUSH_CONST EmitU16((ushort)ci); - // removed emitting the type byte into code stream; type is stored with constant table break; case RealExpr re: int cri = AddConst(re.Value); EmitByte(Bytecode.OpCodes.PUSH_REAL_CONST); // PUSH_REAL_CONST EmitU16((ushort)cri); - // removed emitting the type byte into code stream; type is stored with constant table break; case VarExpr ve: @@ -244,6 +298,42 @@ public class BytecodeEmitter { EmitByte(Bytecode.OpCodes.LOAD_VAR); // LOAD_VAR EmitU16((ushort)symbol.Index); break; + + case ArrayAccessExpr ae: + Symbol? arraySymbol = null; + if (!syms.TryGetValue(ae.ArrayName, out arraySymbol)) { + throw new Exception($"Undeclared array '{ae.ArrayName}'"); + } + if (arraySymbol.Type != VarType.ARRAY || arraySymbol.ArrayInfo == null) { + throw new Exception($"Variable '{ae.ArrayName}' is not an array"); + } + + // Emit the index expression first + EmitExpr(ae.Index); + + // Emit array bounds check + int start = arraySymbol.ArrayInfo.Start; + int end = arraySymbol.ArrayInfo.End; + EmitByte(Bytecode.OpCodes.ARRAY_BOUNDS_CHECK); + EmitU16((ushort)start); + EmitU16((ushort)end); + + // Convert index to zero-based + if (start != 0) { + EmitByte(Bytecode.OpCodes.PUSH_CONST); + EmitU16((ushort)AddConst(start)); + EmitByte(Bytecode.OpCodes.SUB_INT); + } + + // Load array base address + EmitByte(Bytecode.OpCodes.PUSH_CONST); + EmitU16((ushort)arraySymbol.Index); + EmitByte(Bytecode.OpCodes.ADD_INT); + + // Load array element + EmitByte(Bytecode.OpCodes.LOAD_VAR); + EmitU16(0); // Index is already on stack + break; case BinaryExpr be: EmitExpr(be.L); @@ -253,14 +343,6 @@ public class BytecodeEmitter { if (!opCodes.ContainsKey(key)) { throw new Exception($"Unknown operator '{be.Op}' for type {be.Type}"); } - - // Wenn nötig, Typenkonvertierung vor der Operation - // Conversion opcodes removed - runtime will handle type differences using constant type markers and operation opcodes - // if (be.L.Type != be.Type) - // EmitByte((byte)(0x50 + (int)be.Type)); // CONVERT_TO_* - // if (be.R.Type != be.Type) - // EmitByte((byte)(0x50 + (int)be.Type)); // CONVERT_TO_* - EmitByte(opCodes[key]); break; } @@ -308,11 +390,29 @@ public class BytecodeEmitter { } } + // Calculate total variable space needed (accounting for arrays) + int totalVarSpace = 0; + foreach(var kv in syms) { + if (kv.Value.Type == VarType.ARRAY && kv.Value.ArrayInfo != null) { + totalVarSpace = Math.Max(totalVarSpace, kv.Value.Index + kv.Value.ArrayInfo.Length); + } else { + totalVarSpace = Math.Max(totalVarSpace, kv.Value.Index + 1); + } + } + // Variablen - w.Write((ushort)syms.Count); - var types = new byte[syms.Count]; - foreach(var kv in syms) - types[kv.Value.Index] = (byte)kv.Value.Type; + w.Write((ushort)totalVarSpace); + var types = new byte[totalVarSpace]; + foreach(var kv in syms) { + if (kv.Value.Type == VarType.ARRAY && kv.Value.ArrayInfo != null) { + // Fill array elements with their element type + for (int i = 0; i < kv.Value.ArrayInfo.Length; i++) { + types[kv.Value.Index + i] = (byte)kv.Value.ArrayInfo.ElementType; + } + } else { + types[kv.Value.Index] = (byte)kv.Value.Type; + } + } foreach(var b in types) w.Write(b); diff --git a/STCompiler.Compiler/bin/Debug/net8.0/STCompiler.Common.dll b/STCompiler.Compiler/bin/Debug/net8.0/STCompiler.Common.dll index ea9b04b..f181d40 100644 Binary files a/STCompiler.Compiler/bin/Debug/net8.0/STCompiler.Common.dll and b/STCompiler.Compiler/bin/Debug/net8.0/STCompiler.Common.dll differ diff --git a/STCompiler.Compiler/bin/Debug/net8.0/STCompiler.Common.pdb b/STCompiler.Compiler/bin/Debug/net8.0/STCompiler.Common.pdb index 8486650..ba33997 100644 Binary files a/STCompiler.Compiler/bin/Debug/net8.0/STCompiler.Common.pdb and b/STCompiler.Compiler/bin/Debug/net8.0/STCompiler.Common.pdb differ diff --git a/STCompiler.Compiler/bin/Debug/net8.0/STCompiler.Compiler.dll b/STCompiler.Compiler/bin/Debug/net8.0/STCompiler.Compiler.dll index 9c7f68a..53c681a 100644 Binary files a/STCompiler.Compiler/bin/Debug/net8.0/STCompiler.Compiler.dll and b/STCompiler.Compiler/bin/Debug/net8.0/STCompiler.Compiler.dll differ diff --git a/STCompiler.Compiler/bin/Debug/net8.0/STCompiler.Compiler.pdb b/STCompiler.Compiler/bin/Debug/net8.0/STCompiler.Compiler.pdb index 49e9360..651302c 100644 Binary files a/STCompiler.Compiler/bin/Debug/net8.0/STCompiler.Compiler.pdb and b/STCompiler.Compiler/bin/Debug/net8.0/STCompiler.Compiler.pdb differ diff --git a/STCompiler.Compiler/input.st b/STCompiler.Compiler/input.st index 99bb2de..bd9a298 100644 --- a/STCompiler.Compiler/input.st +++ b/STCompiler.Compiler/input.st @@ -8,8 +8,16 @@ VAR x REAL := 1.5; y LREAL := 2.5; cnt INT := 0; +// numbers ARRAY [1..10] OF INT; +// matrix ARRAY [0..3] OF REAL; END_VAR + +// numbers[1] := 42; +// numbers[2] := numbers[1] * 2; +// matrix[0] := 3.14; + + // Einfacher If-Test IF a = 0 THEN a := 1; diff --git a/STCompiler.Compiler/obj/Debug/net8.0/STCompiler.Compiler.AssemblyInfo.cs b/STCompiler.Compiler/obj/Debug/net8.0/STCompiler.Compiler.AssemblyInfo.cs index 23cbb57..dfa34bc 100644 --- a/STCompiler.Compiler/obj/Debug/net8.0/STCompiler.Compiler.AssemblyInfo.cs +++ b/STCompiler.Compiler/obj/Debug/net8.0/STCompiler.Compiler.AssemblyInfo.cs @@ -13,7 +13,7 @@ using System.Reflection; [assembly: System.Reflection.AssemblyCompanyAttribute("STCompiler.Compiler")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] -[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+ec4d7dc26ee2fd96db003ab3a6c1af70e02894b9")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+3cb63739152cd26ec43993953c7b93d4ab9bcce7")] [assembly: System.Reflection.AssemblyProductAttribute("STCompiler.Compiler")] [assembly: System.Reflection.AssemblyTitleAttribute("STCompiler.Compiler")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] diff --git a/STCompiler.Compiler/obj/Debug/net8.0/STCompiler.Compiler.AssemblyInfoInputs.cache b/STCompiler.Compiler/obj/Debug/net8.0/STCompiler.Compiler.AssemblyInfoInputs.cache index cbd1f84..174f51c 100644 --- a/STCompiler.Compiler/obj/Debug/net8.0/STCompiler.Compiler.AssemblyInfoInputs.cache +++ b/STCompiler.Compiler/obj/Debug/net8.0/STCompiler.Compiler.AssemblyInfoInputs.cache @@ -1 +1 @@ -bcd7f5e5efddd7ac50fcf7487abbb9cf17cacc826a4dbbf1dcb95d96e7974c93 +cc701f58f98db810dc498092a84a16f3679a63cf316500de1b157491a545da80 diff --git a/STCompiler.Compiler/obj/Debug/net8.0/STCompiler.Compiler.csproj.AssemblyReference.cache b/STCompiler.Compiler/obj/Debug/net8.0/STCompiler.Compiler.csproj.AssemblyReference.cache index 308cebe..f4b75ac 100644 Binary files a/STCompiler.Compiler/obj/Debug/net8.0/STCompiler.Compiler.csproj.AssemblyReference.cache and b/STCompiler.Compiler/obj/Debug/net8.0/STCompiler.Compiler.csproj.AssemblyReference.cache differ diff --git a/STCompiler.Compiler/obj/Debug/net8.0/STCompiler.Compiler.dll b/STCompiler.Compiler/obj/Debug/net8.0/STCompiler.Compiler.dll index 9c7f68a..53c681a 100644 Binary files a/STCompiler.Compiler/obj/Debug/net8.0/STCompiler.Compiler.dll and b/STCompiler.Compiler/obj/Debug/net8.0/STCompiler.Compiler.dll differ diff --git a/STCompiler.Compiler/obj/Debug/net8.0/STCompiler.Compiler.pdb b/STCompiler.Compiler/obj/Debug/net8.0/STCompiler.Compiler.pdb index 49e9360..651302c 100644 Binary files a/STCompiler.Compiler/obj/Debug/net8.0/STCompiler.Compiler.pdb and b/STCompiler.Compiler/obj/Debug/net8.0/STCompiler.Compiler.pdb differ diff --git a/STCompiler.Compiler/obj/Debug/net8.0/ref/STCompiler.Compiler.dll b/STCompiler.Compiler/obj/Debug/net8.0/ref/STCompiler.Compiler.dll index 816638c..cae0eec 100644 Binary files a/STCompiler.Compiler/obj/Debug/net8.0/ref/STCompiler.Compiler.dll and b/STCompiler.Compiler/obj/Debug/net8.0/ref/STCompiler.Compiler.dll differ diff --git a/STCompiler.Compiler/obj/Debug/net8.0/refint/STCompiler.Compiler.dll b/STCompiler.Compiler/obj/Debug/net8.0/refint/STCompiler.Compiler.dll index 816638c..cae0eec 100644 Binary files a/STCompiler.Compiler/obj/Debug/net8.0/refint/STCompiler.Compiler.dll and b/STCompiler.Compiler/obj/Debug/net8.0/refint/STCompiler.Compiler.dll differ diff --git a/STCompiler.Disassembler/Program.cs b/STCompiler.Disassembler/Program.cs index 23d58b4..cafe69f 100644 --- a/STCompiler.Disassembler/Program.cs +++ b/STCompiler.Disassembler/Program.cs @@ -46,10 +46,29 @@ class Program { byte tb = r.ReadByte(); var vt = (VarType)tb; varTypes[i] = vt; - if (Enum.IsDefined(typeof(VarType), vt)) + + if (vt == VarType.ARRAY) { + // Look ahead to find array length and element type + int arrayStart = i; + int length = 1; + VarType elementType = 0; // Initialize to INT as default + + if (i + 1 < nVars) { + elementType = (VarType)varTypes[i + 1]; + while (i + length < nVars && varTypes[i + length] == varTypes[i + 1]) { + length++; + } + } + + Console.WriteLine($" Var[{i}] type = ARRAY[{length}] OF {elementType}"); + i += length - 1; // Skip array elements + } + else if (Enum.IsDefined(typeof(VarType), vt)) { Console.WriteLine($" Var[{i}] type = {vt}"); - else + } + else { Console.WriteLine($" Var[{i}] type = {tb} (unknown)"); + } } ushort codeLen = r.ReadUInt16(); @@ -71,6 +90,12 @@ class Program { case Bytecode.OpCodes.JZ: { ushort target = ReadU16(code, ref ip); Console.WriteLine($"JZ addr={target:0000}"); break; } case Bytecode.OpCodes.JMP: { ushort target = ReadU16(code, ref ip); Console.WriteLine($"JMP addr={target:0000}"); break; } case Bytecode.OpCodes.HALT: Console.WriteLine("HALT"); break; + case Bytecode.OpCodes.ARRAY_BOUNDS_CHECK: { + Console.WriteLine("ARRAY_BOUNDS_CHECK"); + // Skip the next byte as it's part of the array bounds check instruction + if (ip < code.Length) ip++; + break; + } default: Console.WriteLine($"{Bytecode.OpName(op)}"); break; } } diff --git a/STCompiler.Disassembler/bin/Debug/net8.0/STCompiler.Common.dll b/STCompiler.Disassembler/bin/Debug/net8.0/STCompiler.Common.dll index ea9b04b..f181d40 100644 Binary files a/STCompiler.Disassembler/bin/Debug/net8.0/STCompiler.Common.dll and b/STCompiler.Disassembler/bin/Debug/net8.0/STCompiler.Common.dll differ diff --git a/STCompiler.Disassembler/bin/Debug/net8.0/STCompiler.Common.pdb b/STCompiler.Disassembler/bin/Debug/net8.0/STCompiler.Common.pdb index 8486650..ba33997 100644 Binary files a/STCompiler.Disassembler/bin/Debug/net8.0/STCompiler.Common.pdb and b/STCompiler.Disassembler/bin/Debug/net8.0/STCompiler.Common.pdb differ diff --git a/STCompiler.Disassembler/bin/Debug/net8.0/STCompiler.Disassembler.dll b/STCompiler.Disassembler/bin/Debug/net8.0/STCompiler.Disassembler.dll index d09d15d..0ecfa3c 100644 Binary files a/STCompiler.Disassembler/bin/Debug/net8.0/STCompiler.Disassembler.dll and b/STCompiler.Disassembler/bin/Debug/net8.0/STCompiler.Disassembler.dll differ diff --git a/STCompiler.Disassembler/bin/Debug/net8.0/STCompiler.Disassembler.pdb b/STCompiler.Disassembler/bin/Debug/net8.0/STCompiler.Disassembler.pdb index be20647..bb79ffc 100644 Binary files a/STCompiler.Disassembler/bin/Debug/net8.0/STCompiler.Disassembler.pdb and b/STCompiler.Disassembler/bin/Debug/net8.0/STCompiler.Disassembler.pdb differ diff --git a/STCompiler.Disassembler/obj/Debug/net8.0/STCompiler.Disassembler.AssemblyInfo.cs b/STCompiler.Disassembler/obj/Debug/net8.0/STCompiler.Disassembler.AssemblyInfo.cs index 7dcf789..907e41e 100644 --- a/STCompiler.Disassembler/obj/Debug/net8.0/STCompiler.Disassembler.AssemblyInfo.cs +++ b/STCompiler.Disassembler/obj/Debug/net8.0/STCompiler.Disassembler.AssemblyInfo.cs @@ -13,10 +13,10 @@ using System.Reflection; [assembly: System.Reflection.AssemblyCompanyAttribute("STCompiler.Disassembler")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] -[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+ec4d7dc26ee2fd96db003ab3a6c1af70e02894b9")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+3cb63739152cd26ec43993953c7b93d4ab9bcce7")] [assembly: System.Reflection.AssemblyProductAttribute("STCompiler.Disassembler")] [assembly: System.Reflection.AssemblyTitleAttribute("STCompiler.Disassembler")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] -// Von der MSBuild WriteCodeFragment-Klasse generiert. +// Generated by the MSBuild WriteCodeFragment class. diff --git a/STCompiler.Disassembler/obj/Debug/net8.0/STCompiler.Disassembler.AssemblyInfoInputs.cache b/STCompiler.Disassembler/obj/Debug/net8.0/STCompiler.Disassembler.AssemblyInfoInputs.cache index 2774274..b5d8578 100644 --- a/STCompiler.Disassembler/obj/Debug/net8.0/STCompiler.Disassembler.AssemblyInfoInputs.cache +++ b/STCompiler.Disassembler/obj/Debug/net8.0/STCompiler.Disassembler.AssemblyInfoInputs.cache @@ -1 +1 @@ -124c0ad3412d8c18080f8da6f8923566217268c81c32c97108af077bc918b46f +2175f71304910ca37c6a64a54785d953c58ecd76944c17fb6fe56c6a95a4d3e4 diff --git a/STCompiler.Disassembler/obj/Debug/net8.0/STCompiler.Disassembler.csproj.AssemblyReference.cache b/STCompiler.Disassembler/obj/Debug/net8.0/STCompiler.Disassembler.csproj.AssemblyReference.cache index 308cebe..f4b75ac 100644 Binary files a/STCompiler.Disassembler/obj/Debug/net8.0/STCompiler.Disassembler.csproj.AssemblyReference.cache and b/STCompiler.Disassembler/obj/Debug/net8.0/STCompiler.Disassembler.csproj.AssemblyReference.cache differ diff --git a/STCompiler.Disassembler/obj/Debug/net8.0/STCompiler.Disassembler.dll b/STCompiler.Disassembler/obj/Debug/net8.0/STCompiler.Disassembler.dll index d09d15d..0ecfa3c 100644 Binary files a/STCompiler.Disassembler/obj/Debug/net8.0/STCompiler.Disassembler.dll and b/STCompiler.Disassembler/obj/Debug/net8.0/STCompiler.Disassembler.dll differ diff --git a/STCompiler.Disassembler/obj/Debug/net8.0/STCompiler.Disassembler.pdb b/STCompiler.Disassembler/obj/Debug/net8.0/STCompiler.Disassembler.pdb index be20647..bb79ffc 100644 Binary files a/STCompiler.Disassembler/obj/Debug/net8.0/STCompiler.Disassembler.pdb and b/STCompiler.Disassembler/obj/Debug/net8.0/STCompiler.Disassembler.pdb differ diff --git a/STCompiler.Disassembler/obj/Debug/net8.0/ref/STCompiler.Disassembler.dll b/STCompiler.Disassembler/obj/Debug/net8.0/ref/STCompiler.Disassembler.dll index e7a465b..c9bd325 100644 Binary files a/STCompiler.Disassembler/obj/Debug/net8.0/ref/STCompiler.Disassembler.dll and b/STCompiler.Disassembler/obj/Debug/net8.0/ref/STCompiler.Disassembler.dll differ diff --git a/STCompiler.Disassembler/obj/Debug/net8.0/refint/STCompiler.Disassembler.dll b/STCompiler.Disassembler/obj/Debug/net8.0/refint/STCompiler.Disassembler.dll index e7a465b..c9bd325 100644 Binary files a/STCompiler.Disassembler/obj/Debug/net8.0/refint/STCompiler.Disassembler.dll and b/STCompiler.Disassembler/obj/Debug/net8.0/refint/STCompiler.Disassembler.dll differ diff --git a/STCompiler.Simulator/Program.cs b/STCompiler.Simulator/Program.cs index 9b990ee..edb9a79 100644 --- a/STCompiler.Simulator/Program.cs +++ b/STCompiler.Simulator/Program.cs @@ -54,6 +54,42 @@ class Program { Console.WriteLine($"CodeLen: {codeLen} bytes"); var code = r.ReadBytes(codeLen); + // Initialize arrays for element type tracking + var arrayRanges = new Dictionary(); + Console.WriteLine("\nAnalyzing variable types:"); + for (int i = 0; i < nVars; i++) { + Console.WriteLine($" [{i}] = {(VarType)varTypes[i]}"); + } + + Console.WriteLine("\nDetecting arrays:"); + for (int i = 0; i < nVars; i++) { + if (varTypes[i] == (byte)VarType.ARRAY && i + 2 <= nVars) { + // An array consists of: + // - ARRAY marker at position i + // - ElementType at position i+1 + // - Array elements starting at position i+2 + int arrayStart = i; + VarType elementType = (VarType)varTypes[i + 1]; + int startOfElements = i + 2; + + // Count elements until we hit either end of vars or a different type + int length = 0; + for (int j = startOfElements; j < nVars; j++) { + if (varTypes[j] != (byte)elementType) break; + length++; + } + + arrayRanges[arrayStart] = (startOfElements, length, elementType); + Console.WriteLine($"Found array at index {arrayStart}:"); + Console.WriteLine($" - Element type: {elementType}"); + Console.WriteLine($" - Elements start at: {startOfElements}"); + Console.WriteLine($" - Length: {length}"); + + // Skip past the array definition (ARRAY marker + element type) + i = startOfElements - 1; + } + } + var stack = new Stack(); var vars = new object[nVars]; int ip = 0; @@ -61,7 +97,7 @@ class Program { while (ip < code.Length) { int addr = ip; byte op = code[ip++]; - Console.Write($"{addr:0000}: 0x{op:X2} {Bytecode.OpName(op)} "); + Console.Write($"{addr:0000}: 0x{op:X2} "); switch (op) { case Bytecode.OpCodes.NOP: Console.WriteLine("NOP"); break; case Bytecode.OpCodes.PUSH_CONST: { @@ -76,12 +112,103 @@ class Program { Console.WriteLine($"PUSH_REAL_CONST {ci} ({consts[ci]})"); stack.Push(consts[ci]); break; } - case Bytecode.OpCodes.LOAD_VAR: { ushort vi = (ushort)(code[ip++] | (code[ip++] << 8)); Console.WriteLine($"LOAD_VAR {vi}"); stack.Push(vars[vi]); break; } - case Bytecode.OpCodes.STORE_VAR: { ushort vi = (ushort)(code[ip++] | (code[ip++] << 8)); Console.WriteLine($"STORE_VAR {vi}"); vars[vi] = stack.Pop(); break; } - case Bytecode.OpCodes.JZ: { ushort target = (ushort)(code[ip++] | (code[ip++] << 8)); Console.WriteLine($"JZ addr={target}"); var cond = stack.Pop(); bool isFalse = cond is int ci ? ci == 0 : cond is long cl ? cl == 0L : cond is double cd ? cd == 0.0 : cond == null; if (isFalse) ip = target; break; } - case Bytecode.OpCodes.JMP: { ushort target = (ushort)(code[ip++] | (code[ip++] << 8)); Console.WriteLine($"JMP addr={target}"); ip = target; break; } - case Bytecode.OpCodes.HALT: Console.WriteLine("HALT"); ip = code.Length; break; - default: Console.WriteLine(); + case Bytecode.OpCodes.LOAD_VAR: { + ushort vi = (ushort)(code[ip++] | (code[ip++] << 8)); + Console.WriteLine($"LOAD_VAR {vi}"); + + // Check if the variable index is within bounds + if (vi >= vars.Length) { + throw new Exception($"Variable index {vi} is out of bounds (max: {vars.Length - 1})"); + } + + if (arrayRanges.ContainsKey(vi)) { + var (start, arrayLength, arrayElementType) = arrayRanges[vi]; + var arrayData = new object[arrayLength]; + Array.Copy(vars, start, arrayData, 0, arrayLength); + stack.Push(arrayData); + } else { + stack.Push(vars[vi]); + } + break; + } + case Bytecode.OpCodes.STORE_VAR: { + ushort vi = (ushort)(code[ip++] | (code[ip++] << 8)); + Console.WriteLine($"STORE_VAR {vi}"); + + // Check if the variable index is within bounds + if (vi >= vars.Length) { + throw new Exception($"Variable index {vi} is out of bounds (max: {vars.Length - 1})"); + } + + var value = stack.Pop(); + if (arrayRanges.ContainsKey(vi)) { + var (start, arrayLength, arrayElementType) = arrayRanges[vi]; + if (value is object[] arr) { + Array.Copy(arr, 0, vars, start, Math.Min(arr.Length, arrayLength)); + } else { + Console.WriteLine($"Warning: Attempting to store non-array value in array variable at index {vi}"); + vars[vi] = value; + } + } else { + vars[vi] = value; + } + break; + } + case Bytecode.OpCodes.JZ: { ushort target = (ushort)(code[ip++] | (code[ip++] << 8)); Console.WriteLine($"JZ addr={target:0000}"); var cond = stack.Pop(); bool isFalse = cond is int ci ? ci == 0 : cond is long cl ? cl == 0L : cond is double cd ? cd == 0.0 : cond == null; if (isFalse) ip = target; break; } + case Bytecode.OpCodes.JMP: { + ushort target = (ushort)(code[ip++] | (code[ip++] << 8)); + Console.WriteLine($"JMP addr={target:0000}"); + ip = target; + break; + } + case Bytecode.OpCodes.HALT: + Console.WriteLine("HALT"); + ip = code.Length; + break; + case Bytecode.OpCodes.ARRAY_BOUNDS_CHECK: + // Extract the array index from the instruction + byte arrayIndex = 0; + if (ip < code.Length) { + arrayIndex = code[ip]; + ip++; + } + + // Check if this variable is actually an array + if (!arrayRanges.ContainsKey(arrayIndex)) { + Console.WriteLine($"Warning: ARRAY_BOUNDS_CHECK instruction for non-array variable {arrayIndex}"); + continue; // Skip this instruction + } + + Console.WriteLine($"ARRAY_BOUNDS_CHECK for array at index {arrayIndex}"); + + if (stack.Count < 1) { + throw new Exception("Stack underflow during array bounds check"); + } + + // Convert index value safely + var indexObj = stack.Pop(); + int index = Convert.ToInt32(indexObj); + + // The arrayStart from the instruction should be the array marker directly + if (!arrayRanges.TryGetValue(arrayIndex, out var arrayInfo)) { + // This should not happen since we checked above + throw new Exception($"Array metadata missing for index {arrayIndex}"); + } + + var (elementsStart, length, elementType) = arrayInfo; + + // Adjust for IEC array indexing (1-based) + int adjustedIndex = index - 1; + if (adjustedIndex < 0 || adjustedIndex >= length) { + throw new Exception($"Array index {index} out of bounds [1..{length}]"); + } + + // Calculate the actual element address + stack.Push(elementsStart + adjustedIndex); + Console.WriteLine($"Accessing element {index} of array, mapped to variable index {elementsStart + adjustedIndex}"); + break; + default: +; // fallback handlers if (Bytecode.OpName(op).StartsWith("ADD_") || Bytecode.OpName(op).StartsWith("SUB_") || Bytecode.OpName(op).StartsWith("MUL_") || Bytecode.OpName(op).StartsWith("DIV_")) { dynamic b = stack.Pop(); dynamic a = stack.Pop(); if (Bytecode.OpName(op).StartsWith("ADD_")) stack.Push(a + b); else if (Bytecode.OpName(op).StartsWith("SUB_")) stack.Push(a - b); else if (Bytecode.OpName(op).StartsWith("MUL_")) stack.Push(a * b); else stack.Push(a / b); @@ -98,6 +225,47 @@ class Program { stack.Push(res ? 1 : 0); break; } + // Array operations + if (op == Bytecode.OpCodes.ARRAY_BOUNDS_CHECK) { + // Extract the array index from the instruction + byte arrayIndexInner = 0; + if (ip < code.Length) { + arrayIndexInner = code[ip]; + ip++; + } + + // Check if this variable is actually an array + if (!arrayRanges.ContainsKey(arrayIndexInner)) { + Console.WriteLine($"Warning: ARRAY_BOUNDS_CHECK instruction for non-array variable {arrayIndexInner}"); + continue; // Skip this instruction + } + + Console.WriteLine($"ARRAY_BOUNDS_CHECK for array at index {arrayIndexInner}"); + + if (stack.Count < 1) { + throw new Exception("Stack underflow during array bounds check"); + } + + // Convert index value safely + var indexObjInner = stack.Pop(); + int indexInner = Convert.ToInt32(indexObjInner); + + // The arrayStart from the instruction should be the array marker directly + if (!arrayRanges.TryGetValue(arrayIndexInner, out var arrayInfoInner)) { + // This should not happen since we checked above + throw new Exception($"Array metadata missing for index {arrayIndexInner}"); + } + + var (elementsStartInner, lengthInner, elementTypeInner) = arrayInfoInner; + if (indexInner < 0 || indexInner >= lengthInner) { + throw new Exception($"Array index {indexInner} out of bounds [0..{lengthInner-1}]"); + } + + // Calculate the actual element address + stack.Push(elementsStartInner + indexInner); + Console.WriteLine($"Accessing element {indexInner} of array, mapped to variable index {elementsStartInner + indexInner}"); + break; + } throw new Exception($"Unknown opcode 0x{op:X2}"); } } diff --git a/STCompiler.Simulator/bin/Debug/net8.0/STCompiler.Common.dll b/STCompiler.Simulator/bin/Debug/net8.0/STCompiler.Common.dll index ea9b04b..f181d40 100644 Binary files a/STCompiler.Simulator/bin/Debug/net8.0/STCompiler.Common.dll and b/STCompiler.Simulator/bin/Debug/net8.0/STCompiler.Common.dll differ diff --git a/STCompiler.Simulator/bin/Debug/net8.0/STCompiler.Common.pdb b/STCompiler.Simulator/bin/Debug/net8.0/STCompiler.Common.pdb index 8486650..ba33997 100644 Binary files a/STCompiler.Simulator/bin/Debug/net8.0/STCompiler.Common.pdb and b/STCompiler.Simulator/bin/Debug/net8.0/STCompiler.Common.pdb differ diff --git a/STCompiler.Simulator/bin/Debug/net8.0/STCompiler.Simulator.dll b/STCompiler.Simulator/bin/Debug/net8.0/STCompiler.Simulator.dll index 66358ca..83c61b6 100644 Binary files a/STCompiler.Simulator/bin/Debug/net8.0/STCompiler.Simulator.dll and b/STCompiler.Simulator/bin/Debug/net8.0/STCompiler.Simulator.dll differ diff --git a/STCompiler.Simulator/bin/Debug/net8.0/STCompiler.Simulator.pdb b/STCompiler.Simulator/bin/Debug/net8.0/STCompiler.Simulator.pdb index a4fe96a..5e234e5 100644 Binary files a/STCompiler.Simulator/bin/Debug/net8.0/STCompiler.Simulator.pdb and b/STCompiler.Simulator/bin/Debug/net8.0/STCompiler.Simulator.pdb differ diff --git a/STCompiler.Simulator/obj/Debug/net8.0/STCompiler.Simulator.AssemblyInfo.cs b/STCompiler.Simulator/obj/Debug/net8.0/STCompiler.Simulator.AssemblyInfo.cs index d430c99..69d2bbb 100644 --- a/STCompiler.Simulator/obj/Debug/net8.0/STCompiler.Simulator.AssemblyInfo.cs +++ b/STCompiler.Simulator/obj/Debug/net8.0/STCompiler.Simulator.AssemblyInfo.cs @@ -13,10 +13,10 @@ using System.Reflection; [assembly: System.Reflection.AssemblyCompanyAttribute("STCompiler.Simulator")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] -[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+ec4d7dc26ee2fd96db003ab3a6c1af70e02894b9")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+3cb63739152cd26ec43993953c7b93d4ab9bcce7")] [assembly: System.Reflection.AssemblyProductAttribute("STCompiler.Simulator")] [assembly: System.Reflection.AssemblyTitleAttribute("STCompiler.Simulator")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] -// Von der MSBuild WriteCodeFragment-Klasse generiert. +// Generated by the MSBuild WriteCodeFragment class. diff --git a/STCompiler.Simulator/obj/Debug/net8.0/STCompiler.Simulator.AssemblyInfoInputs.cache b/STCompiler.Simulator/obj/Debug/net8.0/STCompiler.Simulator.AssemblyInfoInputs.cache index 1f809e4..3b0fa93 100644 --- a/STCompiler.Simulator/obj/Debug/net8.0/STCompiler.Simulator.AssemblyInfoInputs.cache +++ b/STCompiler.Simulator/obj/Debug/net8.0/STCompiler.Simulator.AssemblyInfoInputs.cache @@ -1 +1 @@ -9731a6e2cf5ff58c4c9e71ca1d547507058070586723183af16235f22b593078 +b05e088189133b131132a72fa879b53ae0f21051a8f25a2e49266f0f500e3142 diff --git a/STCompiler.Simulator/obj/Debug/net8.0/STCompiler.Simulator.csproj.AssemblyReference.cache b/STCompiler.Simulator/obj/Debug/net8.0/STCompiler.Simulator.csproj.AssemblyReference.cache index 308cebe..f4b75ac 100644 Binary files a/STCompiler.Simulator/obj/Debug/net8.0/STCompiler.Simulator.csproj.AssemblyReference.cache and b/STCompiler.Simulator/obj/Debug/net8.0/STCompiler.Simulator.csproj.AssemblyReference.cache differ diff --git a/STCompiler.Simulator/obj/Debug/net8.0/STCompiler.Simulator.dll b/STCompiler.Simulator/obj/Debug/net8.0/STCompiler.Simulator.dll index 66358ca..83c61b6 100644 Binary files a/STCompiler.Simulator/obj/Debug/net8.0/STCompiler.Simulator.dll and b/STCompiler.Simulator/obj/Debug/net8.0/STCompiler.Simulator.dll differ diff --git a/STCompiler.Simulator/obj/Debug/net8.0/STCompiler.Simulator.pdb b/STCompiler.Simulator/obj/Debug/net8.0/STCompiler.Simulator.pdb index a4fe96a..5e234e5 100644 Binary files a/STCompiler.Simulator/obj/Debug/net8.0/STCompiler.Simulator.pdb and b/STCompiler.Simulator/obj/Debug/net8.0/STCompiler.Simulator.pdb differ diff --git a/STCompiler.Simulator/obj/Debug/net8.0/ref/STCompiler.Simulator.dll b/STCompiler.Simulator/obj/Debug/net8.0/ref/STCompiler.Simulator.dll index 088f46a..7d392da 100644 Binary files a/STCompiler.Simulator/obj/Debug/net8.0/ref/STCompiler.Simulator.dll and b/STCompiler.Simulator/obj/Debug/net8.0/ref/STCompiler.Simulator.dll differ diff --git a/STCompiler.Simulator/obj/Debug/net8.0/refint/STCompiler.Simulator.dll b/STCompiler.Simulator/obj/Debug/net8.0/refint/STCompiler.Simulator.dll index 088f46a..7d392da 100644 Binary files a/STCompiler.Simulator/obj/Debug/net8.0/refint/STCompiler.Simulator.dll and b/STCompiler.Simulator/obj/Debug/net8.0/refint/STCompiler.Simulator.dll differ