RBScript is very powerful. I’m using it to drive exports and “rules” in my program. Why? Because then I have all those items being plugin objects, and people could add their own if they want. Since RBScript is also compiled, there isn’t hardly any overhead between REALbasic code and RBScript.
The “problem” (more like, blessing) of RBScript is that it’s sandboxed. It has the basic intrinsic functions, such as string and math operations, but it doesn’t expose anything from the framework. This is good, however, because it means that you can expose exactly what you want to, and nothing else. All you do is provide a “Context” object, which lets the user have access to everything on that class.
So, how do you expose more classes than just the context’s class? It’s a little bit of brute work, but it can be done. I’ve devised a pretty cool method to do this which I’m going to share.
The first thing I did was I created a new class that I will have each of my contexts subclass. I called mine “BaseContext” and I decided there needed to be three methods: OwnObject, RetrieveObject, and DisposeObject. Also, I’m using the REALbasic dictionary to help out. Here’s what the class looks like:
Class BaseContext
Private pObjectDict As Dictionary
Protected Function OwnObject(obj As Object) As Integer
Dim v As Variant
If obj = Nil Then Return 0
v = obj
If pObjectDict = Nil Then pObjectDict = New Dictionary
pObjectDict.Value(v.Hash) = v
Return v.Hash
End Function
Protected Sub RemoveObject(hash As Integer)
If hash = 0 Then Return
If pObjectDict = Nil Then pObjectDict = New Dictionary
Try
pObjectDict.Remove hash
Catch k As KeyNotFoundException
End Try
End Sub
Protected Function RetrieveObject(hash As Integer) As Object
If hash = 0 Then Return Nil
If pObjectDict = Nil Then pObjectDict = New Dictionary
Try
Return pObjectDict.Value(hash)
Catch k As KeyNotFoundException
Return Nil
End Try
End Function
End Class
Looks pretty straightforward, right? Well, here’s how we’re going to use it. Insert this into each of the RBScript source files before giving the source to RBScript:
Class RBOwnedClass
Dim privateHash As Integer
Public Sub Constructor( hash As Integer )
privateHash = hash
End Sub
Public Sub Destructor()
pDisposeObject( privateHash )
End Sub
End Class
So, now, whenever there is a Class defined that inherits from RBOwnedClass, it can be constructed with this “hash” when we store in the dictionary. So, how would you use it? Let’s take the Date class for example (note, these aren’t all the methods, and it’s read-only):
Class Date
Inherits RBOwnedClass
Public Function Month() As Integer
Return pDateGetMonth( privateHash )
End Function
Public Function Day() As Integer
Return pDateGetDay( privateHash )
End Function
Public Function Year() As Integer
Return pDateGetYear( privateHash )
End Function
Public Function Hour() As Integer
Return pDateGetHour( privateHash )
End Function
Public Function Minute() As Integer
Return pDateGetMinute( privateHash )
End Function
End Class
Now, in the context object, you are responsible for defining pDateGet*. As an example, this is what pDateGetMonth would look like:
Function pDateGetMonth(hash As Integer) As Integer
Return Date(RetrieveObject(hash)).Month
End Function
It is laborious to expose many classes, but take it in sections and it’s not so bad. Plus, you can reuse a lot if you are going to use RBScript again in the future.
For this project, I have to expose my internal data structures in a read-only mode, and then the script can simply loop over all the data and analyze it, export it, etc. RBScript is cool 