fbc-ng

General discussion for topics related to the FreeBASIC project or its community.
Post Reply
chrowle
Posts: 47
Joined: Oct 21, 2013 23:32
Location: Alberta, Canada

fbc-ng

Post by chrowle »

FreeBASIC Compiler next generation is a project that will add sound and other game dev functions to FreeBASIC.
chrowle
Posts: 47
Joined: Oct 21, 2013 23:32
Location: Alberta, Canada

Re: fbc-ng

Post by chrowle »

Having a bit of trouble... I have added a function to the source code(in rtl-gfx.bas). I compiled it all, and the function isn't working! How do I add a new keyword to FreeBASIC?
Roland Chastain
Posts: 1006
Joined: Nov 24, 2011 19:49
Location: France
Contact:

Re: fbc-ng

Post by Roland Chastain »

Hello !
chrowle wrote:FreeBASIC Compiler next generation is a project that will add sound and other game dev functions to FreeBASIC.
chrowle wrote:How do I add a new keyword to FreeBASIC?
It's a joke, isn't it ?
chrowle
Posts: 47
Joined: Oct 21, 2013 23:32
Location: Alberta, Canada

Re: fbc-ng

Post by chrowle »

No... Not a glorious moment..
AGS
Posts: 1284
Joined: Sep 25, 2007 0:26
Location: the Netherlands

Re: fbc-ng

Post by AGS »

chrowle wrote:FreeBASIC Compiler next generation is a project that will add sound and other game dev functions to FreeBASIC.
What other game dev functions do you have in mind? And if you want to add new commands to freebasic that
resemble functions that look like LINE, CIRCLE etc... then you'll have to add code in several places.

As an example of what should be done just take a look at
https://github.com/freebasic/fbc/blob/m ... rk-gfx.bas

You'll see something that looks like

Code: Select all

function cGfxStmt _
        ( _
                byval tk as FB_TOKEN _
        ) as integer

        function = FALSE

        select case as const tk
        case FB_TK_PSET
                CHECK_CODEMASK( )
                lexSkipToken( )
                function = cGfxPSet( FALSE )

        case FB_TK_PRESET
                CHECK_CODEMASK( )
                lexSkipToken( )
                function = cGfxPSet( TRUE )

        case FB_TK_LINE
                CHECK_CODEMASK( )
                lexSkipToken( )
                function = cGfxLine( )

        case FB_TK_CIRCLE
                CHECK_CODEMASK( )
                lexSkipToken( )
                function = cGfxCircle( )

        case FB_TK_PAINT
                CHECK_CODEMASK( )
                lexSkipToken( )
                function = cGfxPaint( )

        case FB_TK_DRAW
                CHECK_CODEMASK( )
                lexSkipToken( )
                function = cGfxDraw( )

        case FB_TK_VIEW
                CHECK_CODEMASK( )
                lexSkipToken( )
                function = cGfxView( TRUE )

        case FB_TK_WINDOW
                CHECK_CODEMASK( )
                lexSkipToken( )
                function = cGfxView( FALSE )

        case FB_TK_PALETTE
                CHECK_CODEMASK( )
                lexSkipToken( )
                function = cGfxPalette( )

        case FB_TK_PUT
                CHECK_CODEMASK( )
                lexSkipToken( )
                function = cGfxPut( )

        case FB_TK_GET
                CHECK_CODEMASK( )
                lexSkipToken( )
                function = cGfxGet( )

        case FB_TK_SCREEN
                CHECK_CODEMASK( )
                lexSkipToken( )
                function = cGfxScreen( FALSE )

        case FB_TK_SCREENQB
                CHECK_CODEMASK( )
                lexSkipToken( )
                function = cGfxScreen( TRUE )

        end select

end function
For every function called (for example cGfxView) there must be a function
that parses that particular command. In case of graphics those commands would be
PSET, LINE etc...

So first thing to do would be to come up with appropriate syntax for the
new commands you want to add.

If you want to add functions that implement the new sound commands
you have to add lines to
https://github.com/freebasic/fbc/blob/m ... ler/rtl.bi

