Page 1 of 1

Script Bytecode recurrence execution

Posted: Thu Feb 19, 2004 11:12 am
by BalrogSoft
Code updated for 5.20+

Hi, some people asked on this forums about creating an scripting language, and this is an example to manage variables, and execute internal instuctions, but this internal executions can be called itself, or can be call also other instructions, that can be difficult to implement for some newbies users.

This is the byte code script interpreter:

Code: Select all

; Recurrence execution of virtual code
; By Pedro Gil, Balrog Soft

Global *memAddress,IR,MakeJump,Quit,DontExecute
Global VariableNumber,VariableNumberByte,VariableNumberWord
Global VariableNumberLong,VariableNumberFloat,VariableNumberString
VariableNb=10000

Global Dim ValueReturn($FF)
Global Dim ValueParam($FF,20)
Global Dim VariableType.b(VariableNb)
Global Dim VariableTypeNumber.b(VariableNb)
Global Dim VariableStByte.b(VariableNb)                                  ; Type = 1
Global Dim VariableStWord.w(VariableNb)                                  ; Type = 2
Global Dim VariableStLong(VariableNb)                                    ; Type = 3
Global Dim VariableStFloat.f(VariableNb)                                 ; Type = 4
Global Dim VariableStString.s(VariableNb)                                ; Type = 5

Declare GetParams(Nb,IRAd,SPtr)

Procedure ExecuteVMInstruction(IRAdd,SP)
  PCAdd=0
  OpCode.b=PeekB(*memAddress+IRAdd)
  
  ;Define variable function
  If OpCode=$0
    If DontExecute=#False
      TotalVariableNumber+1
      VariableType.b=PeekB(*memAddress+IRAdd+1)
      VariableType(TotalVariableNumber)=VariableType
      If VariableType=1
        VarNb=VariableNumberByte
        VariableStByte(VarNb)=0
        VariableNumberByte+1
      ElseIf VariableType=2
        VarNb=VariableNumberWord
        VariableStWord(VarNb)=0
        VariableNumberWord+1
      ElseIf VariableType=3
        VarNb=VariableNumberLong
        VariableStLong(VarNb)=0
        VariableNumberLong+1
      ElseIf VariableType=4
        VarNb=VariableNumberFloat
        VariableStFloat(VarNb)=0
        VariableNumberFloat+1
      ElseIf VariableType=5
        VarNb=VariableNumberString
        VariableStString(VarNb)=""
        VariableNumberString+1
      EndIf
      VariableTypeNumber(TotalVariableNumber)=VarNb
    EndIf
    PCAdd=2
  EndIf
  
  ;Add function
  If OpCode=$1
    ParamBytes=GetParams(1,3+IRAdd,SP)
    If DontExecute=#False
      VariableNumberReturn=PeekW(*memAddress+IRAdd+1)
      VariableTypeReturn=VariableType(VariableNumberReturn)
      VariableInternalNumberReturn=VariableTypeNumber(VariableNumberReturn)
      returnvalue=ValueParam(SP,0)+ValueParam(SP,1)
      If SP=0
        If VariableNumberReturn<>0 And VariableTypeReturn=3
          VariableStLong(VariableInternalNumberReturn)=returnvalue
        EndIf
      Else
        ValueReturn(SP)=returnvalue
      EndIf
    EndIf
    PCAdd=3+ParamBytes
  EndIf
  
  ;Debug function
  If OpCode=$D
    If DontExecute=#False
      VariableNumber1=PeekW(*memAddress+IRAdd+1)
      VariableType1=VariableType(VariableNumber1)
      VariableInternalNumber1=VariableTypeNumber(VariableNumber1)
      If VariableType1=1
        Output.s=Str(VariableStByte(VariableInternalNumber1))
      ElseIf VariableType1=2
        Output.s=Str(VariableStWord(VariableInternalNumber1))
      ElseIf VariableType1=3
        Output.s=Str(VariableStLong(VariableInternalNumber1))
      ElseIf VariableType1=4
        Output.s=StrF(VariableStFloat(VariableInternalNumber1))
      ElseIf VariableType1=5
        Output.s=VariableStString(VariableInternalNumber1)
      EndIf
      MessageRequester("ScriptVM","V["+Str(VariableNumber1)+"] = "+Output.s,0)
    EndIf
    PCAdd=3
  EndIf
  
  ;End function
  If OpCode=$F
    If DontExecute=#False
      Quit=#True
    EndIf
    PCAdd=1
  EndIf
  ProcedureReturn PCAdd
