Tlist and Type

Started by Baggey, September 18, 2023, 14:12:08

Previous topic - Next topic

Baggey


As im still Learning im starting to find the usefullness of the Tlist over an Array.

However, Im trying to set a CPUList up and as i add to the list by passing the C6502 Type to it.

I think i understand its an Object because i created the type so its full of Objects. ie random types of data. ints, string, Byte etc.. :-X

I create the list and the CPU type and flagReg type.

Q1, I cant extends the CPU to have the flagReg added?
      If i add the Global flagReg in the CPU and then create C6502 it does?
      How do i Do this?

Q2, If Understand the Tlist it's some form of "Stack"! where we .AddLast(). What i want to do is Pass the C6502 Type in to the List.
      How do I do this as i can't seem to read it back? :(

What am i doing wrong with this code or can it not be done ??? If it worked this Coded Example may help others to understand Tlist and pass Types to them.

SuperStrict

Global CPUList:TList = New TList

Global C6502:CPU=New CPU

'' I do Not know how To Extends properly so used "Global flagReg:flagtype = New flagtype" to get it to work
'' Type C6502 Extends flagtype
'' Type CPU Extends flagtype   

Type CPU
            Field A:Int
            Field X:Int
            Field Y:Int
            Field Status:Int
            Field Tcycles:Int
            Field Instruction:String
            Field PC:Int

            Global flagReg:flagtype = New flagtype

End Type

Type flagtype
          
            Field Carry:Int
            Field Interrupt:Int
            Field Break:Int

End Type

' Just create some false Data

  C6502.status=255
  C6502.flagReg.Interrupt=True
  C6502.Instruction="Bmi()"

''  Print C6502.status
''  Print C6502.flagReg.Interrupt


' Main

PopulateList()
printCPUList()

End


Function PrintCPUList()

       Local ListLength:Int=CPUList.Count()
       Print "CPUstate="+ListLength

       Local CPUDebug:Object=CPUList.removelast()

       For Local i:Int=0 To ListLength

           ' Lets just examine the opcode and Interrupt
           Print "Opcode "+CPUDebug.instruction
           Print "Interrupt="+CPUDebug.flagReg.Interrupt

       Next

End Function


Function AddCPU_ToList(CPUObject:Object)

        CPUList.AddLast(CPUobject)
  
End Function

Function PopulateList()

     Local Num:Int=Rand(10)

     For Local i:Int=0 To Num

         AddCPU_ToList(C6502)
    
     Next

End Function

My Main problem is here!

Local CPUDebug:Object=CPUList.removelast()

       For Local i:Int=0 To ListLength

           ' Lets just examine the opcode and Interrupt
           Print "Opcode "+CPUDebug.instruction


Kind Regards Baggey
Running a PC that just Aint fast enough!? i7 4Ghz Quad core 24GB ram 1TB SSD and NVIDIA Quadro K620 . DID Technology stop! Or have we been assimulated!

ZX Spectrum 48k, C64, ORIC Atmos 48K, Enterprise 128K, The SID chip. Im Misunderstood!

Baggey

Okay ive managed to get at the CPU type data in the CPUlist by using eachin.

What i want to be able todo is go straight to the last item on the list and access the type there by using the .removelast() i think? 
or change some data in the list. Rather than iterrating through the objects in the list thats not that helpful at the moment :-\

Runable code in BlitzmaxNG

SuperStrict

Global CPUList:TList = New TList


Global C6502:CPU=New CPU

'' I do Not know how To Extends properly so used "Global flagReg:flagtype = New flagtype" to get it to work
'' Type C6502 Extends flagtype
'' Type CPU Extends flagtype   

Type CPU
            Field A:Int
            Field X:Int
            Field Y:Int
            Field Status:Int
            Field Tcycles:Int
            Field Instruction:String
            Field PC:Int

            Field flagReg:flagtype = New flagtype

End Type

Type flagtype
          
            Field Carry:Int
            Field Interrupt:Int
            Field Break:Int

End Type

' Main

PopulateList()
printCPUList()

End


Function PrintCPUList()

       Local ListLength:Int=CPUList.Count()
       Print "CPUstate="+ListLength
   
       For Local CurrentCPU:CPU = EachIn CPUList

           ' Lets just examine the opcode and Interrupt
           Print "Opcode "+CurrentCPU.instruction
           Print "Interrupt="+CurrentCPU.flagReg.Interrupt

       Next


End Function


