Quantcast
Channel: VBForums - CodeBank - Visual Basic 6 and earlier
Viewing all articles
Browse latest Browse all 1530

The VarFrame Class

$
0
0
This is a new class to hold a frame of variables. This can help on making script languages, to keep variables, which means sets of Names and Values.
The interesting part, is how we can establish a reference system, so for each entity we can address to it by a long number, which have two parts, the target VarFrame and the actual position on that Varframe. Also the second part has two parts, the least 12 bits is the actual index number, and the last 4 bit used to indicate the type of the variable, and the actual array (we have for each basic type, one array).


So one type for these "basic types" is the reference one. Is an array which hold references for other VarFrames. These references are not like object references (is a kind of indirection).

For use it in a Virtual Machine for a script language, we can use the low part, as the local variable (two bytes only). The reference variable can be included in the local Varframe, which means we get also two bytes and the VarFrame handle the actual reference (and get the actual type) of the variable.

So with two bytes we may have 4096 variables of same type, 15 types and 1 type for the reference system. Also the Varframe never delete an insert (supposed the varframe can be recycled after the end of use). One type is the variant type. And there is the object type so we may have arrays. through RefArray which make arrays for any type, without using an array of variants which take a lot of space. And this is the goal for this class, to handle "local variables" for a custom virtual machine for a custom script language.

Another use is for user Objects. I didn't show that here, but I can "draw" the idea. Some arrays in VarFrame are for Modules/Functions, which supposed to be local two. So an object is a "movable" part, a "value", and a VarFrame can be done such thing. The difference is that as a Varframe, it can't be reference through a Handler (the top part), except we can use an immediate way, when a method call another method, to add the This Varframe to a one time use of handler, and pass the compound pointer (as reference) to the external method, and then at the return of execution, and the return of the object's method, we just throw the link for the handler to This Varframe (the objec'ts VarFrame). So using Custom Objects, means an expansion for the Handlers (some Handlers may used for temporary use, means can show some other VarFrame later).

So you can now forget the mention about custom objects, and focus to the program here.

The idea for VarFrame, are to NOT INCLUDE names in the varframe. So we have HASH LISTS, without saving the names as "strings". We have one HashList for all names. So a name ALFA maybe is a string in VarFrame A, but a long in varFrame B. So each Identifier NAME has a unique ID.

The Varframe has one Hash table for all types (all included arrays). Some types that not used are not exist, they have an empty "slot".

So VarFrame it's different from ordinary Hash Tables/Lists. One Hash table, addressing multiple arrays. (arrays of values for the variables, arrays per type).

For a script language, we need a way to store/retrieve values, through a "search" system (using name) and for a JIT we need a way to reference the values, without using names, just pointers (or for VarFrame, the 16bit compound indexes), and if we need references to other VarFrames, we can use handlers (16bit, as High Integer Value of a Long Value).

The HashList, and the VarFrame can used for values with same name. We can use two or more same keys, and we can "walk" easy on them.


The program in zip file has some examples:

let see the global variables:

Code:

Global Const VbLongLong = 20Dim poolVarFrame() As VarFrame
Dim poolMax As Integer, NextPoolIndex As Integer
Dim poolHandlers() As Integer
Dim MaxHandler As Integer, Nexthandler As Integer, TopHandler As Integer
Public Identifiers As New HashList
Public LiteralsNum As New HashList
Public LiteralsStr As New HashList

We use Long Long also (64bit Integers)
We make a pool of VarFrames, so each time we need we see if exist in the pool and take it from there.
The basic idea is that we have Handlers which is the numbers which are the top part of a "Referenced" variable.


The VarFrame is a mix of a refArray and a Hashlist. (the last two classes I was introduced them some days ago, but here we have updated classes).

This example show how the reference work (through the WeakPtr, the compound index)

Code:

