public override void VisitTryStatement(TryStatementSyntax node) { if (debug) { Console.WriteLine(node.ToFullString()); } var nl = OurLine.NewLine(LineKind.Decl, "TryStatement"); if (node.Finally != null) { OurLine.AddEssentialInfo(ref nl, "finally:" + node.Finally.ToString()); } if (node.Catches != null) { OurLine.AddEssentialInfo(ref nl, "catches:" + node.Catches.ToString()); } // we get the details later on. nl.Source = node.ToFullString(); nl.ParentKind = node.Parent.RawKind; nl.RawKind = node.RawKind; LogCommand(nl); StartBlock("TryStatement"); base.VisitTryStatement(node); EndBlock("TryStatement"); }
private void TryStatement(TryStatementSyntax statement) { if (statement.Finally != null) { throw new NotSupportedException("Finally blocks not supported: " + statement.ToFullString()); } if (statement.Catches == null || statement.Catches.Count == 0) { throw new NotSupportedException("No catach block after try: " + statement.ToFullString()); } // add special locals StartTryBlock(out string jmpBuffLast, out string jmpBuff, out string isJmp); ++tryCatchNestingLevel; // write try writer.WriteLinePrefix("/* try */"); writer.WriteLinePrefix($"memcpy({jmpBuffLast}, CS2X_ThreadExceptionJmpBuff, sizeof(jmp_buf));"); writer.WriteLinePrefix($"{isJmp} = setjmp({jmpBuff});"); writer.WriteLinePrefix($"if ({isJmp} == 0)"); void WriteTryStart() { writer.WriteLinePrefix($"memcpy(CS2X_ThreadExceptionJmpBuff, {jmpBuff}, sizeof(jmp_buf));"); } BlockStartCallback = WriteTryStart; WriteStatement(statement.Block); // write catches writer.WriteLinePrefix("else /* end try */"); writer.WriteLinePrefix('{'); writer.AddTab(); writer.WriteLinePrefix($"memcpy(CS2X_ThreadExceptionJmpBuff, {jmpBuffLast}, sizeof(jmp_buf));"); var first = statement.Catches.FirstOrDefault(); foreach (var c in statement.Catches) { if (c.Filter != null) { throw new NotSupportedException("Catch blocks do not support filters: " + c.ToFullString()); } if (c.Declaration != null) { var type = ResolveType(c.Declaration.Type); writer.WritePrefix(); if (c != first) { writer.Write("else "); } writer.WriteLine($"if (CS2X_IsType((({GetTypeFullName(specialTypes.objectType)}*)CS2X_ThreadExceptionObject)->CS2X_RuntimeType, &{GetRuntimeTypeObjFullName(type)})) /* catch */"); } else { writer.WriteLinePrefix("/* empty catch */"); } void WriteCatchStart() { if (c.Declaration != null) { var type = ResolveType(c.Declaration.Type); var local = TryAddLocal(c.Declaration.Identifier.ValueText, type); writer.WriteLinePrefix($"{local.name} = CS2X_ThreadExceptionObject;"); } writer.WriteLinePrefix("CS2X_ThreadExceptionObject = 0;"); } BlockStartCallback = WriteCatchStart; WriteStatement(c.Block); } writer.WriteLinePrefix("if (CS2X_ThreadExceptionObject != 0) longjmp(CS2X_ThreadExceptionJmpBuff, 1); /* throw unhandled exception */"); writer.RemoveTab(); writer.WriteLinePrefix('}'); writer.WriteLinePrefix($"memcpy(CS2X_ThreadExceptionJmpBuff, {jmpBuffLast}, sizeof(jmp_buf));"); writer.WriteLinePrefix("/* end catch */"); --tryCatchNestingLevel; }