Jump to content

Recommended Posts

1 hour ago, mizapf said:

Something like this from my recent SCSI emulation - I use it several times in each file.

 

line_state whtscsi_pld_device::scsi_cs()
{
    return (busen()
        && ((m_board->m_address & 0x0fe0)==0x0fe0)
        && (((m_board->m_address & 0x1000)!=0) == m_bank_swapped)
        && (((m_board->m_address & 1)==0) || m_word_transfer))? ASSERT_LINE : CLEAR_LINE;
}

I think idea was pioneered in LISP.  LISP - Cond Construct (tutorialspoint.com)

Does the C version generate better code than  if  else   ?  

  • Like 1

Share this post


Link to post
Share on other sites

Another good use for it is debugging output:

 

printf("Card is turned %s\n", m_selected? "on" : "off");

 

Can't live without it anymore. 🙂

  • Like 2

Share this post


Link to post
Share on other sites
21 hours ago, mizapf said:

Can't live without it anymore. 🙂

I use the ?: notation all the time, here is the implementation of SGN function in the Basic interpreter of the StrangeCart:

      case TOK_SGN:
        line++;
        expect(TOK_OPEN_PARENTHESIS);
        a = eval();
        expect(TOK_CLOSE_PARENTHESIS);
        return a < 0 ? -1 : (a ==0 ? 0 : 1);

I start to feel that I really need to add it to the Basic. Then for example factorials (the standard example of recursive functions) could be computed this way:

DEF FACT(N)= N>1 ? N*FACT(N-1) : 1

 

  • Like 2

Share this post


Link to post
Share on other sites
3 hours ago, speccery said:

I use the ?: notation all the time, here is the implementation of SGN function in the Basic interpreter of the StrangeCart:

      case TOK_SGN:
        line++;
        expect(TOK_OPEN_PARENTHESIS);
        a = eval();
        expect(TOK_CLOSE_PARENTHESIS);
        return a < 0 ? -1 : (a ==0 ? 0 : 1);

I start to feel that I really need to add it to the Basic. Then for example factorials (the standard example of recursive functions) could be computed this way:

DEF FACT(N)= N>1 ? N*FACT(N-1) : 1

 

I realize now that this is sometimes called the "Elvis" operator.  Think emoticon with hair   ?:-)   

 

So I am still curious is it just a syntax convenience or does it generate different code?

  • Haha 3

Share this post


Link to post
Share on other sites
1 hour ago, TheBF said:

I realize now that this is sometimes called the "Elvis" operator.  Think emoticon with hair   ?:-)   

 

So I am still curious is it just a syntax convenience or does it generate different code?

The intermediate code is similar, so it optimizes down the same way. If you think about the assembly language, there's not really too many ways to do "use A or B depending on C" ;)

 

I've had trouble using it with heavily overloaded templates in C++, though, it seems the preprocessor can get confused about the type of operation.

 

  • Like 4
  • Thanks 1

Share this post


Link to post
Share on other sites
6 hours ago, Tursi said:

The intermediate code is similar, so it optimizes down the same way. If you think about the assembly language, there's not really too many ways to do "use A or B depending on C" ;)

That's correct when you talk about compilers, but when talking about an interpreter, the speed is pretty much defined by how much fluff the interpreter has to work through. More compact expressions will mean more speed. In this specific example of recursive functions the interpreter can stay in expression evaluation code path, it does not need to proceed to the next line or something like that, so it should be faster. Of course a TI Basic function can call another function, which could recurse back to the first function, so you may need to change interpretation pointer location but you would not need to search for lines as you would if using GOTO for instance.

 

Having said that, I really want to make another version of the interpreter which would actually be a compiler. Probably not targeting ARM nor TMS9900 assembler in the first step, but instead some intermediate code. Need to try to stay focused on the interpreter first, painful as it is to see how much runtime processing it has to do validate stuff which a compiler only would do once. Maybe I need to split the interpreter into two passes first, do syntax checking first as the TI Basic is doing and then rely more on correctness when interpreting. But even then there a ton of stuff the interpreter needs to check when executing.

 