Function PopulateList()

     Local Num:Int=Rand(10)

     For Local i:Int=0 To Num

         Local newCPU:CPU = New CPU

         newCPU.status=Rand(254)+1
         newCPU.flagReg.Interrupt=Rand(2)-1

         Local Op:Int=Rand(3)-1

         Select Op
           
             Case 0 newCPU.Instruction="Bmi()"
             Case 1 newCPU.Instruction="Nop"
             Case 2 newCPU.Instruction="Cli"

         End Select
        
         AddCPU_ToList(newCPU)
    
     Next

End Function


Function AddCPU_ToList(CPUObject:Object)

        CPUList.AddLast(CPUobject)
  
End Function
Running a PC that just Aint fast enough!? i7 4Ghz Quad core 24GB ram 1TB SSD and NVIDIA Quadro K620 . DID Technology stop! Or have we been assimulated!

ZX Spectrum 48k, C64, ORIC Atmos 48K, Enterprise 128K, The SID chip. Im Misunderstood!

Baggey

#2
So Someone put me out of my misery Please.

Ive passed a Type through an object on to the list and using eachin i can iterate the list and get my type back from the object.

But why cant i do the following? BlitzMax complains with "Unable to Convert from Object to CPU". But i can clearly go from "CPU to Object" :-\

Or is there another way of doing it? A work around so to speak? I just want to POP the last Type/Object from the list and use it or remove it.

I have thought of adding each bit of data to the list and then Poping all the data back but the beauty of Passing the CPU to the List and back seem like a sensible ask?

Function PrintCPUList()

       Local ListLength:Int=CPUList.Count()
       Print "CPUstate="+ListLength
   
       Local CurrentCPU:CPU = New CPU
             CurrentCPU = CPUList.removelast()

           ' Lets just examine the opcode and Interrupt
           Print "Opcode "+CurrentCPU.instruction
           Print "Interrupt="+CurrentCPU.flagReg.Interrupt

       'Next


End Function
Running a PC that just Aint fast enough!? i7 4Ghz Quad core 24GB ram 1TB SSD and NVIDIA Quadro K620 . DID Technology stop! Or have we been assimulated!

ZX Spectrum 48k, C64, ORIC Atmos 48K, Enterprise 128K, The SID chip. Im Misunderstood!

Midimaster

#3
You can of course do it with this 2-step workaround:

Local CurrentCpu:CPU = CpuList.last()
CpuList.RemoveLast()
Print "Opcode "+CurrentCPU.instruction
This first makes a copy of the object, then takes the object from the list away. Now it lives only outside the list as CurentCPU.


If you want to get directly the instance from the command CpuList.RemoveLast() it may be necessary to "cast" it:
'                    CASTING
'                       |
Local CurrentCpu:CPU = CPU ( CpuList.RemoveLast() )
'                     -----
Print "Opcode "+CurrentCPU.instruction
This does the same like the coe above, but the code is shorter.


But remember: CpuList.RemoveLast() does not only pick the object in a list. It also erase the list item!


Type and List

Normaly you would use lists for types like this:

Global C6502:CPU = CPU.Add()

CPU.PrintList()


Type CPU
    Global List:TList = New TList

    Field Instruction:String
    Field FlagReg:TFlag = New TFlag
    '...
   
    Function Add:CPU()
        Local loc:CPU = New CPU
        List.AddLast loc
        loc.Instruction       = "hallo"
        loc.FlagReg.Interrupt = 1
        Return loc
    End Function
   
   
    Function PrintList()
       For Local loc:CPU = EachIn List
            loc.Info
       Next
    End Function

   
    Method Info()
        Print "   Opcode=" + Instruction
        Print "Interrupt=" + FlagReg.Interrupt
    End Method

End Type


Type TFlag
    Field Interrupt:Int
    '...
End Type

The list is "inside" the type. The access to parameters of each CPU is done with Methods. So you do not need to repeat the word "CurrentCPU" all the time.

...back from Egypt

Baggey

Hey, Thanks for your reply the first example with the two lines of code still throws the same error!

However the second Works 8)

Local CurrentCpu:CPU = CPU(CpuList.last())
ironically you can see the "Type" Local being Type ie, Type CurrentCpu:CPU = CPU( "grab the list with all it's objects" ) Back into the type!

Ill have a look further at your other Suggestion's not having to Type CurrentCPU everytime i seem to remember VisualBasic does something like this!

QuoteBut remember: CpuList.RemoveLast() does not only pick the object in a list. It also erase the list item!

Is there away of selecting anyone of the fields within the list!? I mean lets say list item 2 had LDA #255 instruction. Could one go straight to that instruction in the list and pull the Tcycle time that it happend all the informations in the list for that instruction. Or even i suppose pull all the instances of that instruction ::)