At the top of that file you'll find
'' NOTE: when adding any RTL proc that will be called from rtl*.bas,
'' always update the FB_RTL_IDX enum below

Now for those keywords. Have a look at
https://github.com/freebasic/fbc/blob/m ... r/fbint.bi

You'll find an enum called FB_TOKEN. You'll have to add entries
for the commands you are going to add. It's mostly the first word of the command
that matters here but if your commands contain other words that should
be recognized as something other than an identifer they should be
added to the enum as well. Not updating the enum appropriately will lead
to parsing problems.

Next up is the file
https://github.com/freebasic/fbc/blob/m ... eyword.bas

There is a shared variable that reads

Code: Select all

dim shared kwdTb( 0 to FB_TOKENS-1 ) as SYMBKWD => _
You have to add the new keywords there using the enum entries you added
earlier.
I'll take one entry from kwdTB to show the kind of line you most likely want to add

Code: Select all

( @"CIRCLE"     , FB_TK_CIRCLE      , FB_TKCLASS_QUIRKWD ), _
For sound you could have a PLAY command

Code: Select all

( @"PLAY"     , FB_TK_PLAY      , FB_TKCLASS_QUIRKWD,KWD_OPTION_NO_QB ), _
I added KWD_OPTION_NO_QB as PLAY was not part of the original QB syntax.

For any command you want to add you have to
--> add a token to enum FB_TOKEN
--> add an entry to kwdTb
--> implement a parsing function

And you need to create parser-quirk-sound.bas. There you will put all the parsing
functions for the commands you want to add to FreeBASIC.
Each of those parsing functions will call a function that (ultimately) makes
sure the appropriate function call is added to the generated source code (be it
assembler, C or something else).

You should also create a file called rtl-sound.bas with a content similar to that of other
rtl-xxx.bas files (rtl-string.bas, rtl-math.bas being examples of what rtl-sound.bas
should contain).

Having done all of the above you have to write the functions associated with the
commands. And you have to add code to
https://github.com/freebasic/fbc/blob/m ... -quirk.bas

Add a case line for each new keyword to the case statement in cQuirkStmt

Code: Select all

function cQuirkStmt _
        ( _
                byval tk as FB_TOKEN = INVALID _
        ) as integer

        function = FALSE

        if( tk = INVALID ) then
                tk = lexGetToken( )

                select case lexGetClass( )
                case FB_TKCLASS_KEYWORD, FB_TKCLASS_QUIRKWD
                    '' QB mode?
                    if( env.clopt.lang = FB_LANG_QB ) then
                            if( lexGetType() <> FB_DATATYPE_INVALID ) then
                                    return FALSE
                            end if
                    end if

                case else
                        if( tk = CHAR_QUESTION ) then        '' PRINT as '?', can't be a keyword..
                                CHECK_CODEMASK( )
                                function = cPrintStmt( tk )
                        end if
                        exit function
                end select
        end if

        dim as integer res = FALSE

        select case as const tk
        case FB_TK_GOTO, FB_TK_GOSUB, FB_TK_RETURN, FB_TK_RESUME
                CHECK_CODEMASK( )
                res = cGotoStmt( tk )

        case FB_TK_PRINT, FB_TK_LPRINT
                CHECK_CODEMASK( )
                res = cPrintStmt( tk )

        case FB_TK_RESTORE, FB_TK_READ, FB_TK_DATA
                CHECK_CODEMASK( )
                res = cDataStmt( tk )

        case FB_TK_ERASE
                CHECK_CODEMASK( )
                res = cEraseStmt()

        case FB_TK_SWAP
                CHECK_CODEMASK( )
                res = cSwapStmt()

        case FB_TK_LINE
                CHECK_CODEMASK( )
                res = cLineInputStmt( )

        case FB_TK_INPUT
                CHECK_CODEMASK( )
                res = cInputStmt( )

        case FB_TK_POKE
                CHECK_CODEMASK( )
                res = cPokeStmt( )

        case FB_TK_OPEN, FB_TK_CLOSE, FB_TK_SEEK, FB_TK_PUT, FB_TK_GET, _
                 FB_TK_LOCK, FB_TK_UNLOCK, FB_TK_NAME
                CHECK_CODEMASK( )
                res = cFileStmt( tk )

        case FB_TK_ON
                CHECK_CODEMASK( )
                res = cOnStmt( )

        case FB_TK_WRITE
                CHECK_CODEMASK( )
                res = cWriteStmt()

        case FB_TK_ERROR
                CHECK_CODEMASK( )
                res = cErrorStmt()

        case FB_TK_ERR
                CHECK_CODEMASK( )
                res = cErrSetStmt()

        case FB_TK_VIEW
                CHECK_CODEMASK( )
                res = (cViewStmt(FALSE) <> NULL)

        case FB_TK_MID
                CHECK_CODEMASK( )
                res = cMidStmt( )

        case FB_TK_LSET, FB_TK_RSET
                CHECK_CODEMASK( )
                res = cLRSetStmt( tk )

        case FB_TK_WIDTH
                CHECK_CODEMASK( )
                res = cWidthStmt( FALSE ) <> NULL

        case FB_TK_COLOR
                CHECK_CODEMASK( )
                res = cColorStmt( FALSE ) <> NULL

        case FB_TK_REM
                '' due the QB quirks..
                if( env.clopt.lang = FB_LANG_QB ) then
                        res = cComment( )
                end if

        end select

        if( res = FALSE ) then
                res = cGfxStmt( tk )
        end if

        function = res