6 hours ago, Tursi said:

I've had trouble using it with heavily overloaded templates in C++, though, it seems the preprocessor can get confused about the type of operation.

As a small stupid comment regarding C++, my understanding is that templates are handled by the C++ compiler, not by the preprocessor. The type system is of course intimately involved when resolving templates, and I believe the type system is pretty much completely done within the compiler.

  • Like 2
  • Thanks 1

Share this post


Link to post
Share on other sites
13 hours ago, speccery said:

That's correct when you talk about compilers, but when talking about an interpreter, the speed is pretty much defined by how much fluff the interpreter has to work through.

Interpreters don't generate code, so that's not the question I was answering. :)

 

As a small stupid comment regarding C++, my understanding is that templates are handled by the C++ compiler, not by the preprocessor.

 

Yes, even I make mistakes. ;)

 

  • Like 1
  • Haha 1

Share this post


Link to post
Share on other sites

In the aftermath of last weekend's pandemic call @SteveB released code to his Basic game Rescuer.

That was interesting test material, as it uses BREAK statements in the code, as well as the VAL function. Testing it resulted in a few evenings worth of coding to get it running, as I was also in the process of adding DEF.

 

Supporting of BREAK is now added, as is VAL, although the implementation of VAL is still limited to numbers only, as that's what the game uses. I also added UNBREAK. Support of BREAK and UNBREAK needed the addition of an augment linenumber table, which is only partially in use, but once fully in use will speed up interpretation.

 

I added full support of DEF. This is actually somewhat hairy, since there are many different cases:

  • DEF PI=4*ATN(1) : no argument given
  • DEF SQ(X)=X*X : numeric argument numeric function
  • DEF N$(X$)=SEG$(X$,2,100) & SEG$(X$,1,1) : string argument and string function
  • DEF B$(X)=">"&STR$(X+21)&"<" : numeric argument and string result
  • DEF AK(A$)=POS(A$,"X",1) : string argument, numeric result

User defined functions are in my opinion a bit weird since they can refer to normal (global) variables too.

 

I think I still have a special case which does not work properly, since I implemented arguments so that the argument variable is temporarily defined and inserted into the front of the symbol search chain. Thus it will be found before global variables, but if the definition calls another function which is expecting to refer to a global variable, it will actually find the variable defined by the first function like so:

X=3   (global)

DEF F(Y)=Y*X

DEF G(X)=X+F(X)

PRINT G(2)

Here the print should give 2+2*3, but in my implementation it will give 2+2*2, since the function F(Y) will find G's X before the global X. I didn't test this, but that's the way it's written.

 

I have also added LET, which was trivial. The updated list of missing stuff is thus shorter:

  • GO and SUB (GOTO and GOSUB are there, but GO TO and GO SUB not yet, none of the existing programs I've tested use them)
  • CALL SOUND is decoded but sound is not working yet
  • DELETE (token 0x99) is not supported, and it does not need to supported by TI BASIC either?
  • OPEN, CLOSE, DISPLAY, EOF, REC, VARIABLE, RELATIVE, INTERNAL, SEQUENTIAL, OUTPUT UPDATE, APPEND, FIOXED, PERMANENT, # not done yet
  • VAL only supports numeric strings as arguments, the tokenizer is very limited at the moment
  • CALL KEY is only partially done, as is INPUT. CALL KEY currently only supports one of the scanning modes, and INPUT is really stupid in that it only waits for a single character :)
  • Like 3

Share this post


Link to post
Share on other sites
3 hours ago, speccery said:

In the aftermath of last weekend's pandemic call @SteveB released code to his Basic game Rescuer.

That was interesting test material, as it uses BREAK statements in the code, as well as the VAL function. Testing it resulted in a few evenings worth of coding to get it running, as I was also in the process of adding DEF.

 

Supporting of BREAK is now added, as is VAL, although the implementation of VAL is still limited to numbers only, as that's what the game uses. I also added UNBREAK. Support of BREAK and UNBREAK needed the addition of an augment linenumber table, which is only partially in use, but once fully in use will speed up interpretation.

 