Tlist's Seem to be a very useful Tool, especially being able to store anytype of data. As Nmi's and irq's happen im finding it necessary to keep track of all that was going on at that current moment in time. :-X

Kind Regards Baggey

Running a PC that just Aint fast enough!? i7 4Ghz Quad core 24GB ram 1TB SSD and NVIDIA Quadro K620 . DID Technology stop! Or have we been assimulated!

ZX Spectrum 48k, C64, ORIC Atmos 48K, Enterprise 128K, The SID chip. Im Misunderstood!

Midimaster

Quote....Is there away of selecting anyone of the fields within the list!? I mean lets say list item 2 had LDA #255 instruction. Could one go straight to that instruction in the list and pull the Tcycle time...
I'm not sure, that I understood what you want. but you can access Type fields directly in different ways. But therefore you would not necessarily need a list.

Global Item1:CPU = CPU.Add()
Global Item2:CPU = CPU.Add()
...
Print Item2.TCycles
Print Item1.Instruction
Type CPU
    ....
End Type
 


Or do you mean something like a search function? "If I search for Instruction LDA #255, what is it's Cycle time?"

CPU.Add("LDA #255", 18)

Print CPU.Find("LDA #255").Cycles

Type CPU
Global List:TList = New TList

Field Instruction:String
Field Cycles:Int

Function Add(Instruction:String, Cycles:Int)
Local loc:CPU = New CPU
loc.Instruction = Instruction
loc.Cycles      = Cycles
List.AddLast loc
End Function


Function Find:CPU(Instruction:String)
For Local loc:CPU = EachIn List
If loc.Instruction=Instruction
Return loc
EndIf
Next
Return Null
End Function

End Type
...back from Egypt

Baggey

Your Second idea of a search and find is more like i mean. But I think i should be using the words "Random access to the Tlist" and pop the Type i saved there!

So if i have 4 Objects in my list and item 3 was what i needed to Access. Then directly remove it! But i fear this is going to start getting complicated. :-X

For now being able to Access the Last ist good enough and remove the last just like an Stack Last on first off as my interrupts stack up.

Being able to random Access though would make the Tlist very useful indeed ::)

