Disammbler und Simulator angepasst. Arrays begonnen (defunct)
This commit is contained in:
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -14,6 +14,7 @@ public class StParser {
|
||||
StLexer lex;
|
||||
Token cur;
|
||||
Dictionary<string,Symbol> syms = new();
|
||||
public Dictionary<string,ArrayType> arrayTypes = new(); // Add dictionary for array types
|
||||
public List<CompileError> 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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<object> consts = new(); // Kann nun int, long, float oder double speichern
|
||||
Dictionary<string,Symbol> syms = new();
|
||||
List<byte> code = new();
|
||||
Dictionary<string,ArrayType> 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);
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -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;
|
||||
|
||||
@ -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")]
|
||||
|
||||
@ -1 +1 @@
|
||||
bcd7f5e5efddd7ac50fcf7487abbb9cf17cacc826a4dbbf1dcb95d96e7974c93
|
||||
cc701f58f98db810dc498092a84a16f3679a63cf316500de1b157491a545da80
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user