end function
If you want fb programmers to be able to use the new commands like
'regular' functions then you have to add a case for the new commands to

Code: Select all

function cQuirkFunction(byval sym as FBSYMBOL ptr) as ASTNODE ptr
        dim as ASTNODE ptr funcexpr = NULL
        dim as FB_TOKEN tk = sym->key.id

        select case as const tk
        case FB_TK_MKD, FB_TK_MKS, FB_TK_MKI, FB_TK_MKL, _
         FB_TK_MKSHORT, FB_TK_MKLONGINT
                funcexpr = cMKXFunct(tk)

        case FB_TK_CVD, FB_TK_CVS, FB_TK_CVI, FB_TK_CVL, _
         FB_TK_CVSHORT, FB_TK_CVLONGINT
                funcexpr = cCVXFunct(tk)

        case FB_TK_STR, FB_TK_WSTR, FB_TK_MID, FB_TK_STRING, FB_TK_WSTRING, _
         FB_TK_CHR, FB_TK_WCHR, _
         FB_TK_ASC, FB_TK_INSTR, FB_TK_INSTRREV, _
         FB_TK_TRIM, FB_TK_RTRIM, FB_TK_LTRIM, _
         FB_TK_LCASE, FB_TK_UCASE
                funcexpr = cStringFunct(tk)

        case FB_TK_ABS, FB_TK_SGN, FB_TK_FIX, FB_TK_FRAC, FB_TK_LEN, FB_TK_SIZEOF, _
                 FB_TK_SIN, FB_TK_ASIN, FB_TK_COS, FB_TK_ACOS, FB_TK_TAN, FB_TK_ATN, _
                 FB_TK_SQR, FB_TK_LOG, FB_TK_EXP, FB_TK_ATAN2, FB_TK_INT
                funcexpr = cMathFunct(tk, FALSE)

        case FB_TK_PEEK
                funcexpr = cPeekFunct()

        case FB_TK_LBOUND, FB_TK_UBOUND
                funcexpr = cArrayFunct(tk)

        case FB_TK_SEEK, FB_TK_INPUT, FB_TK_WINPUT, FB_TK_OPEN, FB_TK_CLOSE, _
         FB_TK_GET, FB_TK_PUT, FB_TK_NAME
                funcexpr = cFileFunct(tk)

        case FB_TK_ERR
                funcexpr = cErrorFunct()

        case FB_TK_IIF
                return cStrIdxOrMemberDeref( cIIFFunct( ) )

        case FB_TK_VA_FIRST
                funcexpr = cVAFunct()

        case FB_TK_CBYTE, FB_TK_CSHORT, FB_TK_CINT, FB_TK_CLNG, FB_TK_CLNGINT, _
         FB_TK_CUBYTE, FB_TK_CUSHORT, FB_TK_CUINT, FB_TK_CULNG, FB_TK_CULNGINT, _
         FB_TK_CSNG, FB_TK_CDBL, FB_TK_CSIGN, FB_TK_CUNSG
                return cTypeConvExpr( tk )

        case FB_TK_TYPE
                return cStrIdxOrMemberDeref( cAnonType( ) )

        case FB_TK_VIEW
                funcexpr = cViewStmt(TRUE)

        case FB_TK_WIDTH
                funcexpr = cWidthStmt( TRUE )

        case FB_TK_COLOR
                funcexpr = cColorStmt( TRUE )

        case FB_TK_SCREEN, FB_TK_SCREENQB
                funcexpr = cScreenFunct()

        case FB_TK_THREADCALL
                funcexpr = cThreadCallFunc()
        
        end select

        if( funcexpr = NULL ) then
                funcexpr = cGfxFunct( tk )
        end if

        function = funcexpr
