public CacheEntry(int hash, ESIR_Node node) { Hash = hash; Node = node; }
private unsafe void AddIRNodeToTree(ESIR_Node node, TreeViewItem parentItem) { Debug.Assert(node is not null); if (node is null) { return; } switch (node.Kind) { case ESIR_NodeKind.ValueInt: case ESIR_NodeKind.ValueUInt: case ESIR_NodeKind.ValueFloat32: case ESIR_NodeKind.ValueFloat64: case ESIR_NodeKind.ValueIdentifier: case ESIR_NodeKind.ValueString: case ESIR_NodeKind.ValuePointer: case ESIR_NodeKind.List: case ESIR_NodeKind.TypeNode: Debug.Fail("These nodes shouldn't be added directly."); break; case ESIR_NodeKind.StaticVariable when node is ESIR_StaticVariable staticVar: AddNodeToTree($"{staticVar.Name} : {GetTypeName (staticVar.Type)}", parentItem); break; case ESIR_NodeKind.Struct when node is ESIR_Struct structDef: { var structItem = AddNodeToTree($"{GetTypeName (structDef.Type)}", parentItem); AddNodeToTree($"Size: {structDef.Type->RuntimeSize}", structItem); foreach (var member in structDef.Members.Elements) { AddIRNodeToTree(member, structItem); } break; } case ESIR_NodeKind.Function when node is ESIR_Function funcDef: { var structItem = AddNodeToTree($"{GetString (funcDef.Name)}", parentItem); AddNodeToTree($"Return type: {GetTypeName (funcDef.ReturnType)}", structItem); var argsItem = AddNodeToTree("Arguments", structItem); var localsItem = AddNodeToTree("Locals", structItem); var bodyItem = AddNodeToTree("Function body", structItem); var argsCount = 0; foreach (var arg in funcDef.Arguments.Elements) { AddNodeToTree(GetArgString(argsCount++, arg), argsItem); } var localsCount = 0; foreach (var localVal in funcDef.LocalValues.Elements) { AddNodeToTree(GetLocalValueString(localsCount++, localVal), localsItem); } foreach (var stmt in funcDef.Statements.Elements) { AddIRNodeToTree(stmt, bodyItem); } break; } case ESIR_NodeKind.ArgumentValue when node is ESIR_ArgumentValue argVal: if (argVal.ArgType == ES_ArgumentType.Normal) { AddNodeToTree($"{GetNiceExpr (argVal.Expression)}", parentItem); } else { AddNodeToTree($"{argVal.ArgType} {GetNiceExpr (argVal.Expression)}", parentItem); } break; case ESIR_NodeKind.Class: Debug.Fail("No IR node yet."); break; case ESIR_NodeKind.Field when node is ESIR_Field field: { var fieldItem = AddNodeToTree($"{GetString (field.Name)} : {GetTypeName (field.Type)}", parentItem); AddNodeToTree($"Offset: {field.Offset}", fieldItem); break; } case ESIR_NodeKind.StaticField when node is ESIR_StaticField staticField: AddNodeToTree($"{GetString (staticField.Name)} : {GetString (staticField.StaticVariable)}", parentItem); break; #region Expressions case ESIR_NodeKind.ErrorExpression: AddNodeToTree("[ERROR]", parentItem); break; case ESIR_NodeKind.AssignExpression when node is ESIR_AssignExpression assignExpr: { var assignItem = AddNodeToTree($"Assign: {GetNiceExpr (assignExpr.Assignee)} = {GetNiceExpr (assignExpr.Value)}", parentItem); AddIRNodeToTree(assignExpr.Assignee, assignItem); AddIRNodeToTree(assignExpr.Value, assignItem); break; } #region Binary case ESIR_NodeKind.BinaryExprConcat when node is ESIR_SimpleBinaryExpression binaryExpr: { AddBinaryExprToTree("Concatenate", "..", binaryExpr, parentItem); break; } case ESIR_NodeKind.BinaryExprPower when node is ESIR_SimpleBinaryExpression binaryExpr: { AddBinaryExprToTree("Exponentiate", "**", binaryExpr, parentItem); break; } case ESIR_NodeKind.BinaryExprMultiply when node is ESIR_SimpleBinaryExpression binaryExpr: { AddBinaryExprToTree("Multiply", "*", binaryExpr, parentItem); break; } case ESIR_NodeKind.BinaryExprDivide when node is ESIR_SimpleBinaryExpression binaryExpr: { AddBinaryExprToTree("Divide", "/", binaryExpr, parentItem); break; } case ESIR_NodeKind.BinaryExprModulo when node is ESIR_SimpleBinaryExpression binaryExpr: { AddBinaryExprToTree("Modulo", "%", binaryExpr, parentItem); break; } case ESIR_NodeKind.BinaryExprAdd when node is ESIR_SimpleBinaryExpression binaryExpr: { AddBinaryExprToTree("Add", "+", binaryExpr, parentItem); break; } case ESIR_NodeKind.BinaryExprSubtract when node is ESIR_SimpleBinaryExpression binaryExpr: { AddBinaryExprToTree("Subtract", "-", binaryExpr, parentItem); break; } case ESIR_NodeKind.BinaryExprShiftLeft when node is ESIR_SimpleBinaryExpression binaryExpr: { AddBinaryExprToTree("Left shift", "<<", binaryExpr, parentItem); break; } case ESIR_NodeKind.BinaryExprShiftRight when node is ESIR_SimpleBinaryExpression binaryExpr: { AddBinaryExprToTree("Right shift", ">>", binaryExpr, parentItem); break; } case ESIR_NodeKind.BinaryExprShiftRightUnsigned when node is ESIR_SimpleBinaryExpression binaryExpr: { AddBinaryExprToTree("Unsigned right shift", ">>>", binaryExpr, parentItem); break; } case ESIR_NodeKind.BinaryExprLesserThan when node is ESIR_SimpleBinaryExpression binaryExpr: { AddBinaryExprToTree("Lesser than", "<", binaryExpr, parentItem); break; } case ESIR_NodeKind.BinaryExprGreaterThan when node is ESIR_SimpleBinaryExpression binaryExpr: { AddBinaryExprToTree("Greater than", ">", binaryExpr, parentItem); break; } case ESIR_NodeKind.BinaryExprLesserThanEqual when node is ESIR_SimpleBinaryExpression binaryExpr: { AddBinaryExprToTree("Lesser than-equals", "<=", binaryExpr, parentItem); break; } case ESIR_NodeKind.BinaryExprGreaterThanEqual when node is ESIR_SimpleBinaryExpression binaryExpr: { AddBinaryExprToTree("Greater than-equals", ">=", binaryExpr, parentItem); break; } case ESIR_NodeKind.BinaryExprEquals when node is ESIR_SimpleBinaryExpression binaryExpr: { AddBinaryExprToTree("Equals", "==", binaryExpr, parentItem); break; } case ESIR_NodeKind.BinaryExprNotEquals when node is ESIR_SimpleBinaryExpression binaryExpr: { AddBinaryExprToTree("Not equal", "!=", binaryExpr, parentItem); break; } case ESIR_NodeKind.BinaryExprBitAnd when node is ESIR_SimpleBinaryExpression binaryExpr: { AddBinaryExprToTree("AND", "&", binaryExpr, parentItem); break; } case ESIR_NodeKind.BinaryExprBitOr when node is ESIR_SimpleBinaryExpression binaryExpr: { AddBinaryExprToTree("OR", "|", binaryExpr, parentItem); break; } case ESIR_NodeKind.BinaryExprBitXor when node is ESIR_SimpleBinaryExpression binaryExpr: { AddBinaryExprToTree("XOR", "^", binaryExpr, parentItem); break; } case ESIR_NodeKind.BinaryExprLogicalAnd when node is ESIR_SimpleBinaryExpression binaryExpr: { AddBinaryExprToTree("Logical and", "&&", binaryExpr, parentItem); break; } case ESIR_NodeKind.BinaryExprLogicalOr when node is ESIR_SimpleBinaryExpression binaryExpr: { AddBinaryExprToTree("Logical or", "||", binaryExpr, parentItem); break; } #endregion #region Unary case ESIR_NodeKind.UnaryNegative when node is ESIR_UnaryExpression unaryExpr: { AddUnaryExprToTree("Negative", "-", unaryExpr, parentItem); break; } case ESIR_NodeKind.UnaryLogicalNot when node is ESIR_UnaryExpression unaryExpr: { AddUnaryExprToTree("Logical negation", "!", unaryExpr, parentItem); break; } case ESIR_NodeKind.UnaryBitNot when node is ESIR_UnaryExpression unaryExpr: { AddUnaryExprToTree("NOT", "~", unaryExpr, parentItem); break; } case ESIR_NodeKind.UnaryDereference when node is ESIR_UnaryExpression unaryExpr: { AddUnaryExprToTree("Dereference", "*", unaryExpr, parentItem); break; } case ESIR_NodeKind.UnaryPreIncrement when node is ESIR_UnaryExpression unaryExpr: { AddUnaryExprToTree("Pre-increment", "++", unaryExpr, parentItem, false); break; } case ESIR_NodeKind.UnaryPreDecrement when node is ESIR_UnaryExpression unaryExpr: { AddUnaryExprToTree("Pre-decrement", "--", unaryExpr, parentItem, false); break; } case ESIR_NodeKind.UnaryPostIncrement when node is ESIR_UnaryExpression unaryExpr: { AddUnaryExprToTree("Post-increment", "++", unaryExpr, parentItem, true); break; } case ESIR_NodeKind.UnaryPostDecrement when node is ESIR_UnaryExpression unaryExpr: { AddUnaryExprToTree("Post-decrement", "--", unaryExpr, parentItem, true); break; } #endregion #region Literals case ESIR_NodeKind.LiteralTrue: AddNodeToTree("True", parentItem); break; case ESIR_NodeKind.LiteralFalse: AddNodeToTree("False", parentItem); break; case ESIR_NodeKind.LiteralInt when node is ESIR_LiteralExpression litExpr: AddNodeToTree($"Int {litExpr.Value.GetInt ()}", parentItem); break; case ESIR_NodeKind.LiteralFloat when node is ESIR_LiteralExpression litExpr: { if (litExpr.Value.Kind == ESIR_NodeKind.ValueFloat32) { AddNodeToTree($"Float {litExpr.Value.GetFloat32 ()}", parentItem); } else { AddNodeToTree($"Float {litExpr.Value.GetFloat64 ()}", parentItem); } break; } case ESIR_NodeKind.LiteralChar when node is ESIR_LiteralExpression litExpr: AddNodeToTree($"Char {(char) litExpr.Value.GetInt ()}", parentItem); break; case ESIR_NodeKind.LiteralNull when node is ESIR_NullLiteralExpression nullExpr: AddNodeToTree($"Null {GetTypeName (nullExpr.Type)}", parentItem); break; #endregion #region Values case ESIR_NodeKind.StringConstant when node is ESIR_StringConstantExpression stringConstExpr: { AddNodeToTree($"String constant #{stringConstExpr.Index}", parentItem); break; } case ESIR_NodeKind.StaticVariableExpression when node is ESIR_StaticVariableExpression staticVarExpr: { AddNodeToTree($"Static var {GetString (staticVarExpr.Name)}", parentItem); break; } case ESIR_NodeKind.ArgumentExpression when node is ESIR_ArgumentExpression argExpr: { AddNodeToTree($"Arg #{argExpr.Index}", parentItem); break; } case ESIR_NodeKind.LocalValueExpression when node is ESIR_LocalValueExpression localExpr: { AddNodeToTree($"Local #{localExpr.Index}", parentItem); break; } case ESIR_NodeKind.DefaultValueExpression when node is ESIR_DefaultValueExpression defValExpr: { AddNodeToTree($"Defaults {GetTypeName (defValExpr.Type)}", parentItem); break; } #endregion case ESIR_NodeKind.MemberAccessExpression when node is ESIR_MemberAccessExpression accessExpr: { var nameStr = GetString(accessExpr.Name); var accessItem = AddNodeToTree($"Member access: {GetNiceExpr (accessExpr.ExprParent)}.{nameStr}", parentItem); AddIRNodeToTree(accessExpr.ExprParent, accessItem); AddNodeToTree(nameStr, accessItem); break; } case ESIR_NodeKind.FunctionCallExpression when node is ESIR_FunctionCallExpression callExpr: { var funcName = GetString(callExpr.Name); var callItem = AddNodeToTree($"Function call {funcName}", parentItem); foreach (var arg in callExpr.Arguments.Elements) { AddIRNodeToTree(arg, callItem); } break; } case ESIR_NodeKind.IndexingExpression when node is ESIR_IndexingExpression indexExpr: { var sb = new StringBuilder(); sb.Append("Index "); sb.Append(GetNiceExpr(indexExpr.IndexedExpr)); sb.Append(" ["); var firstDim = false; foreach (var index in indexExpr.Indices.Elements) { if (firstDim) { firstDim = false; } else { sb.Append(", "); } sb.Append(GetNiceExpr(index)); } sb.Append(']'); var indexItem = AddNodeToTree(sb.ToString(), parentItem); AddIRNodeToTree(indexExpr.IndexedExpr, indexItem); var dimsItem = AddNodeToTree("Dimensions", indexItem); foreach (var index in indexExpr.Indices.Elements) { AddIRNodeToTree(index, dimsItem); } break; } case ESIR_NodeKind.NewObjectExpression when node is ESIR_NewObjectExpression newObjExpr: { AddNodeToTree($"New {GetTypeName (newObjExpr.Type)}", parentItem); break; } case ESIR_NodeKind.NewArrayExpression when node is ESIR_NewArrayExpression newArrExpr: { var dimsCount = newArrExpr.Ranks.Elements.Length; var newItem = AddNodeToTree($"New {GetTypeName (newArrExpr.ElementType)} [{new string (',', dimsCount - 1)}]", parentItem); foreach (var dim in newArrExpr.Ranks.Elements) { AddIRNodeToTree(dim, newItem); } break; } case ESIR_NodeKind.CastExpression when node is ESIR_CastExpression castExpr: { var castItem = AddNodeToTree($"Cast ({GetTypeName (castExpr.DestType)})", parentItem); AddIRNodeToTree(castExpr.Expression, castItem); break; } case ESIR_NodeKind.ConditionalExpression when node is ESIR_ConditionalExpression condExpr: { var niceCond = GetNiceExpr(condExpr.Condition); var niceTrueExpr = GetNiceExpr(condExpr.ThenExpression); var niceFalseExpr = GetNiceExpr(condExpr.ElseExpression); var condItem = AddNodeToTree($"Conditional: {niceCond} ? {niceTrueExpr} : {niceFalseExpr}", parentItem); AddIRNodeToTree(condExpr.Condition, condItem); AddIRNodeToTree(condExpr.ThenExpression, condItem); AddIRNodeToTree(condExpr.ElseExpression, condItem); break; } case ESIR_NodeKind.ExpressionList when node is ESIR_ExpressionList exprList: { var listItem = AddNodeToTree("Expression list", parentItem); foreach (var expr in exprList.Expressions.Elements) { AddIRNodeToTree(expr, listItem); } break; } #endregion #region Statements case ESIR_NodeKind.BlockStatement when node is ESIR_BlockStatement blockStmt: { var blockItem = AddNodeToTree("Block", parentItem); foreach (var stmt in blockStmt.Statements.Elements) { AddIRNodeToTree(stmt, blockItem); } break; } case ESIR_NodeKind.LabeledStatement when node is ESIR_LabeledStatement labelStmt: { AddNodeToTree($"Label {GetString (labelStmt.Label)}:", parentItem); AddIRNodeToTree(labelStmt.Statement, parentItem); break; } case ESIR_NodeKind.ConditionalStatement when node is ESIR_ConditionalStatement condStmt: { var ifItem = AddNodeToTree($"If ({GetNiceExpr (condStmt.Condition)})", parentItem); var condItem = AddNodeToTree("Condition", ifItem); AddIRNodeToTree(condStmt.Condition, condItem); AddIRNodeToTree(condStmt.Then, ifItem); if (condStmt.Else is not null) { AddIRNodeToTree(condStmt.Else, ifItem); } break; } case ESIR_NodeKind.SwitchStatement: AddNodeToTree("Switch [NO NODE IMPLEMENTED]", parentItem); break; case ESIR_NodeKind.BreakStatement when node is ESIR_BreakStatement breakStmt: { if (breakStmt.Label is null) { AddNodeToTree("Break", parentItem); break; } AddNodeToTree($"Break {GetString (breakStmt.Label.Value)}", parentItem); break; } case ESIR_NodeKind.ContinueStatement when node is ESIR_ContinueStatement continueStmt: { if (continueStmt.Label is null) { AddNodeToTree("Continue", parentItem); break; } AddNodeToTree($"Continue {GetString (continueStmt.Label.Value)}", parentItem); break; } case ESIR_NodeKind.GotoLabelStatement when node is ESIR_GotoLabelStatement gotoStmt: { AddNodeToTree($"Goto {GetString (gotoStmt.Label)}", parentItem); break; } case ESIR_NodeKind.GotoCaseStatement when node is ESIR_GotoCaseStatement gotoCaseStmt: { var caseStr = gotoCaseStmt.CaseExpr is null ? "default" : $"case {GetNiceExpr (gotoCaseStmt.CaseExpr)}"; AddNodeToTree($"Goto {caseStr}", parentItem); break; } case ESIR_NodeKind.ReturnStatement when node is ESIR_ReturnStatement retStmt: { if (retStmt.ReturnExpr is null) { AddNodeToTree("Return void", parentItem); break; } var retItem = AddNodeToTree($"Return {GetNiceExpr (retStmt.ReturnExpr)}", parentItem); AddIRNodeToTree(retStmt.ReturnExpr, retItem); break; } case ESIR_NodeKind.LoopStatement when node is ESIR_LoopStatement loopStmt: { var loopItem = AddNodeToTree("Loop", parentItem); var condExprs = loopStmt.ConditionExpr.Elements; if (condExprs.Length > 0) { foreach (var expr in condExprs[..^ 1])