There is still much to learn with Blitzmax as i only thought you used methods within Types and you used a function!?
So I tried changing it to a Method!?  And it didnt work.
Method Add:CPU()
        Local loc:CPU = New CPU
        List.AddLast loc

 I dont quite understand why not though! :-[

Kind Regards Baggey
Running a PC that just Aint fast enough!? i7 4Ghz Quad core 24GB ram 1TB SSD and NVIDIA Quadro K620 . DID Technology stop! Or have we been assimulated!

ZX Spectrum 48k, C64, ORIC Atmos 48K, Enterprise 128K, The SID chip. Im Misunderstood!

Midimaster

#7
How can it be usefull to pick items in a list RANDOMLY? Normaly you pick a certain item: The last or the 5th or one, that fits to my search, ect...

If you already "found" your item and you already picked it once, you can access to it (also remove) whenever you want in the future:

global tempItem:CPU = CPU.Find(whatever)
...
'do some other thing
....
tempItem.Cycles=5
'do some other thing
....
CPU.List.Remove tempItem
...
tempItem.Cycles=15


Function versus Method

Read some OOP tuorials.

A Function() has access to the whole TYPE, included all instances and the list also. It is often used to scan the list and do things with several (more than one) instances (list members): Searching, Comparing, Calculation, etc

Type TTest
    Global List:TList
    Fields A,B,C

    Function PrintAll()
        For local loc:TTest =EachIn List
            loc.A = loc.A+10
    End Function
End Type


Look at the next two code boxes. It shows Function versus Method. They do exactly the same:

Type TTest
    Global List:TList
    Fields A,B,C

    Function PrintAll()
        For local loc:TTest = EachIn List
            print loc.A
            print loc.B
            print loc.C
    End Function
End Type

A Method() only works on a single instance. You needed to define the instance before, then afterwards you can access it with METHODs. A Method does not know other instances and cannot access them

Type TTest
    Global List:TList
    Fields A,B,C

    Function PrintAll()
        For local loc:TTest = EachIn List
            loc.PrintOne()
    End Function

    Method PrintOne()
            print A
            print B
            print C
    End Method

End Type

A List with free access to the members

If you search for a free acces to any instance in a list, you should not use a LIST but an ARRAY of Types

Type TTest
    Global ListArray:TTest[99]
    Fields A,B,C

    Function PrintPostion(Number:Int)
        ListArray[Number].PrintOne
    End Function

    Method PrintOne()
            print A
            print B
            print C
    End Method

End Type


There is something similar with real LISTs: List.ValueAtIndex(), but you need to know that List-Items can change their positions!

Type TTest
    Global List:TList
    Fields A,B,C

    Function PrintPostion(Number:Int)
        List.ValueAtIndex(Number).PrintOne
    End Function

    Method PrintOne()
            print A
            print B
            print C
    End Method

End Type
...back from Egypt

Derron

Maybe have a look at brl.objectlist -> useable like a TList but in its inner using an array, so you can have random accesses without the overhead of "valueAtIndex()"


bye
Ron

Baggey

I like the sound of using an Array of Types

Quote
QuoteIf you search for a free acces to any instance in a list, you should not use a LIST but an ARRAY of Types
Code Select Expand
Type TTest
    Global ListArray:TTest[99]
    Fields A,B,C
    Function PrintPostion(Number:Int)
        ListArray[Number].PrintOne
    End Function
    Method PrintOne()
            print A
            print B
            print C
    End Method
End Type

There is something similar with real LISTs: List.ValueAtIndex(), but you need to know that List-Items can change their positions!

I appreciate your time and effort but i cant get seem to get the above code to work at all. Is the code correct?

Kind Regards Baggey
Running a PC that just Aint fast enough!? i7 4Ghz Quad core 24GB ram 1TB SSD and NVIDIA Quadro K620 . DID Technology stop! Or have we been assimulated!

ZX Spectrum 48k, C64, ORIC Atmos 48K, Enterprise 128K, The SID chip. Im Misunderstood!

Midimaster

This is a runable example:

SuperStrict

For Local i:Int=0 To 9
TTest.Create(i)
Next

TTest.PrintPosition 4

Type TTest
    Global ListArray:TTest[99]
    Field A:Int, B:Int, C:Int

Function Create(Nr%)
Local loc:TTest= New TTest
loc.A = Nr
loc.B = Nr*Nr
loc.C = Nr*Nr*Nr

ListArray[Nr] = loc
End Function

    Function PrintPosition(Number:Int)
        ListArray[Number].PrintOne
    End Function

    Method PrintOne()
            Print A
            Print B
            Print C
    End Method

End Type
...back from Egypt

Baggey

Excellent Thanks for the Runable BlitzMaxNG Example. When your trying to get to grips with something you dont understand this is the only way to get something.

I modified the example of ListArray and have now worked out how to Extend my flags to the CPU and then Extend into My InterruptList which you called TTest

I have changed the create to AddToList. This all fits exactly to what im trying to achieve.

When an interrupt happens put them into a list so i can process them as in the emulation of the CPU real 8Bit they get Lost!

Here is Runable BlitzMaxNG code to ListArray and Type Not how the thread started but seems to tobe be the better approach! Thankyou Midimaster.
SuperStrict

For Local i:Int=0 To 99
InterruptList.AddToList(i)
Next

For Local i:Int=20 To 30
    Print
    InterruptList.PrintPosition i
Next

Type flagReg

    Field Interrupt:Int=Rnd(2)
    Field Carry:Int

End Type

Type CPU Extends flagreg

    Field Ticks:Int=Rand(24000)

End Type

Type InterruptList Extends Cpu

    Global ListArray:InterruptList[99]
    Field A:Int, B:Int, C:Int, Opcode:String, ArrayNum:Int
    'Field flag:FlagReg = New flagReg

Function AddToList(Nr:Int)
Local loc:InterruptList= New InterruptList
loc.A = Nr Shr 3 ' Divide by 8
loc.B = Nr Shl 2 ' Multiply by 4
loc.C = Nr Shl 3 ' Multiply by 8
loc.Opcode="Array Element="+Nr
loc.ArrayNum=Nr
loc.Interrupt=Rnd(2)

' Note Array wasnt ammended here so should always return "zero"!
' But when Element 29 will Force To 255 illegal cant happen!
If Nr=29 Then loc.Carry=255

ListArray[Nr] = loc
End Function

    Function PrintPosition(Number:Int)
        ListArray[Number].PrintOne
    End Function

    Method PrintOne()
            Print "Array["+ArrayNum+"]"
            Print Opcode
            Local Remainder:Int=(ArrayNum Mod 8)
            Print "( "+(ArrayNum Shr 3) +" * 8 ) + "+ Remainder + " = "+ArrayNum
            Print A
            Print B
            Print C
            Print "fINTERRUPT="+Interrupt
            Print "Cycles="+Ticks
            Print "fCARRY="+Carry
    End Method

End Type

Now, What i need todo is when i have code running in another .bmx file in another Type Reference back to the above code but AddToList and alter anything in the other types :-X

I havent tried yet but im hopping when i include the other .bmx files they'll become global!? I dont think you can pass a type into a Function then Manipulate inside that function or method ???

Kind Regards Baggey
Running a PC that just Aint fast enough!? i7 4Ghz Quad core 24GB ram 1TB SSD and NVIDIA Quadro K620 . DID Technology stop! Or have we been assimulated!

ZX Spectrum 48k, C64, ORIC Atmos 48K, Enterprise 128K, The SID chip. Im Misunderstood!

Midimaster

You can do with a TYPE whatever you can do with "normal" variable types like FLOAT. A TYPE is the same as any variable type. Remember  that it is also called "User defined variable". Play around and you will see what is possible.

You can send instances (list items) to any function. You also can call the functions of a TYPE from anywhere. You can also create a TYPE A inside TYPE B:


Here are some strange examples:
Type AType
    Global List:TList = New TList
    Field X:int

    Function Set()
        Print "Hello"
    End Function
End Type


Type BType
    '....

    Function GetBack:AType()
        local A:AType = New AType
        Return A
    End Function

    Function WhatTheFuck()
        Print AType.List.Count()
        ATyp.Set()
    End Function

End Type


Type CType
    Field Y:A_Type

    Function WhatEver()
        local loc:CType = New CType
        loc.Y = B_Type.GetBack()
        AType.List.AddLast loc.Y
    End Function
End Type


The function GetBack() return a instance of a AType, this is what you call "like GLOBAL"

The function WhatTheFuck() counts the list item in the AType List and calls a function inside AType

The type CType has a field Y where you can store ATYPEs

Function WhatEver() fills this field and adds the field to the AType List

The functions are without sense here, but show, what is possible

...back from Egypt

Baggey

Again thank you for your Help.

So you say
QuotePlay around and you will see what is possible.


Well, in the MaxIDE hovering over TYPE and pressing F1 we get help on Type's. We get.
Rem
Type marks the beginning of a BlitzMax custom type.
Standard BlitzMax types use a preceeding "T" naming
convention to differentiate themselves from standard
BlitzMax variable names.
End Rem
SuperStrict
Type TVector
    Field x:Int,y:Int,z:Int
End Type
Local a:TVector=New TVector
a.x=10
a.y=20
a.z=30

Our type is TVector and fields are used to declare the variables within the type!? So, Without the Line Local a:TVector=New TVector . We cant access anything inside the Type. Most other examples we see Use Mainly Method()s and sometimes Functions()

Now, In one of your Examples you send me. We have Atype
Type AType
    Global List:TList = New TList
    Field X:int
    Function Set()
        Print "Hello"
    End Function
End Type

You used Global List:TList = New TList. Now i try
Print Atype.List.count()I get 0 from the output window as expected, as nothing is in the list. So as im learning and only have examples to learn from.  Youve got me thinking outside the box! Ive just realised ive Accesed List:Tlist straight away!
Without having to use, say a:AType = New AType and then typing Print a.List.count() ::)