Sub main1()    Identifiers.Prepare 2000
    TopHandler = -1: poolMax = -1: NextPoolIndex = -1: MaxHandler = -1: Nexthandler = -1
    AddHandlers 100: ExpandPool 100:
    Dim a As Integer, b As Integer
    a = NeoVar.NewVarFrame()
    b = NeoVar.NewVarFrame()
    Dim aa As VarFrame, bb As VarFrame
    Set aa = poolVarFrame(a)
    Set bb = poolVarFrame(b)
   
    Debug.Print aa.VarCount(), bb.VarCount()
    aa.AddVar "ALFA$", "HELLO THERE"
    bb.AddVar "ALFA1$", "HELLO THERE AND THERE"
    aa.AddVar "DBLBETA", 123#
    bb.AddVar "DBLDELTA", 500#
    Dim val
    If aa.Find("ALFA$", val) Then
        Debug.Print "aa.ALFA$ = "; val
    End If
    If bb.Find("ALFA1$", val) Then
        Debug.Print "bb.ALFA1$ = "; val
    End If
    If aa.Find("DBLBETA", val) Then
        Debug.Print "aa.DBLBETA = "; val
    End If
    If bb.Find("DBLDELTA", val) Then
        Debug.Print "bb.DBLDELTA = "; val
    End If
    Dim WeakPtr, ptr1, ptr2
    If aa.Find("ALFA$", , WeakPtr) Then
        Debug.Print "aa.ALFA$ has weak ptr: ", aa.VarId(WeakPtr)
        Debug.Print "handelr: "; aa.HandlerFromWeak(WeakPtr)
        Debug.Print "Value from WeakPtr = "; aa(WeakPtr)
        WeakPtr = bb.AddRefVar("HELLO$", WeakPtr)
        Debug.Print "bb.HELLO$ is a reference to aa.ALFA$"
        Debug.Print "local ptr="; WeakPtr
        Debug.Print "Value from Local Ptr ="; bb(WeakPtr)
        bb(WeakPtr) = "New Value"
        Debug.Print "Value from Local Ptr ="; bb(WeakPtr)
    End If
    If bb.Find("HELLO$", val, WeakPtr) Then
        Debug.Print "bb.HELLO$ = "; val
        Debug.Print "bb.HELLO$ has weak ptr: ", bb.VarId(WeakPtr)
        Debug.Print "handelr: "; bb.HandlerFromWeak(WeakPtr)
        Debug.Print "Value from WeakPtr = "; bb(WeakPtr)
       
    End If
    If bb.Find("ALFA1$", , WeakPtr) Then
        Debug.Print "bb.ALFA1$ has weak ptr: ", bb.VarId(WeakPtr)
        Debug.Print "handelr: "; bb.HandlerFromWeak(WeakPtr)
        Debug.Print "Value from WeakPtr = "; bb(WeakPtr)
    End If
        If aa.Find("ALFA$", val) Then
        Debug.Print "aa.ALFA$ = "; val
    End If
    Debug.Print aa.Count(), bb.Count(), " Total fields"
    Debug.Print aa.VarCount(), bb.VarCount()
    Debug.Print "Identifier at id 0: "; Identifiers.Key(0)
    Debug.Print "Total Identifiers: "; Identifiers.Count
    Dim zero As Long
    zero = LiteralsNum.Add(0#, "0", vbVariant)
    Dim zerolong As Long
    zerolong = LiteralsNum.Add(0&, "0&", vbVariant)
    Debug.Print zero, " zero id", TypeName(LiteralsNum(zero))
    Debug.Print zerolong, " zeroLong id", TypeName(LiteralsNum(zerolong))
    Debug.Print "Total number literals: "; LiteralsNum.Count
    Dim vars As HashList
    Set vars = bb.VarNamesList()
    Dim i As Long
    For i = 0 To vars.Count - 1
        Debug.Print vars(i), Hex$(vars.KeyNum2(i))
    Next i
    Debug.Print Join$(aa.VarNamesList("AA.").Values, ", ")
    Debug.Print Join$(bb.VarNamesList("BB.").Values, ", ")
 
End Sub

This example show the HashList with rename function.


Code:

Sub main()' using HashList as Variant type
Dim hash1 As New HashList
hash1.Prepare 1000
' just mark the first item as VbVariant
hash1.Add 10, "integer1", vbVariant
hash1.Add "hello", "String1"
hash1.Add hash1.cInt64("123456789012345678"), "long long 1"
hash1.Add CDec("12345678901234567800123456"), "Decimal 1"
hash1(1) = 50000
Debug.Print hash1(0), hash1(1), hash1(2), hash1(3)
hash1(0) = hash1(0) + 100
hash1(1) = 50000  ' change type
Debug.Print hash1(0), hash1(1), hash1(2), hash1(3)
hash1(2) = "ok" 'change type
Debug.Print hash1(0), hash1(1), hash1(2), hash1(3)
Debug.Print hash1.cInt64("123456789012345678")
Dim val, there, i As Long
If hash1.Find("long long 1", , there) Then
    hash1.KeyNoReHash(there) = "New Key"
End If
If hash1.Find("New Key", val) Then
    Debug.Print "Value at New Key = ", val
End If
If hash1.Find("Decimal 1", , there) Then
    hash1.Key(there) = "New Key"
    ' so now we do rehash here
End If
If hash1.Find("New Key", val) Then
    Debug.Print "Value at New Key = ", val
End If


Debug.Print "List"
For i = 0 To hash1.Count - 1
Debug.Print hash1(i), hash1.Key(i)
Next i
End Sub

Attached Files

Viewing all articles
Browse latest Browse all 1530

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>