MathGroup Archive 2003

[Date Index] [Thread Index] [Author Index]

Search the Archive

Mathematica + NETLink + CodeDom- Example 2

  • To: mathgroup at smc.vnet.net
  • Subject: [mg45304] Mathematica + NETLink + CodeDom- Example 2
  • From: ToolmakerSteve at shawstudio.com (ToolmakerSteve)
  • Date: Mon, 29 Dec 2003 00:22:11 -0500 (EST)
  • Sender: owner-wri-mathgroup at wolfram.com

(Follow on to [mg45085] NETLink - CREATING a new class?
I have submitted this to support@wolfram,
and explained that I hope it will be given to a programmer
who is working on NETLink -
so that the problems I encountered in mg45085 can be resolved,
and so that some example like this can be included in the NETLink documentation,
in hopes that some other O-O .NET programmers can be enticed to use Mathematica.
)

Here is a more interesting notebook,
which creates a .NET assembly without
having to type all those "NETNew" expressions.

It contains a package "NetCodeGen",
which is a translator from a simple structure in Mathematica,
which represents the assembly as code snippets within some structural
constructs.

(By The Way, this is far more readable than the XML version of code that some
people are starting to work with in other environments.)

For example, here is "Hello Net World" source code, in its Mathematica form:

Namespace[ "MyNamespace",
  Using[
    "System",
    "System.Windows.Forms"
    ],
  Class[ "HelloWorldMsgApp",
    {
      EntryMethod[ "Main",
        {
           "MessageBox.Show( \"Hello, .NET World!\" )"
          }
        ]
      }
    ]
  ]

Below is the notebook expression with all the details.