Now, The penny drops i cant access X with print Atype.X. But if i change the declaration to Global X:int and just use print Atype.X I it get access straight away! 8)

Anyone reading this might think this is very basic and laugh. Anyone Learning might think Oh yeah? But a learner would't necessary Think of do anything different!

Now, that i have furthered my learning with types and Tlist and using Arrays with types etc.

I now find myself asking when Declaring a Type. Why do we bother with Methods and fields At All!? :-X Because if we have Global variables and Functions inside the type we can access directly the type with just it's name.

I feel someone is going to shoot me down and point something unbekown out to me. Like Program size or Speed or something else? But if your learning and trying to get to grips with new concepts of coding with Blitzmax like me. You have to ask these questions!

If someone finds these insights helpful use them. If not ignore them!

Kind Regards Baggey
 
Running a PC that just Aint fast enough!? i7 4Ghz Quad core 24GB ram 1TB SSD and NVIDIA Quadro K620 . DID Technology stop! Or have we been assimulated!

ZX Spectrum 48k, C64, ORIC Atmos 48K, Enterprise 128K, The SID chip. Im Misunderstood!

Henri

Hi,

functions and globals are static, and are shared with all instances of a type (created only once). As such, functions cannot access fields directly.

Methods and fields are created everytime you use 'New' keyword, and each instance of a type has their own. This is usefull as each object you create can have its own atributes.

-Henri
- Got 01100011 problems, but the bit ain't 00000001