EndProcedure

Procedure GetParams(Nb,IRAd,SPtr)
  ParamB=0
    For Param=0 To Nb
    ValueType1=PeekB(*memAddress+(ParamB)+IRAd)
    If ValueType1=1
      VariableNumber1=PeekW(*memAddress+(ParamB)+IRAd+1)
      VariableType1=VariableType(VariableNumber1)
      VariableInternalNumber1=VariableTypeNumber(VariableNumber1)
      If VariableType1=1
        ValueParam(SPtr,Param)=VariableStByte(VariableInternalNumber1)
      ElseIf VariableType1=2
        ValueParam(SPtr,Param)=VariableStWord(VariableInternalNumber1)
      ElseIf VariableType1=3
        ValueParam(SPtr,Param)=VariableStLong(VariableInternalNumber1)
      ElseIf VariableType1=4
        ValueParam(SPtr,Param)=VariableStFloat(VariableInternalNumber1)
      ElseIf VariableType1=5
        ValueParam(SPtr,Param)=@VariableStString(VariableInternalNumber1)
      EndIf
      ParamB+3
    ElseIf ValueType1=2
      ValueParam(SPtr,Param)=PeekL(*memAddress+(ParamB)+IRAd+1)
      ParamB+5
    ElseIf ValueType1=3
      ParamBAdd=ExecuteVMInstruction((ParamB)+IRAd+1,SPtr+1)
      Rtn=ValueReturn(SPtr+1)
      ValueParam(SPtr,Param)=Rtn
      ParamB+ParamBAdd+1
    EndIf
  Next Param
  ProcedureReturn ParamB
EndProcedure

PC=0
Filename.s= "test.svm"
Size=FileSize(Filename.s)

*memAddress = AllocateMemory(Size)

If OpenFile(0,Filename.s)
  ReadData(0,*memAddress,Size)
  CloseFile(0)
EndIf

Repeat
  If MakeJump=#False
    IR+PC
  ElseIf MakeJump=#True
    IR=PC
    MakeJump=#False
  EndIf
  PC=ExecuteVMInstruction(IR,0)
Until Quit=#True Or Error=#True
FreeMemory(*memAddress)
GetParams gets the value of parameters, and execute instructions if some parameter is a function.
ExecuteVMInstruction execute a instruction on a speficic IR(Instruction register, contains direction of actual execution opcode).
SP its stack pointer to difference the level of recurrence

How to use GetParams?
Nb is number of params, 0 counts for this, it means that if it have 2 parameters, Nb must be 1.
IRAd, its the internal address to where parameters can be founded.
SPtr, is stack pointer

An this is the program to make an example:

Code: Select all

If CreateFile(0,"test.svm")
  ;Define var01 as long
  WriteByte(0,$0)
  WriteByte(0,$3)
  
  ;add function: Add(var01,Add(3,5))
  WriteByte(0,$1)
  ;Return variable 01
  WriteWord(0,$1)
  ;Param1 is a variable
  WriteByte(0,$1)
  ;VarNb
  WriteWord(0,$1)
  ;Param2 is a function
  WriteByte(0,$3)
  ;Add function
  WriteByte(0,$1)
  ;return variable
  WriteWord(0,$0)
  ;Param1 is a direct value
  WriteByte(0,$2)
  ; Value 
  WriteLong(0,$3)
  ;Param2 is a direct value
  WriteByte(0,$2)
  ; Value
  WriteLong(0,$5)
  
  ;Debug var01
  WriteByte(0,$D)
  WriteWord(0,$1)
  
  ;End
  WriteByte(0,$F)
  
  CloseFile(0)
EndIf
The virtual code for this is:

Define Var01 as long

Var01=Add(Var01,Add(3,5))

Debug Var01

EndProgram

I know that can be a little complicated to understand, but if you have any question only send me an email.