-- ToolmakerSteve
= = = = = = = = = = = = = = = = = = = = = = = = = = =
Notebook[{
Cell[TextData[StyleBox["(* 60-HelloNetWorld-SnippetSyntax.\nBetter \
than typing in NETLink expressions to call CodeDom methods, and far \
easier to implement than a full C# recursive descent parser:\nHere is \
a structure translator that builds up a NET assembly from \
code-snippets and CodeDom structural methods,\nby associating a \
symbol with each method.\n*)",
  FontSize->14,
  FontWeight->"Bold"]], "Subsubtitle"],

Cell[CellGroupData[{

Cell[BoxData[{
    \(\(\(BeginPackage["\<NETCodeGen`\>"]\)\(\[IndentingNewLine]\)
    \)\), "\[IndentingNewLine]", 
    \(\(\(Needs["\<NETLink`\>"]\)\(\n\)\(\[IndentingNewLine]\)\( (*\ \
\(--\(-\ Quiet\)\)\ spell\ warnings\  + \ 
        limit\ output\ \(length\ --\) - \ \
*) \)\(\[IndentingNewLine]\)
    \) (*\ TBD : \ Hold\ current\ values, \ 
      so\ can\ restore\ at\ end\ of\ \(\(package\)\(.\)\)\ *) \), "\
\[IndentingNewLine]", 
    \(Off[General::spell]; \ \ \ Off[General::spell1];\), "\n", 
    \(\($PrePrint = 
        Short[#, 50] &;\)\[IndentingNewLine]\[IndentingNewLine] (*\ 
      Load\ type \((s)\)\ to\ call\ static\ members . \ 
          Move\ HERE\ for\ \(\(PERFORMANCE\)\(?\)\); \
\[IndentingNewLine]Need\ here\ to\ resolve\ during\ \(\(compilation\)\
\(?\)\)\ *) \), "\[IndentingNewLine]", 
    \(\(\(LoadNETType[\ "\<System.CodeDom.MemberAttributes\>"\ ];\)\(\
\[IndentingNewLine]\)
    \)\), "\[IndentingNewLine]", 
    \(\(\(BuildAssembly::usage = \[IndentingNewLine]"\<BuildAssembly[ \
tree1, fileName1 ]\>"\)\(\[IndentingNewLine]\)
    \)\), "\[IndentingNewLine]", 
    \(\(\(DumpNamespace::usage = \[IndentingNewLine]"\<DumpNamespace[ \
namespace1 ]\>"\)\(\[IndentingNewLine]\)
    \)\), "\[IndentingNewLine]", 
    \(\(\(Namespace::usage = \[IndentingNewLine]"\<type: Namespace[ \
<name>,Class[...] ]\>"\)\(\[IndentingNewLine]\)
    \)\), "\[IndentingNewLine]", 
    \(\(\(Using::usage = \[IndentingNewLine]"\<type: Using[ <name>,.. \
]\>"\)\(\[IndentingNewLine]\)
    \)\), "\[IndentingNewLine]", 
    \(\(\(Class::usage = \[IndentingNewLine]"\<type: Class[ \
<name>,Using[...], { <member>,.. } ]\>"\)\(\[IndentingNewLine]\)
    \)\), "\[IndentingNewLine]", 
    \(\(\(EntryMethod::usage = \[IndentingNewLine]"\<type: \
EntryMethod[ <name>, { <statement>,.. } ]\>"\)\(\[IndentingNewLine]\)
    \)\), "\[IndentingNewLine]", 
    \(\(\(Method::usage = \[IndentingNewLine]"\<type: Method[ <name>, \
{ <statement>,.. } ]\>"\)\(\[IndentingNewLine]\)
    \)\), "\[IndentingNewLine]", 
    \(\(Begin["\<`Private`\>"];\)\[IndentingNewLine]\
\[IndentingNewLine] (*\ \(--\(--\(-\ \ \(--\(---\)\)\)\)\)\ *) \), "\
\[IndentingNewLine]", 
    \(\(BuildAssembly[\[IndentingNewLine]Namespace[\[IndentingNewLine]\
namespaceName1_String, \[IndentingNewLine]imports_Using, \
\[IndentingNewLine]type1_Class\  (*\ 
              FUTURE : \ 
                or\ other\ TYPE\ *) \[IndentingNewLine]], \
\[IndentingNewLine]fileName1_\ ] := \[IndentingNewLine]NETBlock[\
\[IndentingNewLine]Module[\ {netSpace1, 
              netType1}, \[IndentingNewLine]netSpace1 = 
              NewNamespace[\ 
                namespaceName1\ ]; \[IndentingNewLine]AddImports[\ 
              imports, netSpace1\ ]; \[IndentingNewLine]netType1 = 
              NewPublicType[\ type1, 
                netSpace1\ ]; \[IndentingNewLine]\[IndentingNewLine] \
(*\ TBD : \ 
                Compile\ the\ \(\(assembly\)\(.\)\)\ \
*) \[IndentingNewLine]\[IndentingNewLine] (*\ 
              TBD : \ 
                output\ compiled\ assembly\ to\ \(\(file\)\(.\)\)\ \
*) \[IndentingNewLine]"\<assembly \>" <> namespaceName1 <> "\<-->\>" <> 
                fileName1 // 
              Print; \[IndentingNewLine]\[IndentingNewLine] (*\ 
              TESTING - \ 
                dump\ contents\ of\ \(\(assembly\)\(.\)\)\ \
*) \[IndentingNewLine]DumpNamespace[\ 
              netSpace1\ ]; \[IndentingNewLine] (*\ 
              NOTE : \ 
                If\ this\ RETURNS\ netSpace1, \[IndentingNewLine]then\
\ "\<netSpace1\>"\ escapes\ "\<NETBlock[..]\>"\  - \
\[IndentingNewLine]in\ which\ case\ client\ should\ call\ \
"\<ReleaseNETObject[ netSpace1 ]\>"\ *) \[IndentingNewLine] (*\ 
              
              netSpace1\ *) \[IndentingNewLine]]\[IndentingNewLine]];\
\)\[IndentingNewLine]\[IndentingNewLine] (*\ \(--\(--\(-\ \ \(--\(---\
\)\)\)\)\)\ *) \), "\[IndentingNewLine]", 
    \(\(DumpNamespace[\ 
          netSpace1_\ ] := \[IndentingNewLine]Module[\ {}, \
\[IndentingNewLine]"\<Namespace: \>" <> \((netSpace1@Name)\) // 
            Print; \[IndentingNewLine]DumpImports[\ 
            netSpace1\ ]; \[IndentingNewLine]DumpTypes[\ 
            netSpace1\ ];\[IndentingNewLine]];\)\[IndentingNewLine]\
\[IndentingNewLine] (*\ \(--\(--\(-\ \ \(--\(---\)\)\)\)\)\ *) \), "\
\[IndentingNewLine]", 
    \(\(NewNamespace[\ 
          namespaceName1_String\ ] := \[IndentingNewLine]Module[\ \
{netSpace1}, \[IndentingNewLine]netSpace1 = 
            NETNew[\ "\<System.CodeDom.CodeNamespace\>"\ ]; \
\[IndentingNewLine]netSpace1@Name = 
            namespaceName1; \[IndentingNewLine]netSpace1\
\[IndentingNewLine]];\)\[IndentingNewLine]\[IndentingNewLine] (*\ \(\
--\(--\(-\ \ \(--\(---\)\)\)\)\)\ *) \), "\[IndentingNewLine]", 
    \(\(AddImports[\ imports_, 
          netSpace1_\ ] := \[IndentingNewLine]Module[\ {netImports}, \
\[IndentingNewLine]netImports = 
            netSpace1@Imports; \[IndentingNewLine]Map[\ 
            AddImport[\ #, netImports\ ] &, 
            imports\ ];\[IndentingNewLine]];\)\[IndentingNewLine]\), \
"\[IndentingNewLine]", 
    \(\(AddImport[\ importName1_String, 
          netImports_\ ] := \[IndentingNewLine]netImports@
          Add[\ NETNew[\ "\<System.CodeDom.CodeNamespaceImport\>", 
              importName1\ ]\ ];\)\[IndentingNewLine]\), "\
\[IndentingNewLine]", 
    \(\(DumpImports[\ 
          netSpace1_\ ] := \[IndentingNewLine]Module[\ {netImports, 
            count}, \[IndentingNewLine]netImports = 
            netSpace1@Imports; \[IndentingNewLine]count = 
            netImports@
              Count; \[IndentingNewLine] (*\ \("\<# imports: \>" <> 
                  ToString[\ count\ ] // 
                Print;\)\ \
*) \[IndentingNewLine]Do[\[IndentingNewLine]DumpImport[\ 
              netImports@Item[\ i - 1\ ]\ ], \  (*\ 
              ZERO - BASED\ *) \[IndentingNewLine]{i, 
              count}\[IndentingNewLine]];\[IndentingNewLine]];\)\
\[IndentingNewLine]\), "\[IndentingNewLine]", 
    \(\(DumpImport[\ 
          import1_\ ] := \[IndentingNewLine]Module[\ {}, \
\[IndentingNewLine]\("\<using: \>" <> \((import1@Namespace)\) // 
              Print;\)\[IndentingNewLine]];\)\[IndentingNewLine]\
\[IndentingNewLine] (*\ \(--\(--\(-\ \ \(--\(---\)\)\)\)\)\ *) \), "\
\[IndentingNewLine]", 
    \(\(NewPublicType[\ 
          Class[\[IndentingNewLine]className1_String, \
\[IndentingNewLine]members_List\[IndentingNewLine]], 
          netSpace1_\ ] := \[IndentingNewLine]Module[\ {class1}, \
\[IndentingNewLine]class1 = 
            NewPublicType[\ className1, netSpace1, 
              True\ ]; \[IndentingNewLine]AddMembers[\ members, 
            class1\ ]; \[IndentingNewLine]class1\[IndentingNewLine]];\
\)\[IndentingNewLine]\), "\[IndentingNewLine]", 
    \(\(NewPublicType[\ typeName1_String, netSpace1_, 
          isClass_Symbol\ ] := \[IndentingNewLine]Module[\ {netType1, 
            spaceTypes1}, \[IndentingNewLine] (*\ 
            Load\ type \((s)\)\ to\ call\ static\ members . \ \
\(\(PERFORMANCE\)\(?\)\)\ *) \[IndentingNewLine]LoadNETType[\ \
"\<System.CodeDom.MemberAttributes\>"\ ]; \[IndentingNewLine]\
\[IndentingNewLine]netType1 = 
            NETNew[\ "\<System.CodeDom.CodeTypeDeclaration\>"\ ]; \
\[IndentingNewLine]netType1@Name = 
            typeName1; \[IndentingNewLine]netType1@IsClass = 
            isClass; \[IndentingNewLine] (*\ \(TBD\ netType1@
                    Attributes = 
                MemberAttributes`Public;\)\ *) \[IndentingNewLine]\
\[IndentingNewLine]spaceTypes1 = 
            netSpace1@Types; \[IndentingNewLine]spaceTypes1@
            Add[\ netType1\ ]; \[IndentingNewLine]netType1\
\[IndentingNewLine]];\)\[IndentingNewLine]\), "\[IndentingNewLine]", 
    \(\(DumpTypes[\ 
          netSpace1_\ ] := \[IndentingNewLine]Module[\ {netTypes, 
            count}, \[IndentingNewLine]netTypes = 
            netSpace1@Types; \[IndentingNewLine]count = 
            netTypes@Count; \[IndentingNewLine]"\<# types: \>" <> 
              ToString[\ count\ ] // 
            Print; \[IndentingNewLine]Do[\[IndentingNewLine]DumpType[\
\ netTypes@Item[\ i - 1\ ]\ ], \  (*\ 
              ZERO - BASED\ *) \[IndentingNewLine]{i, 
              
              count}\ ];\[IndentingNewLine]];\)\[IndentingNewLine]\), \
"\[IndentingNewLine]", 
    \(\(DumpType[\ 
          netType1_\ ] := \[IndentingNewLine]Module[\ {}, \
\[IndentingNewLine]"\<type: \>" <> \((netType1@Name)\) // 
            Print; \[IndentingNewLine]DumpMembers[\ 
            netType1\ ];\[IndentingNewLine]];\)\[IndentingNewLine]\
\[IndentingNewLine] (*\ \(--\(--\(-\ \ \(--\(---\)\)\)\)\)\ *) \), "\
\[IndentingNewLine]", 
    \(\(AddMembers[\ members_List, 
          type1_\ ] := \[IndentingNewLine]Module[\ {}, \
\[IndentingNewLine]\(Map[\ AddMember[\ #, type1\ ] &, 
              members\ ];\)\[IndentingNewLine]];\)\[IndentingNewLine]\
\), "\[IndentingNewLine]", 
    \(\(AddMember[\ memberStuff_, 
          type1_\ ] := \[IndentingNewLine]Module[\ {member1}, \
\[IndentingNewLine]member1 = 
            BuildMember[\ 
              memberStuff\ ]; \[IndentingNewLine]\((type1@Members)\)@
            Add[\ member1\ ]; \[IndentingNewLine]member1\
\[IndentingNewLine]];\)\[IndentingNewLine]\[IndentingNewLine] (*\ 
      TBD : \ Does\ this\ care\ what\ type\ it\ is\ building\ member\ \
\(\(for\)\(?\)\)\ *) \), "\[IndentingNewLine]", 
    \(\(BuildMember[\[IndentingNewLine]EntryMethod[\ 
            methodName_String, 
            statements_List\ ]\ ] := \[IndentingNewLine]Module[\ \
{method1}, \[IndentingNewLine]method1 = 
            NETNew[\ "\<System.CodeDom.CodeEntryPointMethod\>"\ ]; \
\[IndentingNewLine]method1@Name = 
            methodName; \[IndentingNewLine]\[IndentingNewLine] (*\ 
            Load\ type \((s)\)\ to\ call\ static\ members . \ \
\(\(PERFORMANCE\)\(?\)\)\ *) \[IndentingNewLine]LoadNETType[\ \
"\<System.CodeDom.MemberAttributes\>"\ ]; \[IndentingNewLine] (*\ \
\(TBD\ method1@Attributes = 
                NetMergeAttributes[\ MemberAttributes`Public, 
                  MemberAttributes`Static\ ];\)\ \
*) \[IndentingNewLine]\[IndentingNewLine]Map[\ 
            AddStatement[\ #, method1\ ] &, 
            statements\ ]; \[IndentingNewLine]method1\
\[IndentingNewLine]];\)\[IndentingNewLine]\), "\[IndentingNewLine]", 
    \(\(DumpMembers[\ 
          netType1_\ ] := \[IndentingNewLine]Module[\ {netMembers, 
            count}, \[IndentingNewLine]netMembers = 
            netType1@Members; \[IndentingNewLine]count = 
            netMembers@Count; \[IndentingNewLine]"\<# members: \>" <> 
              ToString[\ count\ ] // 
            Print; \[IndentingNewLine]Do[\[IndentingNewLine]\
DumpMember[\ netMembers@Item[\ i - 1\ ]\ ], \  (*\ 
              ZERO - BASED\ *) \[IndentingNewLine]{i, 
              count}\ ];\[IndentingNewLine]];\)\[IndentingNewLine]\), \
"\[IndentingNewLine]", 
    \(\(DumpMember[\ 
          netMember1_\ ] := \[IndentingNewLine]Module[\ {}, \
\[IndentingNewLine]"\<member: \>" <> \((netMember1@Name)\) // 
            Print; \[IndentingNewLine] (*\ 
            TBD : \ Depends\ on\ TYPE\ of\ member\ [field, property, 
                  method]\ *) \[IndentingNewLine] (*\ \
\(DumpStatements[\ 
                netMember1\ ];\)\ *) \[IndentingNewLine]];\)\
\[IndentingNewLine]\[IndentingNewLine] (*\ \(--\(--\(-\ \ \(--\(---\)\
\)\)\)\)\ *) \[IndentingNewLine] (*\ 
      Simplest\ statement\ is\ a\ code\ snippet\ in\ C \( \
\(#\)\(.\)\)\ *) \), "\[IndentingNewLine]", 
    \(\(AddStatement[\ snippetString_String, 
          method1_\ ] := \[IndentingNewLine]Module[\ {statement1, 
            snippet1}, \[IndentingNewLine]snippet1 = 
            NewSnippet[\ 
              snippetString\ ]; \[IndentingNewLine]statement1 = 
            NETNew[\ "\<System.CodeDom.CodeExpressionStatement\>", 
              snippet1\ ]; \[IndentingNewLine]\((method1@
                Statements)\)@
            Add[\ statement1\ ];\[IndentingNewLine]];\)\
\[IndentingNewLine]\[IndentingNewLine] (*\ 
      TBD : \ Statements\ representing\ logic\ structures; \
\[IndentingNewLine]e . 
        g . \ "\<If\>", \ \(\("\<Do\>"\)\(.\)\)\ *) \
\[IndentingNewLine]\[IndentingNewLine] (*\ \(--\(--\(-\ \ \(--\(---\)\
\)\)\)\)\ *) \), "\[IndentingNewLine]", 
    \(\(NewSnippet[\ 
          snippetString_String\ ] := \[IndentingNewLine]NETNew[\ \
"\<System.CodeDom.CodeSnippetExpression\>", \
\[IndentingNewLine]snippetString\ ];\)\[IndentingNewLine]\
\[IndentingNewLine] (*\ \(--\(--\(-\ \ \(--\(---\)\)\)\)\)\ *) \
\[IndentingNewLine] (*\ "\<net1 | net2\>"\ *) \), \
"\[IndentingNewLine]", 
    \(\(NetBitOr[\ net1_, net2_\ ] := \[IndentingNewLine]BitOr[\ 
          NETObjectToExpression[\ net1\ ], 
          NETObjectToExpression[\ 
            net2\ ]\ ];\)\[IndentingNewLine]\[IndentingNewLine] (*\ 
      TBD : \ haven' 
          t\ found\ a\ way\ to\ do\ this\ yet . \ 
            TBD\ *) \), "\[IndentingNewLine]", 
    \(\(NetMergeAttributes[\ net1_, net2_\ ] := 
        net1\  (*\ \(|\)\(\ \)\(net2\)\ *) ;\)\[IndentingNewLine]\), \
"\[IndentingNewLine]", 
    \(\(End[];\)\), "\[IndentingNewLine]", 
    \(EndPackage[]\)}], "Input"],

Cell[BoxData[
    \("NETCodeGen`"\)], "Output"],

Cell[BoxData[
    TagBox["\<\"BuildAssembly[ tree1, fileName1 ]\"\>",
      (Short[ #, 50]&)]], "Output"],

Cell[BoxData[
    TagBox["\<\"DumpNamespace[ namespace1 ]\"\>",
      (Short[ #, 50]&)]], "Output"],

Cell[BoxData[
    TagBox["\<\"type: Namespace[ <name>,Class[...] ]\"\>",
      (Short[ #, 50]&)]], "Output"],

Cell[BoxData[
    TagBox["\<\"type: Using[ <name>,.. ]\"\>",
      (Short[ #, 50]&)]], "Output"],

Cell[BoxData[
    TagBox["\<\"type: Class[ <name>,Using[...], { <member>,.. } \
]\"\>",
      (Short[ #, 50]&)]], "Output"],

Cell[BoxData[
    TagBox["\<\"type: EntryMethod[ <name>, { <statement>,.. } ]\"\>",
      (Short[ #, 50]&)]], "Output"],

Cell[BoxData[
    TagBox["\<\"type: Method[ <name>, { <statement>,.. } ]\"\>",
      (Short[ #, 50]&)]], "Output"]
}, Open  ]],

Cell[CellGroupData[{

Cell[BoxData[
    \(\(\( (*\ 
      An\ example\ assembly\ \
*) \)\(\[IndentingNewLine]\)\(helloNetWorld\[Bullet]Tree = \
\[IndentingNewLine]Namespace[\ "\<MyNamespace\>", \
\[IndentingNewLine]Using[\[IndentingNewLine]"\<System\>", \
\[IndentingNewLine]"\<System.Windows.Forms\>"\[IndentingNewLine]], \
\[IndentingNewLine]Class[\ "\<HelloWorldMsgApp\>", \
\[IndentingNewLine]{\[IndentingNewLine]EntryMethod[\ "\<Main\>", \
\[IndentingNewLine]{\[IndentingNewLine]\ "\<MessageBox.Show( \"Hello, \
.NET World!\" )\>"\[IndentingNewLine]}\[IndentingNewLine]]\
\[IndentingNewLine]}\[IndentingNewLine]]\[IndentingNewLine]]\)\)\)], \
"Input"],

Cell[BoxData[
    TagBox[\(Namespace["MyNamespace", 
        Using["System", "System.Windows.Forms"], 
        Class["HelloWorldMsgApp", {EntryMethod[
              "Main", {"MessageBox.Show( \"Hello, .NET World!\" \
)"}]}]]\),
      (Short[ #, 50]&)]], "Output"]
}, Open  ]],

Cell[CellGroupData[{

Cell[BoxData[
    \(BuildAssembly[\ 
      helloNetWorld\[Bullet]Tree, "\<c:\\Temp\\HelloWorldMsg.exe\>"\ \
]\)], "Input"],

Cell[BoxData[
    \("assembly MyNamespace-->c:\\Temp\\HelloWorldMsg.exe"\)], \
"Print"],

Cell[BoxData[
    \("Namespace: MyNamespace"\)], "Print"],

Cell[BoxData[
    \("using: System"\)], "Print"],

Cell[BoxData[
    \("using: System.Windows.Forms"\)], "Print"],

Cell[BoxData[
    \("# types: 1"\)], "Print"],

Cell[BoxData[
    \("type: HelloWorldMsgApp"\)], "Print"],

Cell[BoxData[
    \("# members: 1"\)], "Print"],

Cell[BoxData[
    \("member: Main"\)], "Print"]
}, Open  ]]
},
FrontEndVersion->"5.0 for Microsoft Windows",
ScreenRectangle->{{0, 1280}, {0, 971}},
CellGrouping->Manual,
WindowSize->{645, 843},
WindowMargins->{{5, Automatic}, {10, Automatic}}
]


  • Prev by Date: Re: AW: AW: Re: Transpose matrix does not work when MatrixForm is used, why?
  • Next by Date: Shortest path algorithm
  • Previous by thread: Re: AW: AW: Re: Transpose matrix does not work when MatrixForm is used, why?
  • Next by thread: Re: Mathematica + NETLink + CodeDom- Example 2