end function
And so forth and so on. To make a long story short: to add new commands to
FreeBASIC you have to add a few lines of code to several existing files, create
some BASIC files and (of course) implement whatever the command should
'do'.

Above all your code has so fit into the runtime library framework as (informally)
defined by the developers. You have a bit of freedom here and there when it
comes to implementation but overall the framework used forces you to do things
in a certain manner. Divert to much from the framework and your extension to
the rtlib will not work.

Having written all of the above I personally do not think it is worthwhile
to try and add functions to the freebasic runtime library.
Chances are your code will not make it into the fb runtime library.

But don't let my scepticism keep you from hacking the fb source code.
If you are able to create a working version of the fbc that includes your
extended version of the runtime library then that would be quite something.
sean_vn
Posts: 283
Joined: Aug 06, 2012 8:26

Re: fbc-ng

Post by sean_vn »

It is the holographic (distributed) nature of the FreeBasic source code that prevents it being patched up to allow dynamic arrays in objects, isn't it?
marcov
Posts: 3462
Joined: Jun 16, 2005 9:45
Location: Netherlands
Contact:

Re: fbc-ng

Post by marcov »

sean_vn wrote:It is the holographic (distributed) nature of the FreeBasic source code that prevents it being patched up to allow dynamic arrays in objects, isn't it?
No, usually it is the freeing. Anything dynamic must have a strategy to free memory when it goes out of scope etc. Usually reliable freeing and resizing also needs a form of reliable initialization. (e.g. a refcount)

This initialization is used to distinguish within a random (pointer) value due not being initialized and an initialized pointer value that must be resized (or freed)
sean_vn
Posts: 283
Joined: Aug 06, 2012 8:26

Re: fbc-ng

Post by sean_vn »

Ok, that clarifies the situation.
sir_mud
Posts: 1401
Joined: Jul 29, 2006 3:00
Location: US
Contact:

Re: fbc-ng

Post by sir_mud »

chrowle wrote:FreeBASIC Compiler next generation is a project that will add sound and other game dev functions to FreeBASIC.
Have you taken a look at what we have done with the Extended Library project? We don't have a sound module yet, but there is a ton of graphical and other functions/classes that would be useful for game development (and general development). I have thought about building a sound module around the excellent BASS library, but I would much prefer something that is open source as a base.
chrowle
Posts: 47
Joined: Oct 21, 2013 23:32
Location: Alberta, Canada

Re: fbc-ng

Post by chrowle »

I would consider joining the project, if you made it support Linux.

EDIT: Never mind, seems to be compiling fine. How do I join?
sir_mud
Posts: 1401
Joined: Jul 29, 2006 3:00
Location: US
Contact:

Re: fbc-ng

Post by sir_mud »

chrowle wrote:I would consider joining the project, if you made it support Linux.

EDIT: Never mind, seems to be compiling fine. How do I join?
Join me on IRC http://ext.freebasic.net/page/support
Post Reply