Menu

FnLSL

jackjames
2025-04-17
2025-04-21
  • jackjames

    jackjames - 2025-04-17

    MyVar = FnLSL( 1, BitNum)is Equivalent toMyVar = 1<<BitNum

    But has this implementation been added to the new compiler? It gives me an error...
    I trying to transport a program that I had written in Mikrobasic on Gcbasic, but I find myself in difficulty on these instructions:
    ADDR = 0x80 OR ((Row-1) << 6) OR (Col-1)

     

    Last edit: jackjames 2025-04-17
  • Anobium

    Anobium - 2025-04-17

    See later post... resolved.

    'MyVar = FnLSL( 1, BitNum)' is equivalent to 'MyVar = 1<<BitNum'

    But, that is not equivalent to a complex calc such as 0x80 OR ((Row-1) << 6) OR (Col-1). The implementation in the compiler is the issue - the internal transformation is failing... as you can see!

    The workaround is to expand the operations.

    ADDR = Row-1
    ADDR = ADDR << 6
    ADDR = 0x80 OR ADDR OR ( Col - 1 )
    

    Once I have completed my current project I will investigate.

     

    Last edit: Anobium 2025-04-18
  • Anobium

    Anobium - 2025-04-18

    @JackJames

    Should be resolved in Build 1480. If you want to test - please email me. You know where....


    In Builds prior to 1480. You can see what is happening/broken by editing the USE.INI
    Edit USE.INI and change compilerdebug = 0 to compilerdebug = 512. This will show expansion of the shifts.

    So, for this test program.

    #SKIPTEST
    #CHIP 16f1939
    
    Dim BitNum as Byte
    Dim MyVar as Word
    
    // Works
    MyVar = FnLSL( 1, BitNum)
    MyVar = 1<<BitNum
    
    Dim Addr as Word
    Dim Row as Byte
    Dim Col as Byte
    
    ADDR = 0x80 OR ((Row - 1) << 6) OR (Col-1)
    

    You get, clearly the last entry ( 512 ExpandShifts Out:.. ) is incorrect. The expanded syntax is totally incorrect. The parentheses around Row - 1 are not been handled correctly... actually there is no implementation to handle parentheses in the expansion section of the compiler.

    512 ExpandShifts  In: MYVAR = 1<<BITNUM ;?F1L9S0I9?
    512 ExpandShifts Out: MYVAR= FnLSL(1,BITNUM)  ;?F1L9S0I9?
    
    512 ExpandShifts  In: ADDR = 128 | ((ROW - 1) << 6) | (COL-1) ;?F1L16S0I16?;STARTUP13
    512 ExpandShifts Out: ADDR=128 | ( ( ROW - 1  FnLSL(),6)  ) | ( COL-1 ) ;?F1L16S0I16?;STARTUP13
    

    Build 1480 handles correctly.

    512 ExpandShifts  In: MYVAR = 1<<BITNUM ;?F1L9S0I9?
    512 ExpandShifts Out: MYVAR= FnLSL(1,BITNUM)  ;?F1L9S0I9?
    
    512 ExpandShifts  In: ADDR = 128 | ((ROW - 1) << 6) | (COL-1) ;?F1L16S0I16?;STARTUP13
    512 ExpandShifts Out: ADDR=128 | ( FnLSL((ROW-1),6)  ) | ( COL-1 ) ;?F1L16S0I16?;STARTUP13
    

    This code is part of the GCBASIC compiler (written in FreeBASIC) that processes bitwise shift operations (<< for left shift and >> for right shift). Let me explain what it's doing:

    Overall Purpose

    The code parses source code that contains bitwise shift operations and transforms them into function calls (FnLSL for left shift and FnLSR for right shift). This is a common compiler technique where higher-level operations are converted to more primitive function calls.

    I'll expand on the three cases for handling shift operators in this code. The Case 1 and the parentheses maangement is what I have added in Build 1480.

    Process:

    Intial operation.
    
    1. The code identifies that the shift operator is followed by a opening parenthesis "("
    2. It needs to find the matching opening parenthesis ")" and capture everything in between
    3. It handles nested parentheses by counting opening and closing parentheses:
    - When it encounters a "(", it increments braceIndex
    - When it encounters a ")", it decrements braceIndex
    - It continues until all parentheses are balanced (braceIndex = 0)
    4. It reconstructs the entire expression inside the parentheses as shiftCalc and replaces the initial "(", removing all elements to the closing ")"
    

    Next Operation

    1. The code then identifies that the shift operator is preceded by a closing parenthesis ")"
    2. It needs to find the matching opening parenthesis "(" and capture everything in between
    3. It handles nested parentheses by counting opening and closing parentheses:
    - When it encounters a ")", it increments braceIndex
    - When it encounters a "(", it decrements braceIndex
    - It continues until all parentheses are balanced (braceIndex = 0)
    4. It reconstructs the entire expression inside the parentheses as shiftCalc
    5. It captures the number of bits to shift (the right operand) as NumBits
    6. It transforms the entire construction into a function call:
        - FnLSL(expression, bits) for left shifts (<<)
        - FnLSR(expression, bits) for right shifts (>>)
    
    Case 1: Parenthesized Expressions - (expression) << bits
    
    This is the most complex case, handling situations where the left operand of a shift operator is a parenthesized expression.
    
    Example Input: (x + 3) << 2
    
    Example Output: FnLSL(x + 3, 2)
    

    Else if
    Case 2: Constant Values - constant << constant

    This case handles shift operations where both operands are constant values that can be evaluated at compile time.
    
    Example Input: 4 << 2
    
    Process:
    1. The code checks that both the left and right operands are constants using IsConst()
    2. It concatenates the original expression leftOperand + operator + rightOperand
    3. It evaluates the result using the Calculate() function
    4. It replaces the shift operation with the calculated result
    5. It clears the original operands since they've been incorporated into the result
    
    Example Output: 16 (the precalculated result)
    

    Else

    Case 3: Standard Variable Shifting - variable << constant
    
    This is the most straightforward case, handling standard shift operations on variables.
    
    Example Input: myVar << 3
    
    Process:
    1. The code captures the left operand (the value to be shifted) as BitsIn
    2. It captures the right operand (the number of bits to shift) as NumBits
    3. It creates a function call based on the shift direction:
    - FnLSL(myVar, 3) for left shifts (<<)
    - FnLSR(myVar, 3) for right shifts (>>)
    4. It clears the original operands since they've been incorporated into the function call
    
    Example Output: FnLSL(myVar, 3)
    

    The purpose of all the transformations is to convert C-style shift operators (<< and >>) into function calls that the GCBASIC compiler can understand and process correctly.
    This enables developers to use familiar syntax while ensuring compatibility with the target compiler.

     

    Last edit: Anobium 2025-04-18
  • Anobium

    Anobium - 2025-04-18

    I am amazed that this now works.

    // Very complex... works
    ADDR = 0 + ( (Row - 1) << ( BitNum + 2 ) + 3) | 1 << Bitnum
    

    Verified as Good.

    512 ExpandShifts  In: ADDR = 0 + ( (ROW - 1) << ( BITNUM + 2 ) + 3) | 1 << BITNUM ;?F1L96S0I96?
    
    512 ExpandShifts Out: ADDR=0 + (      FnLSL((ROW-1),(BITNUM+2))      + 3 ) |  FnLSL(1,BITNUM)  ;?F1L96S0I96?
    
     
  • Anobium

    Anobium - 2025-04-19

    Just posted a review of this work to KO-FI

     
    • jackjames

      jackjames - 2025-04-21

      Congratulations!
      Great job, can't wait to try it.
      I'll be back in Rome in a few days and do a functional test.

       

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.