News:

Let's find out together what makes a PIC Tick!

Main Menu

Need feature for Procedure!

Started by atomix, Mar 07, 2022, 09:50 AM

Previous topic - Next topic

atomix

Les you can make that when using the Gosub or Goto with procedures, the procedures are included in the output code.

Test(1, 2)   ' This includes a procedure on the output code.

Proc Test(v1 As FSR0L, v2 as PRODL)
EndProc

FSR0L = 0  :  PRODL = 0
... any code ...
Gosub Test   ' This not includes a procedure on the output code.
Goto  Test   ' This not includes a procedure on the output code.

Proc Test(v1 As FSR0L, v2 as PRODL)
EndProc

top204

#1
I can do it for Gosub, And using Goto for a procedure will work already, but the compiler will give a reminder to not use it. "*** Jumping to a procedure is not a standard mechanism and may cause problems if it is allowed to Return. Only perform the task if you know what is happening in your code! ***", because it will cause problems with users who do not understand the difference between a call and a Jump. However, I will be changing that to a "Warning", instead of a "Reminder".

The compiler already allows the Call command to call a procedure: Call MyProc(), but not as an assignment.

This is one of the reasons I made the parenthasis on a procedure call mandatory, so a user can immediately see that it is a procedure being called. i.e. DoSomething(). Some languages allow the parenthasis to be optional, and it can makes a code listing more complex to read.

atomix

Just in this code I would like to write like this:

If Lcd_Y = Lcd_Y2 Then Goto LCD_LineH_Calc

Gosub LCD_LineH

Instead of this:

If Lcd_Y = Lcd_Y2 Then LCD_LineH_Calc()  :  Return

LCD_LineH(Lcd_X, Lcd_Y, Lcd_X2)

Example code:

'----------------------------------------------------------------------------
Proc LCD_LineH_Calc()
Lcd_X2 = Lcd_X2 - Lcd_X  :  If Lcd_X2 < 0 Then Lcd_X2 = -Lcd_X2  :  Lcd_X = Lcd_X - Lcd_X2  :  Dec Lcd_X
Inc Lcd_X2
LCD_LineH(Lcd_X, Lcd_Y, Lcd_X2)
EndProc

'----------------------------------------------------------------------------
Proc LCD_LineH(X As Lcd_X, Y As Lcd_Y, W As Lcd_X2)
If Lcd_X2 = 0    Then Return
If LCD_OverflowY Then Return

$ifdef LCD_Opt_LineH
LCD_Opt_LineH
$else
Lcd_Y2 = Lcd_X
Repeat  ___  GoSub LCD_Pixel_X  :  Inc Lcd_X  :  Dec Lcd_X2  ___  Until Lcd_X2 = 0
Lcd_X = Lcd_Y2
$endif
EndProc


'----------------------------------------------------------------------------
Proc LCD_Line(X As Lcd_X, Y As Lcd_Y, X2 As Lcd_X2, Y2 As Lcd_Y2)
If Lcd_Y = Lcd_Y2 Then LCD_LineH_Calc()  :  Return ' draw horizontal line (fast)
If Lcd_X = Lcd_X2 Then LCD_LineV_Calc()  :  Return ' draw vertical   line (fast)

If Lcd_X > Lcd_X2 Then Swap Lcd_X, Lcd_X2  :  Swap Lcd_Y, Lcd_Y2 ' left to right draw

LCD_Pixel()

        ... other code ...
EndProc

atomix

Also good if it were possible to do this:

Proc OS__Yield_Timeout()
    GoSub OS__Task_Timeout_Me
!EndProc                          ' symbol ! - means not add Return in this place.
Proc OS__Yield_Stop()
    Task_Stop(OS_TaskID)
!EndProc
Proc OS__Yield_Next()
    OS_NextTask
!EndProc
Proc OS__Yield()
    TaskPtr_Addr(OS_TaskID)      TaskPtr_Write(TOSL)      Pop
EndProc

Instead of this:

OS__Yield_Timeout:
    GoSub OS__Task_Timeout_Me
OS__Yield_Stop:
    Task_Stop(OS_TaskID)
OS__Yield_Next:
    OS_NextTask
OS__Yield:
    TaskPtr_Addr(OS_TaskID)      TaskPtr_Write(TOSL)      Pop
Return

JohnB

Sounds like you are developing a Real Time OS.  Have you taken a look at PRTOS24 - its co-operative Real Time OS which I published some years ago.
It is now published with Positron Studio as a project.  Its complete with a demo program.
I haven't been able to test it recently because I don't have ISIS anymore since moving to a new PC.
JohnB

atomix

I wrote RTOS for PIC18 for more than a year ago.

Simple, small and fast.

top204

#6
Procedures will not always follow each other in the assembler listing in the same sequence as they are laid out in the BASIC listing. So automatically dropping from one procedure into another will not work.

As past experiences have shown, adding extras that can cause issues with a program's operation "will" cause problems over time, and it is always the compilers that get the blame. LOL

For a procedure type mechanism that has no return, you can use standard subroutines and wrap them in a preprocessor meta-macro, or inline within the meta-macro. They then look like a procedure call within the code listing, but you have control of what is inside them, and where they are within the listing.

With a lot of C coded Real Time OS code listings, you will find a lot of preprocessor meta-macros used, because functions are not allocated in sequence with that language either, and sometimes, their optimisers make functions disappear if the optimiser does not fully understand the semantics of the layout, and makes educated guesses. So meta-macros give an element of control over the language.

The compiler optimises the assembler code when it can, so if a Call is made to a subroutine, then immediataly after it a Return is found. It will remove the Return and make the Call into a Goto mnemonic, so the subroutine itself will perform the return.

top204

#7
As an example of the procedure mechanism I talked about in the above post. The program listing:

    TestProc1()
   
Proc TestProc2()
EndProc

Proc TestProc1()
    TestProc2()
EndProc

Produces the assembler code:

F1_000118 equ $ ; in [18FXXQ4X_TEST.BAS] TestProc1()
    rcall TestProc1
F1_000002 equ $ ; in [18FXXQ4X_TEST.BAS] Stop
_pblb__5
    bra _pblb__5
;---------------------------------------------
F1_000123 equ $ ; in [18FXXQ4X_TEST.BAS] Proc TestProc1()
TestProc1
F1_000124 equ $ ; in [18FXXQ4X_TEST.BAS] TestProc2()
    bra TestProc2
;---------------------------------------------
F1_000120 equ $ ; in [18FXXQ4X_TEST.BAS] Proc TestProc2()
TestProc2
F1_000121 equ $ ; in [18FXXQ4X_TEST.BAS] EndProc
    return 0 ; EndProc

Notice that, even though, TestProc2 was listed first in the program, the assembler has it after TestProc1. This is because it was called first in the BASIC listing.

Also notice, the Call TestProc2 has been changed to a Bra TestProc2, because the EndProc was seen as the Return, which it is. If the TestProc2 procedure was further away from the TestProc1 procedure, it would be Goto TestProc2, but the optimiser detected that it was within a relative jump distance, so changed it to save both time and flash memory space..

atomix

These nuances I knew, so I like your compiler.