I added full support of DEF. This is actually somewhat hairy, since there are many different cases:

  • DEF PI=4*ATN(1) : no argument given
  • DEF SQ(X)=X*X : numeric argument numeric function
  • DEF N$(X$)=SEG$(X$,2,100) & SEG$(X$,1,1) : string argument and string function
  • DEF B$(X)=">"&STR$(X+21)&"<" : numeric argument and string result
  • DEF AK(A$)=POS(A$,"X",1) : string argument, numeric result

User defined functions are in my opinion a bit weird since they can refer to normal (global) variables too.

 

I think I still have a special case which does not work properly, since I implemented arguments so that the argument variable is temporarily defined and inserted into the front of the symbol search chain. Thus it will be found before global variables, but if the definition calls another function which is expecting to refer to a global variable, it will actually find the variable defined by the first function like so:

X=3   (global)

DEF F(Y)=Y*X

DEF G(X)=X+F(X)

PRINT G(2)

Here the print should give 2+2*3, but in my implementation it will give 2+2*2, since the function F(Y) will find G's X before the global X. I didn't test this, but that's the way it's written.

 

I have also added LET, which was trivial. The updated list of missing stuff is thus shorter:

 

  • GO and SUB (GOTO and GOSUB are there, but GO TO and GO SUB not yet, none of the existing programs I've tested use them)
  • CALL SOUND is decoded but sound is not working yet
  • DELETE (token 0x99) is not supported, and it does not need to supported by TI BASIC either?
  • OPEN, CLOSE, DISPLAY, EOF, REC, VARIABLE, RELATIVE, INTERNAL, SEQUENTIAL, OUTPUT UPDATE, APPEND, FIOXED, PERMANENT, # not done yet
  • VAL only supports numeric strings as arguments, the tokenizer is very limited at the moment
  • CALL KEY is only partially done, as is INPUT. CALL KEY currently only supports one of the scanning modes, and INPUT is really stupid in that it only waits for a single character :)

Take a look at RXB CALL KEY routines they are similar to XB 3 or SXB but they do not have CALL ONKEY either.

CALL ONKEY is like ON KEY GOTO built into a single command.

Example: 200 CALL ONKEY("yYnN",5,K,S) GOTO 300,300,400,400 :: GOTO 200

If y or Y goto to 300, if n or N then goto 400, if no key pressed goto 200

CALL ONKEY is pass thru like normal CALL KEY in XB, but RXB has both pass thru or single key.

 

Example: 200 CALL KEY("0123456789",5,K,S)

Program will only advance if a number key is pressed.

 

RXB also has CALL JOYMOTION and JOYLOCATE that both are for JOYST MOTION or LOCATE built into your joystick actions.

  • Like 1

Share this post


Link to post
Share on other sites
4 hours ago, speccery said:

In the aftermath of last weekend's pandemic call @SteveB released code to his Basic game Rescuer.

That was interesting test material, as it uses BREAK statements in the code, as well as the VAL function. Testing it resulted in a few evenings worth of coding to get it running, as I was also in the process of adding DEF.

 

My 14 year old me is not available to be asked, why the hell he used BREAK back then. And twice! Pointing to a REM ... 

 

But my present me is glad that the program was of help for the Strange Cart Project.

 

Steve

  • Like 2

Share this post


Link to post
Share on other sites
32 minutes ago, SteveB said:

 

My 14 year old me is not available to be asked, why the hell he used BREAK back then. And twice! Pointing to a REM ... 

 

But my present me is glad that the program was of help for the Strange Cart Project.

 

Steve

I am looking forward to playing this game! I have added a new feature, CALL VSYNC a couple of weeks ago, which will allow me to slow down the game to a reasonable level when running on strangecart. Currently there’s just some flickering and the fuel runs out of in a matter of 10 seconds or something like that. 
 

I like the look of the game.  Impressive for TI Basic. it requires a joystick.  I don’t have one, or actually I just remembered that I have built a TI compatible thing with arcade buttons a few years ago, need to try with it. Before that need to check if CALL JOYST actually goes somewhere 🙂

  • Like 2

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...