logo WinWrap®

Symbol Information

WinWrap® Basic is an embedded macro language component available for .NET and COM 32/64 bit Windows applications. The WinWrap® Basic Component is an alternative to Visual Basic for Applications (VBA), ActiveX (e.g. VBScript, JScript, PerlScript, Rexx-based WSH engines and others), and VSTA for this purpose. The WinWrap® Basic Component is compatible with VBA, Sax Basic, VB.NET and Visual Basic 6.0 style scripts.

Symbol Information

  • Script, Module or Project does not need to be parsed for execution
  • Get Global Methods, Structures, Types, Modules, Classes and Enums
  • Get Members of Scripts, Structures, Types, Modules, Classes and Enums
  • Return identifier definition location
  • Determine expression result type
  • Supports all scripting languages (WWB-COM, WWB.NET and WWB.NET/Compiled)

Symbol Information

Symbol Information

WinWrap® Basic treats script code as structured collection of symbols. The SymbolInfo method allows an application to determine what's in a script before execution. For this solution we will explore the symbols defined by the Triangle.wwd script. The source code for this solution is available for download here.

The triangle.wwd macro code.

'Attribute VB_Name = "Triangle" '#Language "WWB.NET" Imports System Imports System.Collections.Generic Public Class Triangle ' http://www.mathsisfun.com/algebra/trig-solving-triangles.html Private Corners As New List(Of TriangleCorner) Public Sub New(Sa As Double, Sb As Double, Sc As Double, AA As Double, AB As Double, AC As Double) Corners.Add(New TriangleCorner("A", Sa, AA)) Corners.Add(New TriangleCorner("B", Sb, AB)) Corners.Add(New TriangleCorner("C", Sc, AC)) If Sides + Angles > 3 AndAlso True Then Throw New System.Exception("Over specified triangle") ' End If End Sub Public Function Angle(index As Integer) As Double Return Corners(index).Angle End Function Public Function Side(index As Integer) As Double Return Corners(index).Side End Function Public Function Solve() Dim n As Integer Do n = Sides + Angles If Sides = 3 Then TrySSS() If Sides = 2 AndAlso Angles >= 1 Then TrySAS() If Sides = 2 AndAlso Angles >= 1 Then TrySSA() If Sides = 1 AndAlso Angles >= 2 Then TryAAS() If Angles = 2 Then TryAA() Loop While Not Solved AndAlso Sides + Angles > n ' continue while making progress SortNames() Return Me End Function Public ReadOnly Property Solved As Boolean Get Return Sides = 3 AndAlso Angles = 3 End Get End Property Private Sub TrySSA() SortAngles() If Side(2) <> 0 AndAlso Angle(1) = 0 Then ' Law of Sines: a/sin(A) = b/sin(B) = c/sin(C) ' solve for B: sin(B)/b = sin(C)/c ' solve for B: B = asin(sin(C)*b/c) ' side b is Side(1) ' side c is Side(2) ' angle C is Angle(2) Dim asin = Math.Sin(Angle(2)) * Side(1) / Side(2) ' cope with asin slightly out of range If asin < -1 Then asin = -1 If asin > 1 Then asin = 1 Corners(1).Angle = Math.Asin(asin) End If End Sub Private Sub TrySAS() SortSides() If Angle(0) <> 0 AndAlso Side(0) = 0 Then ' Law of Cosines: a^2 = b^2 + c^2 - 2*b*c*cos(A) ' solve for a: a = sqrt(b^2 + c^2 - 2*b*c*cos(A)) ' angle A is Angle(0) ' side b is Side(1) ' side c Side(2) ' side a is Side(0) Corners(0).Side = Math.Sqrt(Side(1) ^ 2 + Side(2) ^ 2 - 2 * Side(1) * Side(2) * Math.Cos(Angle(0))) End If End Sub Private Sub TryAA() SortAngles() If Angle(0) = 0 Then ' Law of Angles: A + B + C = 180 ' solve for A: A = 180 - B - C ' angle A is Angle(0) ' angle B is Angle(1) ' angle C is Angle(2) Corners(0).Angle = Math.PI - Angle(1) - Angle(2) End If End Sub Private Sub TryAAS() SortSides() If Side(1) = 0 Then SortAngles() ' Law of Sines: a/sin(A) = b/sin(B) = c/sin(C) ' solve for b: b = c*sin(B)/sin(C) ' side b is Side(1) ' angle B is Angle(1) ' side c is Side(2) ' angle C is Angle(2) Corners(1).Side = Side(2) * Math.Sin(Angle(1)) / Math.Sin(Angle(2)) End If End Sub Private Sub TrySSS() SortAngles() If Angle(0) = 0 Then ' Law of Cosines: a^2 = b^2 + c^2 - 2*b*c*cos(A) ' solve for A: A = acos((b^2 + c^2 - a^2)/(2*b*c)) ' side a is Side(0) ' side b is Side(1) ' side c is Side(2) ' angle A is Angle(0) Corners(0).Angle = Math.Acos((Side(1) ^ 2 + Side(2) ^ 2 - Side(0) ^ 2) / (2 * Side(1) * Side(2))) 'If Double.IsNaN(Corners(0).Angle) Then 'Throw New System.Exception("Sides can not make a triangle.") 'End If End If End Sub Private Sub SortNames() Dim tc As New TriangleCornerNameComparer Corners.Sort(tc) End Sub Private Sub SortSides() Dim tc As New TriangleCornerSideComparer Corners.Sort(tc) End Sub Private Sub SortAngles() Dim tc As New TriangleCornerAngleComparer Corners.Sort(tc) End Sub Private ReadOnly Property Sides() As Integer ' count sides Get Dim cnt As Integer = 0 For Each Corner As TriangleCorner In Corners If Corner.Side <> 0 Then cnt = cnt + 1 Next Return cnt End Get End Property Private ReadOnly Property Angles() As Integer Get Dim cnt As Integer = 0 For Each Corner As TriangleCorner In Corners If Corner.Angle <> 0 Then cnt = cnt + 1 Next Return cnt End Get End Property Private Function PieceDescription(piece As Double) As String If piece = 0 Then Return "0(Empty)" Else Return piece.ToString() End If End Function Public Overrides Function ToString() As String Dim s As String = "" For Each Corner As TriangleCorner In Corners Dim sCorner As String = "(Side=" & PieceDescription(Corner.Side) & ", Angle=" & PieceDescription(Corner.Angle) & ")" s = If(s <> "", s & " ", s) & sCorner Next Return s End Function End Class Public Class TriangleCorner Public Name As String Public Side As Double Public Angle As Double Public Sub New(aname As String, aside As Double, aangle As Double) Name = aname Side = aside Angle = aangle End Sub Public Overrides Function ToString() As String Return String.Format("Side={0}, Angle={1}", Side, Angle) End Function End Class Public Class TriangleCornerNameComparer Implements IComparer(Of TriangleCorner) Public Function Compare(x As TriangleCorner, y As TriangleCorner) As Integer Implements IComparer(Of TriangleCorner).Compare Return x.Name.CompareTo(y.Name) End Function End Class Public Class TriangleCornerSideComparer Implements IComparer(Of TriangleCorner) Public Function Compare(x As TriangleCorner, y As TriangleCorner) As Integer Implements IComparer(Of TriangleCorner).Compare Return If(x.Side = y.Side, x.Angle.CompareTo(y.Angle), x.Side.CompareTo(y.Side)) End Function End Class Public Class TriangleCornerAngleComparer Implements IComparer(Of TriangleCorner) Public Function Compare(x As TriangleCorner, y As TriangleCorner) As Integer Implements IComparer(Of TriangleCorner).Compare Return If(x.Angle = y.Angle, x.Side.CompareTo(y.Side), x.Angle.CompareTo(y.Angle)) End Function End Class

Download the sample code, compile and run it. Here's what clicking on the Triangle.wwd entry in the Choose Macro list looks like.

Global Symbol Information

The host code below returns the public and private Global members of the script below with results "Global Members and Types" as shown in the diagram above.

// Get Global Members and Types string jsonresult = basicNoUIObj_.SymbolInfo(filename_, "Global", 0, false); textBoxSymbolInfo.Text = jsonresult; dynamic result = WinWrap.Basic.Util.ParseJson(jsonresult);

SymbolInfo returns a json object (jsonresult in the code above) describing the symbol. For the Triangle.wwd script the global SymbolInfo method returns this string:

{"symbol_kind":"Global", "module_kind":"Macro", "module_name":"E:\\git\\Working-business\\SolutionsExamples\\GetSymbolInfo\\GetSymbolInfo\\bin\\Debug\\Macros\\Triangle.wwd", "user_defined":true, "last_read_error":"", "known":true, "language":2, "loaded":false, "revision":1, "hidden_len":0, "hidden_lines":0, "imports":["System","System.Collections.Generic","System","System.Collections.Generic"], "types":["Triangle","TriangleCorner","TriangleCornerNameComparer","TriangleCornerSideComparer","TriangleCornerAngleComparer"]}

The "members" json member is absent indicating that Triangle.wwd doesn't have any top-level Subs, Functions or Properties. The "types" json member indicates that Triangle.wwd defines five classes: Triangle, TriangleCorner, TriangleCornerNameComparer, TriangleCornerSideComparer and TriangleCornerAngleComparer. Refer to SymbolInfo's result documentation for a complete description of the json object's members.

Util.ParseJson

The WinWrap.Basic.Util.ParseJson method returns a dynamic .NET object which facilitates working with the SymbolInfo result. The application code below adds the members and types to the listbox.

string jsonresult = basicNoUIObj_.SymbolInfo(filename_, "Global", 0, false); textBoxSymbolInfo.Text = jsonresult; dynamic result = WinWrap.Basic.Util.ParseJson(jsonresult); listBoxGlobalMembers.Items.Clear(); listBoxGlobalMembers.Items.AddRange((string[])result.members); listBoxGlobalMembers.Items.AddRange((string[])result.types);

Class, Enum, Module, Structure and Type Symbol Information

These constructs define containers of symbols. SymbolInfo can get the symbols contained in one of thes symbols. There are two ways to get symbol information from a symbol. Provide a location in the text or provide an expression with that location.

Location Based Symbol Information

When SymbolInfo is provided just a location it determines the expression at that location and returns symbol information about the result of the expression. In this case it is the Triangle class.

// Get Global Members and Types string jsonresult = basicNoUIObj_.SymbolInfo(filename_, "", 127, false); textBoxSymbolInfo.Text = jsonresult; dynamic result = WinWrap.Basic.Util.ParseJson(jsonresult);

Clicking on a symbol in the Macro calls SymbolInfo with the caret location. Here's what clicking on Triangle in the Class line looks like.

Triangle Class Symbol Information

Expression and Location Based Symbol Information

When SymbolInfo is provided an expression and a location it determines the symbol information about the expression by location's scope. In this case it is the Corner member in the Triangle class.

// Get Global Members and Types string jsonresult = basicNoUIObj_.SymbolInfo(filename_, "Corner", 128, false); textBoxSymbolInfo.Text = jsonresult; dynamic result = WinWrap.Basic.Util.ParseJson(jsonresult);

Summary

The SymbolInfo method provides the host application with a way to determine what symbols are defined by a script, module, project or project member.

Copyright Polar Engineering, Inc.