AllBASIC

BASIC Developer & Support Resources => Interpreters => Topic started by: John on July 25, 2013, 12:03:49 AM

Title: MY-BASIC
Post by: John on July 25, 2013, 12:03:49 AM
I have compiled MY-BASIC for Windows (VS2008), Ubuntu 32/64 bit (gcc) and Android Linux (gcc). I view MY-BASIC as a SB-LITE like BASIC that is portable, extensible and embeddable. I modified it a bit and changed the ] prompt to be > with a space after it. I also took the startup info and made it part of the help screen. On startup of the shell, it displays MY-BASIC and the version number before dropping to the prompt. I optimized and stripped the Linux versions. The final executable sized range from 102 KB to 56 KB depending on the platform. The following is what MY-BASIC doesn't have that ScriptBasic does.


If all you're looking for is a simple to use embeddable BASIC, MY-BASIC is very well done and fast for being an interpreter. I see MY-BASIC as a great foundation for someone that wants to create there own BASIC but doesn't have the skills to start from scratch. MY-BASIC would be a good teaching tool for kids to learn BASIC programming.

Windows XP
(http://files.allbasic.info/my-basic/my-basic_win32.png)

Android Linux
(http://files.allbasic.info/my-basic/my-basic_android.png)

Ubuntu Linux
(http://files.allbasic.info/my-basic/my-basic_ubuntu64.png)


Title: Re: MY-BASIC
Post by: John on April 20, 2015, 08:41:30 AM
Hi Tony,

Just noticed your post on the BP.org site. I have been playing with your BASIC for a couple of years. I even have it running native on Android. I had posted the info I had here on All BASIC on BP.org but there seemed to be very little interest.

I'm not surprised as the Bitter BASIC Boys (and their toys) spend most of their time feeling miserable and pissed off their attempts at creating a BASIC of their own wasn't as easy as they anticipated. Their way to deal with it is to trash those that have made the commitment to do it right. Sad really.

John
Title: Re: MY-BASIC
Post by: John on April 20, 2015, 11:25:03 AM
I was able to compile the new release on Linux 64 bit.


jrs@laptop:~/mybasic/my_basic-master$ ./mybasic
MY-BASIC Interpreter Shell - 1.0.0050.
Copyright (C) 2011 - 2015 W. Renxin. All Rights Reserved.
For more information, see https://github.com/paladin-t/my_basic/.
Input HELP and hint enter to view help information.
]HELP
Commands:
  CLS   - Clear screen
  NEW   - Clear current program
  RUN   - Run current program
  BYE   - Quit interpreter
  LIST  - List current program
          Usage: LIST [l [n]], l is start line number, n is line count
  EDIT  - Edit a line in current program
          Usage: EDIT n, n is line number
  LOAD  - Load a file as current program
          Usage: LOAD *.*
  SAVE  - Save current program to a file
          Usage: SAVE *.*
  KILL  - Delete a file
          Usage: KILL *.*
]BYE
jrs@laptop:~/mybasic/my_basic-master$

Title: Re: MY-BASIC
Post by: John on April 20, 2015, 12:14:27 PM
Markus (Cybermonkey),

You must have been reading My_Mind. I have compiled MY-BASIC on all major platforms and wanted to create a Script BASIC extension module embedding My_Basic. It might make a nice addition to the TinyScheme and  Perl extension modules I did. The nice aspect of all three of the language extensions is they are interpretive and typeless. (like Script BASIC the host)

I'm slammed with a project at the moment but when I have some free time I'll take a shot of creating the Script BASIC MY-BASIC extension module using C BASIC.
Title: Re: MY-BASIC
Post by: John on April 20, 2015, 04:07:55 PM
I put together a quick extension module for MY-BASIC and seem to have a problem passing a string.  ???

interface.c
Code: C
  1. // MY-BASIC - Script BASIC extension module
  2.  
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <stdarg.h>
  7. #include <ctype.h>
  8. #include <math.h>
  9. #include <time.h>
  10. #include "../../basext.h"
  11. #include "cbasic.h"
  12.  
  13. #include "my_basic.h"
  14.  
  15.  
  16. /****************************
  17.  Extension Module Functions
  18. ****************************/
  19.  
  20. besVERSION_NEGOTIATE
  21.   RETURN_FUNCTION((int)INTERFACE_VERSION);
  22. besEND
  23.  
  24. besSUB_START
  25.   DIM AS long PTR p;
  26.   besMODULEPOINTER = besALLOC(sizeof(long));
  27.   IF (besMODULEPOINTER EQ NULL) THEN_DO RETURN_FUNCTION(0);
  28.   p = (long PTR)besMODULEPOINTER;
  29.   RETURN_FUNCTION(0);
  30. besEND
  31.  
  32. besSUB_FINISH
  33.   DIM AS long PTR p;
  34.   p = (long PTR)besMODULEPOINTER;
  35.   IF (p EQ NULL) THEN_DO RETURN_FUNCTION(0);
  36.   RETURN_FUNCTION(0);
  37. besEND
  38.  
  39.  
  40. /********************
  41.  MY-BASIC Functions
  42. ********************/
  43.  
  44. struct mb_interpreter_t* bas = 0;
  45.  
  46. besFUNCTION(mbas_init)
  47.   DIM AS int rtnval;
  48.   rtnval = mb_init();
  49.   besRETURN_LONG(rtnval);
  50. besEND
  51.  
  52. besFUNCTION(mbas_dispose)
  53.   DIM AS int rtnval;
  54.   rtnval = mb_dispose();
  55.   besRETURN_LONG(rtnval);
  56. besEND
  57.  
  58. besFUNCTION(mbas_open)
  59.   DIM AS int rtnval;
  60.   rtnval = mb_open(AT bas);
  61.   besRETURN_LONG(rtnval);
  62. besEND
  63.  
  64. besFUNCTION(mbas_close)
  65.   DIM AS int rtnval;
  66.   rtnval = mb_close(AT bas);
  67.   besRETURN_LONG(rtnval);
  68. besEND
  69.  
  70. besFUNCTION(mbas_load_str)
  71.   DIM AS const char PTR pgm;
  72.   DIM AS int rtnval;  
  73.   besARGUMENTS("z")
  74.     AT pgm
  75.   besARGEND
  76.   rtnval = mb_load_string(AT bas, pgm);
  77.   besRETURN_LONG(rtnval);
  78. besEND
  79.  
  80. besFUNCTION(mbas_run)
  81.   DIM AS int rtnval;
  82.   rtnval = mb_run(AT bas);
  83.   besRETURN_LONG(rtnval);
  84. besEND
  85.  

testmb.sb
Code: ScriptBasic
  1. DECLARE SUB mb_init ALIAS "mbas_init" LIB "mb"
  2. DECLARE SUB mb_dispose ALIAS "mbas_dispose" LIB "mb"
  3. DECLARE SUB mb_open ALIAS "mbas_open" LIB "mb"
  4. DECLARE SUB mb_close ALIAS "mbas_close" LIB "mb"
  5. DECLARE SUB mb_load_str ALIAS "mbas_load_str" LIB "mb"
  6. DECLARE SUB mb_run ALIAS "mbas_run" LIB "mb"
  7.  
  8. mb_init
  9. mb_open
  10. mb_load_str("10 PRINT \"Hello MY-BASIC\"")
  11. mb_run
  12. mb_close
  13. mb_dispose
  14.  

Output

jrs@laptop:~/sb/sb22/mybasic$ scriba testmb.sb
scriba: my_basic.c:3736: mb_load_string: Assertion `s && s->parsing_context' failed.
Aborted (core dumped)
jrs@laptop:~/sb/sb22/mybasic$

Title: Re: MY-BASIC
Post by: John on April 20, 2015, 04:35:49 PM
I thought I would change the interface.c so that the bas  (MY-BASIC execution object pointer) wasn't a global variable. I also added code to the testmb.sb script to make sure I was getting proper return values prior to the mb_load_str() call.

Code: C
  1. // MY-BASIC - Script BASIC extension module
  2.  
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <stdarg.h>
  7. #include <ctype.h>
  8. #include <math.h>
  9. #include <time.h>
  10. #include "../../basext.h"
  11. #include "cbasic.h"
  12.  
  13. #include "my_basic.h"
  14.  
  15.  
  16. /****************************
  17.  Extension Module Functions
  18. ****************************/
  19.  
  20. besVERSION_NEGOTIATE
  21.   RETURN_FUNCTION((int)INTERFACE_VERSION);
  22. besEND
  23.  
  24. besSUB_START
  25.   DIM AS long PTR p;
  26.   besMODULEPOINTER = besALLOC(sizeof(long));
  27.   IF (besMODULEPOINTER EQ NULL) THEN_DO RETURN_FUNCTION(0);
  28.   p = (long PTR)besMODULEPOINTER;
  29.   RETURN_FUNCTION(0);
  30. besEND
  31.  
  32. besSUB_FINISH
  33.   DIM AS long PTR p;
  34.   p = (long PTR)besMODULEPOINTER;
  35.   IF (p EQ NULL) THEN_DO RETURN_FUNCTION(0);
  36.   RETURN_FUNCTION(0);
  37. besEND
  38.  
  39.  
  40. /********************
  41.  MY-BASIC Functions
  42. ********************/
  43.  
  44. besFUNCTION(mbas_init)
  45.   DIM AS int rtnval;
  46.   rtnval = mb_init();
  47.   besRETURN_LONG(rtnval);
  48. besEND
  49.  
  50. besFUNCTION(mbas_dispose)
  51.   DIM AS int rtnval;
  52.   rtnval = mb_dispose();
  53.   besRETURN_LONG(rtnval);
  54. besEND
  55.  
  56. besFUNCTION(mbas_open)
  57.   DIM AS struct mb_interpreter_t* bas = 0;
  58.   DIM AS int rtnval;
  59.   rtnval = mb_open(AT bas);
  60.   besRETURN_LONG(rtnval);
  61. besEND
  62.  
  63. besFUNCTION(mbas_close)
  64.   DIM AS struct mb_interpreter_t* bas;
  65.   DIM AS int rtnval;
  66.   rtnval = mb_close(AT bas);
  67.   besRETURN_LONG(rtnval);
  68. besEND
  69.  
  70. besFUNCTION(mbas_load_str)
  71.   DIM AS struct mb_interpreter_t* bas;
  72.   DIM AS const char PTR pgm;
  73.   DIM AS int rtnval;  
  74.   besARGUMENTS("z")
  75.     AT pgm
  76.   besARGEND
  77.   rtnval = mb_load_string(AT bas, pgm);
  78.   besRETURN_LONG(rtnval);
  79. besEND
  80.  
  81. besFUNCTION(mbas_run)
  82.   DIM AS struct mb_interpreter_t* bas;
  83.   DIM AS int rtnval;
  84.   rtnval = mb_run(AT bas);
  85.   besRETURN_LONG(rtnval);
  86. besEND
  87.  

Code: ScriptBasic
  1. DECLARE SUB mb_init ALIAS "mbas_init" LIB "mb"
  2. DECLARE SUB mb_dispose ALIAS "mbas_dispose" LIB "mb"
  3. DECLARE SUB mb_open ALIAS "mbas_open" LIB "mb"
  4. DECLARE SUB mb_close ALIAS "mbas_close" LIB "mb"
  5. DECLARE SUB mb_load_str ALIAS "mbas_load_str" LIB "mb"
  6. DECLARE SUB mb_run ALIAS "mbas_run" LIB "mb"
  7.  
  8. CONST MB_FUNC_OK = 0
  9.  
  10. IF mb_init() = MB_FUNC_OK THEN PRINT "mb_init = OK\n"
  11. IF mb_open() = MB_FUNC_OK THEN PRINT "mb_open = OK\n"
  12. mb_load_str("10 PRINT \"Hello MY-BASIC\"")
  13. mb_run
  14. mb_close
  15. mb_dispose
  16.  


jrs@laptop:~/sb/sb22/mybasic$ scriba testmb.sb
mb_init = OK
mb_open = OK
scriba: my_basic.c:3736: mb_load_string: Assertion `s && s->parsing_context' failed.
Aborted (core dumped)
jrs@laptop:~/sb/sb22/mybasic$
Title: Re: MY-BASIC
Post by: AIR on April 20, 2015, 05:32:51 PM
Code: [Select]
struct mb_interpreter_t* bas = 0;
...
rtnval = mb_load_string(AT bas, pgm);

Code: [Select]
MBAPI int mb_load_string(mb_interpreter_t* s, const char* l);

Your call doesn't match the function declaration.
Title: Re: MY-BASIC
Post by: John on April 20, 2015, 05:35:33 PM
Code: Text
  1. jrs@laptop:~/mybasic/my_basic-master$ ./mybasic
  2. MY-BASIC Interpreter Shell - 1.0.0050.
  3. Copyright (C) 2011 - 2015 W. Renxin. All Rights Reserved.
  4. For more information, see https://github.com/paladin-t/my_basic/.
  5. Input HELP and hint enter to view help information.
  6. ]10 PRINT "Hello MY-BASIC"
  7. ]RUN
  8. Error:
  9.     [LINE] 1, [COL] 2,
  10.     [CODE] 44, [MESSAGE] Invalid expression, [ABORT CODE] 1003
  11.  
  12. ]
  13.  

I guess I forgot how to program in BASIC.  ???
Title: Re: MY-BASIC
Post by: John on April 20, 2015, 05:47:06 PM
My-BASIC can't print literal strings?  I'm still getting the same error with code that works in the standalone interpreter.

Code: Text
  1. ]NEW
  2. ]a$ = "Hello"
  3. ]PRINT a$
  4. ]RUN
  5. Hello
  6. ]BYE
  7.  

Code: ScriptBasic
  1. DECLARE SUB mb_init ALIAS "mbas_init" LIB "mb"
  2. DECLARE SUB mb_dispose ALIAS "mbas_dispose" LIB "mb"
  3. DECLARE SUB mb_open ALIAS "mbas_open" LIB "mb"
  4. DECLARE SUB mb_close ALIAS "mbas_close" LIB "mb"
  5. DECLARE SUB mb_load_str ALIAS "mbas_load_str" LIB "mb"
  6. DECLARE SUB mb_run ALIAS "mbas_run" LIB "mb"
  7.  
  8. CONST MB_FUNC_OK = 0
  9.  
  10. IF mb_init() = MB_FUNC_OK THEN PRINT "mb_init = OK\n"
  11. IF mb_open() = MB_FUNC_OK THEN PRINT "mb_open = OK\n"
  12. mb_code = """
  13. a$ = "Hello My-BASIC"
  14. PRINT a$
  15. """
  16. mb_load_str(mb_code)
  17. mb_run
  18. mb_close
  19. mb_dispose
  20.  


jrs@laptop:~/sb/sb22/mybasic$ scriba testmb.sb
mb_init = OK
mb_open = OK
scriba: my_basic.c:3736: mb_load_string: Assertion `s && s->parsing_context' failed.
Aborted (core dumped)
jrs@laptop:~/sb/sb22/mybasic$
Title: Re: MY-BASIC
Post by: John on April 20, 2015, 05:56:49 PM
I changed the function but it still gives the same error. I guess I don't understand what you mean.

Code: C
  1. besFUNCTION(mbas_load_str)
  2.   DIM AS struct mb_interpreter_t* bas;
  3.   DIM AS const char PTR pgm;
  4.   DIM AS int rtnval;  
  5.   besARGUMENTS("z")
  6.     AT pgm
  7.   besARGEND
  8.   rtnval = mb_load_string(AT bas, AT pgm);
  9.   besRETURN_LONG(rtnval);
  10. besEND
  11.  

Title: Re: MY-BASIC
Post by: AIR on April 20, 2015, 06:01:14 PM
That assertion error is thrown by this:

Code: [Select]
mb_assert(s && s->parsing_context);
Which means 's' is either wrong or is being _passed_ wrong.

Look more closely at what I posted above for the prototype, and look at how _you're_ passing the parameters.
Title: Re: MY-BASIC
Post by: John on April 20, 2015, 06:13:28 PM
I guess I don't get what is obvious to you.  :-\

I thought what you meant was ALL struct mb_interpreter_t* bas = 0; needed to initialized NULL (zero). It still gives the same error so I'm lost.

Code: C
  1. // MY-BASIC - Script BASIC extension module
  2.  
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <stdarg.h>
  7. #include <ctype.h>
  8. #include <math.h>
  9. #include <time.h>
  10. #include "../../basext.h"
  11. #include "cbasic.h"
  12.  
  13. #include "my_basic.h"
  14.  
  15.  
  16. /****************************
  17.  Extension Module Functions
  18. ****************************/
  19.  
  20. besVERSION_NEGOTIATE
  21.   RETURN_FUNCTION((int)INTERFACE_VERSION);
  22. besEND
  23.  
  24. besSUB_START
  25.   DIM AS long PTR p;
  26.   besMODULEPOINTER = besALLOC(sizeof(long));
  27.   IF (besMODULEPOINTER EQ NULL) THEN_DO RETURN_FUNCTION(0);
  28.   p = (long PTR)besMODULEPOINTER;
  29.   RETURN_FUNCTION(0);
  30. besEND
  31.  
  32. besSUB_FINISH
  33.   DIM AS long PTR p;
  34.   p = (long PTR)besMODULEPOINTER;
  35.   IF (p EQ NULL) THEN_DO RETURN_FUNCTION(0);
  36.   RETURN_FUNCTION(0);
  37. besEND
  38.  
  39.  
  40. /********************
  41.  MY-BASIC Functions
  42. ********************/
  43.  
  44. besFUNCTION(mbas_init)
  45.   DIM AS int rtnval;
  46.   rtnval = mb_init();
  47.   besRETURN_LONG(rtnval);
  48. besEND
  49.  
  50. besFUNCTION(mbas_dispose)
  51.   DIM AS int rtnval;
  52.   rtnval = mb_dispose();
  53.   besRETURN_LONG(rtnval);
  54. besEND
  55.  
  56. besFUNCTION(mbas_open)
  57.   DIM AS struct mb_interpreter_t* bas = 0;
  58.   DIM AS int rtnval;
  59.   rtnval = mb_open(AT bas);
  60.   besRETURN_LONG(rtnval);
  61. besEND
  62.  
  63. besFUNCTION(mbas_close)
  64.   DIM AS struct mb_interpreter_t* bas = 0;
  65.   DIM AS int rtnval;
  66.   rtnval = mb_close(AT bas);
  67.   besRETURN_LONG(rtnval);
  68. besEND
  69.  
  70. besFUNCTION(mbas_load_str)
  71.   DIM AS struct mb_interpreter_t* bas = 0;
  72.   DIM AS const char PTR pgm;
  73.   DIM AS int rtnval;  
  74.   besARGUMENTS("z")
  75.     AT pgm
  76.   besARGEND
  77.   rtnval = mb_load_string(AT bas, pgm);
  78.   besRETURN_LONG(rtnval);
  79. besEND
  80.  
  81. besFUNCTION(mbas_run)
  82.   DIM AS struct mb_interpreter_t* bas = 0;
  83.   DIM AS int rtnval;
  84.   rtnval = mb_run(AT bas);
  85.   besRETURN_LONG(rtnval);
  86. besEND
  87.  

Since this works, I'm assuming the AT bas is correct.

Code: C
  1. besFUNCTION(mbas_open)
  2.   DIM AS struct mb_interpreter_t* bas = 0;
  3.   DIM AS int rtnval;
  4.   rtnval = mb_open(AT bas);
  5.   besRETURN_LONG(rtnval);
  6. besEND
  7.  

Can you give a clue I might understand?
Title: Re: MY-BASIC
Post by: John on April 20, 2015, 06:29:46 PM
I was wrong. Just don't use line numbers. (Paul Dunn  :P )

Code: [Select]
jrs@laptop:~/mybasic/my_basic-master$ ./mybasic
MY-BASIC Interpreter Shell - 1.0.0050.
Copyright (C) 2011 - 2015 W. Renxin. All Rights Reserved.
For more information, see https://github.com/paladin-t/my_basic/.
Input HELP and hint enter to view help information.
]PRINT "HellO"
]RUN
HellO
]
Title: Re: MY-BASIC
Post by: AIR on April 20, 2015, 06:31:33 PM
Again, look at the function DECLARATION. Ask yourself what "mb_interpreter_t* s" is.

Then compare it to what you are passing to the function. It's not what the function requires.

That is what the assert is trying to tell you.
Title: Re: MY-BASIC
Post by: John on April 20, 2015, 06:48:15 PM
Here are the command lines I'm using to compile the module.

gcc -O2 -w -m64 -fPIC -c my_basic.c -lm -o my_basic.o
gcc -O2 -w -m64 -fPIC -c interface.c -lm -o interface.o
ld -shared -fPIC interface.o my_basic.o -lm -o mb.so



This is the example I used from the MY-BASIC docs. (PDF)

Code: C
  1. struct mb_interpreter_t* bas = 0;
  2. mb_open(&bas);
  3.  

The mb_open() function works in my code so I must be handling call correctly. IMHO

I'm totally clueless about the point you're trying to make.

Title: Re: MY-BASIC
Post by: AIR on April 20, 2015, 07:29:37 PM
struct mb_interpreter_t* bas = 0;

Creates a pointer to a mb_interpreter struct.  Intialized to 0.

MBAPI int mb_load_string(mb_interpreter_t* s, const char* l);

The signature/declaration of the function you're trying to call.  ALL OTHER FUNCTIONS ARE IRRELEVANT, THIS IS THE ONE GIVING YOU THE PROBLEM.


rtnval = mb_load_string(AT bas, pgm);

THIS IS HOW YOU ARE CALLING THE FUNCTION.

"AT bas" translates to "&bas".  So you are NOT passing an mb_interpreter POINTER to the function, you are essentially passing the first FIELD of the struct.

mb_assert(s && s->parsing_context); is telling you that the parameter you passed is INVALID.  BECAUSE it's NOT a Pointer to an mb_interpreter_t structure.

I leave it to you to fix now.
Title: Re: MY-BASIC
Post by: John on April 20, 2015, 07:52:18 PM
I changed the code based on what I think you are saying. Okay, I give up and have to finish the project I'm working on to feed me. Can you just tell me where I'm screwing up and I'll remember it for next time.

Quote from: Tony
3. String pushing. Pelase git a updated revision and use 'mb_memdup' to generate a MY-BASIC managable string before pushing, you can find more information about this API in the ref doc pdf or search for it in https://github.com/paladin-t/my_basic/wiki/File-module for a demo usage.

Code: C
  1. static int _file_open(struct mb_interpreter_t* s, void** l) {
  2.     int result = MB_FUNC_OK;
  3.     FILE* fp = 0;
  4.     char* fn = 0;
  5.     char* fm = 0;
  6.  
  7.     mb_assert(s && l);
  8.  
  9.     mb_check(mb_attempt_open_bracket(s, l));
  10.  
  11.     mb_check(mb_pop_string(s, l, &fn));
  12.  
  13.     mb_check(mb_pop_string(s, l, &fm));
  14.  
  15.     mb_check(mb_attempt_close_bracket(s, l));
  16.  
  17. ....
  18.  

Code: C
  1. // MY-BASIC - Script BASIC extension module
  2.  
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <stdarg.h>
  7. #include <ctype.h>
  8. #include <math.h>
  9. #include <time.h>
  10. #include "../../basext.h"
  11. #include "cbasic.h"
  12.  
  13. #include "my_basic.h"
  14.  
  15.  
  16. /****************************
  17.  Extension Module Functions
  18. ****************************/
  19.  
  20. besVERSION_NEGOTIATE
  21.   RETURN_FUNCTION((int)INTERFACE_VERSION);
  22. besEND
  23.  
  24. besSUB_START
  25.   DIM AS long PTR p;
  26.   besMODULEPOINTER = besALLOC(sizeof(long));
  27.   IF (besMODULEPOINTER EQ NULL) THEN_DO RETURN_FUNCTION(0);
  28.   p = (long PTR)besMODULEPOINTER;
  29.   RETURN_FUNCTION(0);
  30. besEND
  31.  
  32. besSUB_FINISH
  33.   DIM AS long PTR p;
  34.   p = (long PTR)besMODULEPOINTER;
  35.   IF (p EQ NULL) THEN_DO RETURN_FUNCTION(0);
  36.   RETURN_FUNCTION(0);
  37. besEND
  38.  
  39.  
  40. /********************
  41.  MY-BASIC Functions
  42. ********************/
  43.  
  44. besFUNCTION(mbas_init)
  45.   DIM AS int rtnval;
  46.   rtnval = mb_init();
  47.   besRETURN_LONG(rtnval);
  48. besEND
  49.  
  50. besFUNCTION(mbas_dispose)
  51.   DIM AS int rtnval;
  52.   rtnval = mb_dispose();
  53.   besRETURN_LONG(rtnval);
  54. besEND
  55.  
  56. besFUNCTION(mbas_open)
  57.   DIM AS struct mb_interpreter_t* bas = 0;
  58.   DIM AS int rtnval;
  59.   rtnval = mb_open(AT bas);
  60.   besRETURN_LONG(rtnval);
  61. besEND
  62.  
  63. besFUNCTION(mbas_close)
  64.   DIM AS struct mb_interpreter_t* bas;
  65.   DIM AS int rtnval;
  66.   rtnval = mb_close(bas);
  67.   besRETURN_LONG(rtnval);
  68. besEND
  69.  
  70. besFUNCTION(mbas_load_str)
  71.   DIM AS struct mb_interpreter_t* bas;
  72.   DIM AS const char PTR pgm;
  73.   DIM AS int rtnval;  
  74.   besARGUMENTS("z")
  75.     AT pgm
  76.   besARGEND
  77.   rtnval = mb_load_string(bas, pgm);
  78.   besRETURN_LONG(rtnval);
  79. besEND
  80.  
  81. besFUNCTION(mbas_run)
  82.   DIM AS struct mb_interpreter_t* bas;
  83.   DIM AS int rtnval;
  84.   rtnval = mb_run(bas);
  85.   besRETURN_LONG(rtnval);
  86. besEND
  87.  


jrs@laptop:~/sb/sb22/mybasic$ scriba testmb.sb
mb_init = OK
mb_open = OK
scriba: my_basic.c:3736: mb_load_string: Assertion `s && s->parsing_context' failed.
Aborted (core dumped)
jrs@laptop:~/sb/sb22/mybasic$

 
Title: Re: MY-BASIC
Post by: John on April 20, 2015, 08:29:25 PM
I think the issue is that the string needs to be pushed to the structure before use.

Code: C
  1. int mb_push_string(struct mb_interpreter_t* s, void** l, char* val);
  2.  

Quote
This function pushes an argument of char* to an interpreter structure.
Title: Re: MY-BASIC
Post by: wangrenxin on April 20, 2015, 08:29:46 PM
Hi all,

Glad to join here!

There are a lot of magic macros, where can I get header files including definitions of the macros?

WRX.
Title: Re: MY-BASIC
Post by: John on April 20, 2015, 08:33:42 PM
Welcome Tony!

Attached is the C BASIC (cbasic.h #define's). Thanks for having a peek.

The Script BASIC extension API is defined in basext.h.
Title: Re: MY-BASIC
Post by: AIR on April 20, 2015, 08:52:31 PM
Code: [Select]
#include "my_basic.c"

static struct mb_interpreter_t* bas = 0;

int main (int argc, char** argv) {
int retval;

mb_open(&bas);

retval = mb_load_string(bas,"print \"Hello, World!\n\"");

retval = mb_run(bas);


return retval;
}

Edit:  This is on my Mac.  Outputs "Hello, World!" as expected.
Title: Re: MY-BASIC
Post by: John on April 20, 2015, 09:03:03 PM
Thanks AIR!

That is helpful. I thought mb_init() was the first call before any others were made. It doesn't seem to be needed in your example.
Title: Re: MY-BASIC
Post by: John on April 20, 2015, 09:10:40 PM
Still no luck but now I'm getting a segmentation fault rather than a parse error.

Code: C
  1. // MY-BASIC - Script BASIC extension module
  2.  
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <stdarg.h>
  7. #include <ctype.h>
  8. #include <math.h>
  9. #include <time.h>
  10. #include "../../basext.h"
  11. #include "cbasic.h"
  12.  
  13. #include "my_basic.h"
  14.  
  15.  
  16. /****************************
  17.  Extension Module Functions
  18. ****************************/
  19.  
  20. besVERSION_NEGOTIATE
  21.   RETURN_FUNCTION((int)INTERFACE_VERSION);
  22. besEND
  23.  
  24. besSUB_START
  25.   DIM AS long PTR p;
  26.   besMODULEPOINTER = besALLOC(sizeof(long));
  27.   IF (besMODULEPOINTER EQ NULL) THEN_DO RETURN_FUNCTION(0);
  28.   p = (long PTR)besMODULEPOINTER;
  29.   RETURN_FUNCTION(0);
  30. besEND
  31.  
  32. besSUB_FINISH
  33.   DIM AS long PTR p;
  34.   p = (long PTR)besMODULEPOINTER;
  35.   IF (p EQ NULL) THEN_DO RETURN_FUNCTION(0);
  36.   RETURN_FUNCTION(0);
  37. besEND
  38.  
  39.  
  40. /********************
  41.  MY-BASIC Functions
  42. ********************/
  43.  
  44. static struct mb_interpreter_t* bas = 0;
  45.  
  46. besFUNCTION(mbas_init)
  47.   DIM AS int rtnval;
  48.   rtnval = mb_init();
  49.   besRETURN_LONG(rtnval);
  50. besEND
  51.  
  52. besFUNCTION(mbas_dispose)
  53.   DIM AS int rtnval;
  54.   rtnval = mb_dispose();
  55.   besRETURN_LONG(rtnval);
  56. besEND
  57.  
  58. besFUNCTION(mbas_open)
  59.   DIM AS int rtnval;
  60.   rtnval = mb_open(AT bas);
  61.   besRETURN_LONG(rtnval);
  62. besEND
  63.  
  64. besFUNCTION(mbas_close)
  65.   DIM AS int rtnval;
  66.   rtnval = mb_close(bas);
  67.   besRETURN_LONG(rtnval);
  68. besEND
  69.  
  70. besFUNCTION(mbas_load_str)
  71.   DIM AS const char PTR pgm;
  72.   DIM AS int rtnval;  
  73.   besARGUMENTS("z")
  74.     AT pgm
  75.   besARGEND
  76.   rtnval = mb_load_string(bas, pgm);
  77.   besRETURN_LONG(rtnval);
  78. besEND
  79.  
  80. besFUNCTION(mbas_run)
  81.   DIM AS int rtnval;
  82.   rtnval = mb_run(bas);
  83.   besRETURN_LONG(rtnval);
  84. besEND
  85.  

Code: ScriptBasic
  1. DECLARE SUB mb_init ALIAS "mbas_init" LIB "mb"
  2. DECLARE SUB mb_dispose ALIAS "mbas_dispose" LIB "mb"
  3. DECLARE SUB mb_open ALIAS "mbas_open" LIB "mb"
  4. DECLARE SUB mb_close ALIAS "mbas_close" LIB "mb"
  5. DECLARE SUB mb_load_str ALIAS "mbas_load_str" LIB "mb"
  6. DECLARE SUB mb_run ALIAS "mbas_run" LIB "mb"
  7.  
  8. CONST MB_FUNC_OK = 0
  9.  
  10. ' IF mb_init() = MB_FUNC_OK THEN PRINT "mb_init = OK\n"
  11. IF mb_open() = MB_FUNC_OK THEN PRINT "mb_open = OK\n"
  12. mb_code = "PRINT \"Hello\"\n"
  13. mb_load_str(mb_code)
  14. mb_run
  15. mb_close
  16. mb_dispose
  17.  


jrs@laptop:~/sb/sb22/mybasic$ scriba testmb.sb
mb_open = OK
Segmentation fault (core dumped)
jrs@laptop:~/sb/sb22/mybasic$

Title: Re: MY-BASIC
Post by: John on April 20, 2015, 09:27:24 PM
It works!  Thanks AIR for your help tonight!

Code: C
  1. // MY-BASIC - Script BASIC extension module
  2.  
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <stdarg.h>
  7. #include <ctype.h>
  8. #include <math.h>
  9. #include <time.h>
  10. #include "../../basext.h"
  11. #include "cbasic.h"
  12.  
  13. #include "my_basic.h"
  14.  
  15.  
  16. /****************************
  17.  Extension Module Functions
  18. ****************************/
  19.  
  20. besVERSION_NEGOTIATE
  21.   RETURN_FUNCTION((int)INTERFACE_VERSION);
  22. besEND
  23.  
  24. besSUB_START
  25.   DIM AS long PTR p;
  26.   besMODULEPOINTER = besALLOC(sizeof(long));
  27.   IF (besMODULEPOINTER EQ NULL) THEN_DO RETURN_FUNCTION(0);
  28.   p = (long PTR)besMODULEPOINTER;
  29.   RETURN_FUNCTION(0);
  30. besEND
  31.  
  32. besSUB_FINISH
  33.   DIM AS long PTR p;
  34.   p = (long PTR)besMODULEPOINTER;
  35.   IF (p EQ NULL) THEN_DO RETURN_FUNCTION(0);
  36.   RETURN_FUNCTION(0);
  37. besEND
  38.  
  39.  
  40. /********************
  41.  MY-BASIC Functions
  42. ********************/
  43.  
  44. static struct mb_interpreter_t* bas = 0;
  45.  
  46. besFUNCTION(mbas_init)
  47.   DIM AS int rtnval;
  48.   rtnval = mb_init();
  49.   besRETURN_LONG(rtnval);
  50. besEND
  51.  
  52. besFUNCTION(mbas_dispose)
  53.   DIM AS int rtnval;
  54.   rtnval = mb_dispose();
  55.   besRETURN_LONG(rtnval);
  56. besEND
  57.  
  58. besFUNCTION(mbas_open)
  59.   DIM AS int rtnval;
  60.   rtnval = mb_open(AT bas);
  61.   besRETURN_LONG(rtnval);
  62. besEND
  63.  
  64. besFUNCTION(mbas_close)
  65.   DIM AS int rtnval;
  66.   rtnval = mb_close(AT bas);
  67.   besRETURN_LONG(rtnval);
  68. besEND
  69.  
  70. besFUNCTION(mbas_load_str)
  71.   DIM AS const char PTR pgm;
  72.   DIM AS int rtnval;  
  73.   besARGUMENTS("z")
  74.     AT pgm
  75.   besARGEND
  76.   rtnval = mb_load_string(bas, pgm);
  77.   besRETURN_LONG(rtnval);
  78. besEND
  79.  
  80. besFUNCTION(mbas_run)
  81.   DIM AS int rtnval;
  82.   rtnval = mb_run(bas);
  83.   besRETURN_LONG(rtnval);
  84. besEND
  85.  

Code: ScriptBasic
  1. DECLARE SUB mb_init ALIAS "mbas_init" LIB "mb"
  2. DECLARE SUB mb_dispose ALIAS "mbas_dispose" LIB "mb"
  3. DECLARE SUB mb_open ALIAS "mbas_open" LIB "mb"
  4. DECLARE SUB mb_close ALIAS "mbas_close" LIB "mb"
  5. DECLARE SUB mb_load_str ALIAS "mbas_load_str" LIB "mb"
  6. DECLARE SUB mb_run ALIAS "mbas_run" LIB "mb"
  7.  
  8. mb_init()
  9. mb_open()
  10. mb_load_str("PRINT \"Hello MY-BASIC from Script BASIC\"\nPRINT\n")
  11. mb_run()
  12. mb_close()
  13. mb_dispose()
  14.  


jrs@laptop:~/sb/sb22/mybasic$ time scriba testmb.sb
Hello MY-BASIC from Script BASIC

real   0m0.004s
user   0m0.000s
sys   0m0.007s
jrs@laptop:~/sb/sb22/mybasic$


Title: Re: MY-BASIC
Post by: wangrenxin on April 20, 2015, 09:38:54 PM
Interesting macros.

Value pop/push are only used to interactive between MB script and host, so you don't need to use mb_memdup or push anything for loading a script code.

Some idea might help:
mb_open/mb_close requires an 'mb_interpreter_t**' typed argument;
mb_load_string requires 'mb_interpreter_t*, const char*';
mb_run requires 'mb_interpreter_t*';

The main procedure should be somehow like:
Code: C
  1. mb_init
  2. mb_open
  3.         mb_load_str("something...")
  4.         mb_run
  5.        
  6.         mb_load_str("something else...")
  7.         mb_run
  8.        
  9.         ...
  10. mb_close
  11. mb_dispose
  12.  

Where bas is a valid mb_interpreter_t*. A null 'bas' triggered the assertion.

I figured out you got many 'DIM AS struct mb_interpreter_t* bas = 0;' in every besFUNCTION in early posts, the latest post using a global 'bas' should be ok. Calling mb_init at the beginning is necessary, and check if there's any more problem.

BTW. It should be 'rtnval = mb_close(AT bas);' in besFUNCTION(mbas_close).
Title: Re: MY-BASIC
Post by: wangrenxin on April 20, 2015, 09:43:15 PM
Cheers :)
Title: Re: MY-BASIC
Post by: John on April 20, 2015, 10:10:32 PM
Thanks for joining and mentoring the MY-BASIC project here on All BASIC. I hope to include the rest of the API in the extension module. Script BASIC now has TinyScheme, Perl and MY-BASIC extension modules to play with.  8)

BTW  - The mb_assert() function doesn't seem to be exported in the API version of MY-BASIC. I noticed the function in your File addition you mention on github.
Title: Re: MY-BASIC
Post by: wangrenxin on April 20, 2015, 10:33:30 PM
The mb_assert() function doesn't seem to be exported in the API version of MY-BASIC.

It's not an actual function, it's a macro wrapper of the standard assert macro. It's defined in my_basic.h.

For more information about assertions, please see: http://en.wikipedia.org/wiki/Assertion_(software_development) (http://en.wikipedia.org/wiki/Assertion_(software_development))
Title: Re: MY-BASIC
Post by: John on April 20, 2015, 11:29:25 PM
Final clean up.

Code: C
  1. // MY-BASIC - Script BASIC extension module
  2.  
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <stdarg.h>
  7. #include <ctype.h>
  8. #include <math.h>
  9. #include <time.h>
  10. #include "../../basext.h"
  11. #include "cbasic.h"
  12.  
  13. #include "my_basic.h"
  14.  
  15.  
  16. /****************************
  17.  Extension Module Functions
  18. ****************************/
  19.  
  20. besVERSION_NEGOTIATE
  21.   RETURN_FUNCTION((int)INTERFACE_VERSION);
  22. besEND
  23.  
  24. besSUB_START
  25.   DIM AS long PTR p;
  26.   besMODULEPOINTER = besALLOC(sizeof(long));
  27.   IF (besMODULEPOINTER EQ NULL) THEN_DO RETURN_FUNCTION(0);
  28.   p = (long PTR)besMODULEPOINTER;
  29.   RETURN_FUNCTION(0);
  30. besEND
  31.  
  32. besSUB_FINISH
  33.   DIM AS long PTR p;
  34.   p = (long PTR)besMODULEPOINTER;
  35.   IF (p EQ NULL) THEN_DO RETURN_FUNCTION(0);
  36.   RETURN_FUNCTION(0);
  37. besEND
  38.  
  39.  
  40. /********************
  41.  MY-BASIC Functions
  42. ********************/
  43.  
  44. static struct mb_interpreter_t* bas = 0;
  45.  
  46. besFUNCTION(mbas_init)
  47.   besRETURN_LONG(mb_init());
  48. besEND
  49.  
  50. besFUNCTION(mbas_dispose)
  51.   besRETURN_LONG(mb_dispose());
  52. besEND
  53.  
  54. besFUNCTION(mbas_open)
  55.   besRETURN_LONG(mb_open(AT bas));
  56. besEND
  57.  
  58. besFUNCTION(mbas_close)
  59.   besRETURN_LONG(mb_close(AT bas));
  60. besEND
  61.  
  62. besFUNCTION(mbas_load_str)
  63.   DIM AS const char PTR pgm;
  64.   besARGUMENTS("z")
  65.     AT pgm
  66.   besARGEND
  67.   besRETURN_LONG(mb_load_string(bas, pgm));
  68. besEND
  69.  
  70. besFUNCTION(mbas_run)
  71.   besRETURN_LONG(mb_run(bas));
  72. besEND
  73.  
Title: Re: MY-BASIC
Post by: John on April 21, 2015, 08:42:00 AM
Here is a Prime Number (benchmark) running under MY-BASIC as a Script BASIC extension module call.

Code: ScriptBasic
  1. DECLARE SUB mb_init ALIAS "mbas_init" LIB "mb"
  2. DECLARE SUB mb_dispose ALIAS "mbas_dispose" LIB "mb"
  3. DECLARE SUB mb_open ALIAS "mbas_open" LIB "mb"
  4. DECLARE SUB mb_close ALIAS "mbas_close" LIB "mb"
  5. DECLARE SUB mb_load_str ALIAS "mbas_load_str" LIB "mb"
  6. DECLARE SUB mb_run ALIAS "mbas_run" LIB "mb"
  7.  
  8. mb_init()
  9. mb_open()
  10.  
  11. mb_code = """
  12. FOR i = 3 TO 5000
  13.  f = 1
  14.  FOR j = 2 TO SQR(i)
  15.    IF i MOD j = 0 THEN f = 0 : EXIT
  16.  NEXT j
  17.  IF f = 1 THEN PRINT i," "
  18. NEXT i
  19. PRINT ,
  20. """
  21. mb_load_str(mb_code)
  22. mb_run()
  23. mb_close()
  24. mb_dispose()
  25.  


jrs@laptop:~/sb/sb22/mybasic$ time scriba mbprime.sb
3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101 103 107 109 113 127 131 137 139 149 151 157 163 167 173 179 181 191 193 197 199 211 223 227 229 233 239 241 251 257 263 269 271 277 281 283 293 307 311 313 317 331 337 347 349 353 359 367 373 379 383 389 397 401 409 419 421 431 433 439 443 449 457 461 463 467 479 487 491 499 503 509 521 523 541 547 557 563 569 571 577 587 593 599 601 607 613 617 619 631 641 643 647 653 659 661 673 677 683 691 701 709 719 727 733 739 743 751 757 761 769 773 787 797 809 811 821 823 827 829 839 853 857 859 863 877 881 883 887 907 911 919 929 937 941 947 953 967 971 977 983 991 997 1009 1013 1019 1021 1031 1033 1039 1049 1051 1061 1063 1069 1087 1091 1093 1097 1103 1109 1117 1123 1129 1151 1153 1163 1171 1181 1187 1193 1201 1213 1217 1223 1229 1231 1237 1249 1259 1277 1279 1283 1289 1291 1297 1301 1303 1307 1319 1321 1327 1361 1367 1373 1381 1399 1409 1423 1427 1429 1433 1439 1447 1451 1453 1459 1471 1481 1483 1487 1489 1493 1499 1511 1523 1531 1543 1549 1553 1559 1567 1571 1579 1583 1597 1601 1607 1609 1613 1619 1621 1627 1637 1657 1663 1667 1669 1693 1697 1699 1709 1721 1723 1733 1741 1747 1753 1759 1777 1783 1787 1789 1801 1811 1823 1831 1847 1861 1867 1871 1873 1877 1879 1889 1901 1907 1913 1931 1933 1949 1951 1973 1979 1987 1993 1997 1999 2003 2011 2017 2027 2029 2039 2053 2063 2069 2081 2083 2087 2089 2099 2111 2113 2129 2131 2137 2141 2143 2153 2161 2179 2203 2207 2213 2221 2237 2239 2243 2251 2267 2269 2273 2281 2287 2293 2297 2309 2311 2333 2339 2341 2347 2351 2357 2371 2377 2381 2383 2389 2393 2399 2411 2417 2423 2437 2441 2447 2459 2467 2473 2477 2503 2521 2531 2539 2543 2549 2551 2557 2579 2591 2593 2609 2617 2621 2633 2647 2657 2659 2663 2671 2677 2683 2687 2689 2693 2699 2707 2711 2713 2719 2729 2731 2741 2749 2753 2767 2777 2789 2791 2797 2801 2803 2819 2833 2837 2843 2851 2857 2861 2879 2887 2897 2903 2909 2917 2927 2939 2953 2957 2963 2969 2971 2999 3001 3011 3019 3023 3037 3041 3049 3061 3067 3079 3083 3089 3109 3119 3121 3137 3163 3167 3169 3181 3187 3191 3203 3209 3217 3221 3229 3251 3253 3257 3259 3271 3299 3301 3307 3313 3319 3323 3329 3331 3343 3347 3359 3361 3371 3373 3389 3391 3407 3413 3433 3449 3457 3461 3463 3467 3469 3491 3499 3511 3517 3527 3529 3533 3539 3541 3547 3557 3559 3571 3581 3583 3593 3607 3613 3617 3623 3631 3637 3643 3659 3671 3673 3677 3691 3697 3701 3709 3719 3727 3733 3739 3761 3767 3769 3779 3793 3797 3803 3821 3823 3833 3847 3851 3853 3863 3877 3881 3889 3907 3911 3917 3919 3923 3929 3931 3943 3947 3967 3989 4001 4003 4007 4013 4019 4021 4027 4049 4051 4057 4073 4079 4091 4093 4099 4111 4127 4129 4133 4139 4153 4157 4159 4177 4201 4211 4217 4219 4229 4231 4241 4243 4253 4259 4261 4271 4273 4283 4289 4297 4327 4337 4339 4349 4357 4363 4373 4391 4397 4409 4421 4423 4441 4447 4451 4457 4463 4481 4483 4493 4507 4513 4517 4519 4523 4547 4549 4561 4567 4583 4591 4597 4603 4621 4637 4639 4643 4649 4651 4657 4663 4673 4679 4691 4703 4721 4723 4729 4733 4751 4759 4783 4787 4789 4793 4799 4801 4813 4817 4831 4861 4871 4877 4889 4903 4909 4919 4931 4933 4937 4943 4951 4957 4967 4969 4973 4987 4993 4999

real   0m0.145s
user   0m0.131s
sys   0m0.000s
jrs@laptop:~/sb/sb22/mybasic$

Title: Re: MY-BASIC
Post by: John on April 21, 2015, 09:43:55 AM
Here is the Script BASIC only equivalent.

Code: ScriptBasic
  1. FOR i = 3 TO 5000
  2.   FOR j = 2 TO SQR(i)
  3.     IF i % j = 0 THEN GOTO nDone
  4.   NEXT
  5.   PRINT i," "
  6.   nDone:
  7. NEXT
  8. PRINTNL
  9.  


jrs@laptop:~/sb/sb22/test$ time scriba pnsqr2.sb
3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101 103 107 109 113 127 131 137 139 149 151 157 163 167 173 179 181 191 193 197 199 211 223 227 229 233 239 241 251 257 263 269 271 277 281 283 293 307 311 313 317 331 337 347 349 353 359 367 373 379 383 389 397 401 409 419 421 431 433 439 443 449 457 461 463 467 479 487 491 499 503 509 521 523 541 547 557 563 569 571 577 587 593 599 601 607 613 617 619 631 641 643 647 653 659 661 673 677 683 691 701 709 719 727 733 739 743 751 757 761 769 773 787 797 809 811 821 823 827 829 839 853 857 859 863 877 881 883 887 907 911 919 929 937 941 947 953 967 971 977 983 991 997 1009 1013 1019 1021 1031 1033 1039 1049 1051 1061 1063 1069 1087 1091 1093 1097 1103 1109 1117 1123 1129 1151 1153 1163 1171 1181 1187 1193 1201 1213 1217 1223 1229 1231 1237 1249 1259 1277 1279 1283 1289 1291 1297 1301 1303 1307 1319 1321 1327 1361 1367 1373 1381 1399 1409 1423 1427 1429 1433 1439 1447 1451 1453 1459 1471 1481 1483 1487 1489 1493 1499 1511 1523 1531 1543 1549 1553 1559 1567 1571 1579 1583 1597 1601 1607 1609 1613 1619 1621 1627 1637 1657 1663 1667 1669 1693 1697 1699 1709 1721 1723 1733 1741 1747 1753 1759 1777 1783 1787 1789 1801 1811 1823 1831 1847 1861 1867 1871 1873 1877 1879 1889 1901 1907 1913 1931 1933 1949 1951 1973 1979 1987 1993 1997 1999 2003 2011 2017 2027 2029 2039 2053 2063 2069 2081 2083 2087 2089 2099 2111 2113 2129 2131 2137 2141 2143 2153 2161 2179 2203 2207 2213 2221 2237 2239 2243 2251 2267 2269 2273 2281 2287 2293 2297 2309 2311 2333 2339 2341 2347 2351 2357 2371 2377 2381 2383 2389 2393 2399 2411 2417 2423 2437 2441 2447 2459 2467 2473 2477 2503 2521 2531 2539 2543 2549 2551 2557 2579 2591 2593 2609 2617 2621 2633 2647 2657 2659 2663 2671 2677 2683 2687 2689 2693 2699 2707 2711 2713 2719 2729 2731 2741 2749 2753 2767 2777 2789 2791 2797 2801 2803 2819 2833 2837 2843 2851 2857 2861 2879 2887 2897 2903 2909 2917 2927 2939 2953 2957 2963 2969 2971 2999 3001 3011 3019 3023 3037 3041 3049 3061 3067 3079 3083 3089 3109 3119 3121 3137 3163 3167 3169 3181 3187 3191 3203 3209 3217 3221 3229 3251 3253 3257 3259 3271 3299 3301 3307 3313 3319 3323 3329 3331 3343 3347 3359 3361 3371 3373 3389 3391 3407 3413 3433 3449 3457 3461 3463 3467 3469 3491 3499 3511 3517 3527 3529 3533 3539 3541 3547 3557 3559 3571 3581 3583 3593 3607 3613 3617 3623 3631 3637 3643 3659 3671 3673 3677 3691 3697 3701 3709 3719 3727 3733 3739 3761 3767 3769 3779 3793 3797 3803 3821 3823 3833 3847 3851 3853 3863 3877 3881 3889 3907 3911 3917 3919 3923 3929 3931 3943 3947 3967 3989 4001 4003 4007 4013 4019 4021 4027 4049 4051 4057 4073 4079 4091 4093 4099 4111 4127 4129 4133 4139 4153 4157 4159 4177 4201 4211 4217 4219 4229 4231 4241 4243 4253 4259 4261 4271 4273 4283 4289 4297 4327 4337 4339 4349 4357 4363 4373 4391 4397 4409 4421 4423 4441 4447 4451 4457 4463 4481 4483 4493 4507 4513 4517 4519 4523 4547 4549 4561 4567 4583 4591 4597 4603 4621 4637 4639 4643 4649 4651 4657 4663 4673 4679 4691 4703 4721 4723 4729 4733 4751 4759 4783 4787 4789 4793 4799 4801 4813 4817 4831 4861 4871 4877 4889 4903 4909 4919 4931 4933 4937 4943 4951 4957 4967 4969 4973 4987 4993 4999

real   0m0.034s
user   0m0.028s
sys   0m0.004s
jrs@laptop:~/sb/sb22/test$

Title: Re: MY-BASIC
Post by: John on April 21, 2015, 12:13:02 PM
@Tony -


Q. What is the best way to print a new line? I noticed that if I use PRINT alone on a line, MY-BASIC complains.

A. If you end the PRINT line with a comma, a newline will be generated.

Q. I'm assuming at this point that MY-BASIC doesn't support FUNCTION/SUB ?


Comment: I had to get use to the older style IF statement. Script BASIC doesn't support multiple statements separated by :'s.
 
Title: Re: MY-BASIC
Post by: John on April 21, 2015, 03:45:50 PM
I added the mb_load_file and mb_reset functions to the extension module.

Code: C
  1. // MY-BASIC - Script BASIC extension module
  2.  
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <stdarg.h>
  7. #include <ctype.h>
  8. #include <math.h>
  9. #include <time.h>
  10. #include "../../basext.h"
  11. #include "cbasic.h"
  12.  
  13. #include "my_basic.h"
  14.  
  15.  
  16. /****************************
  17.  Extension Module Functions
  18. ****************************/
  19.  
  20. besVERSION_NEGOTIATE
  21.   RETURN_FUNCTION((int)INTERFACE_VERSION);
  22. besEND
  23.  
  24. besSUB_START
  25.   DIM AS long PTR p;
  26.   besMODULEPOINTER = besALLOC(sizeof(long));
  27.   IF (besMODULEPOINTER EQ NULL) THEN_DO RETURN_FUNCTION(0);
  28.   p = (long PTR)besMODULEPOINTER;
  29.   RETURN_FUNCTION(0);
  30. besEND
  31.  
  32. besSUB_FINISH
  33.   DIM AS long PTR p;
  34.   p = (long PTR)besMODULEPOINTER;
  35.   IF (p EQ NULL) THEN_DO RETURN_FUNCTION(0);
  36.   RETURN_FUNCTION(0);
  37. besEND
  38.  
  39.  
  40. /********************
  41.  MY-BASIC Functions
  42. ********************/
  43.  
  44. static struct mb_interpreter_t* bas = 0;
  45.  
  46. besFUNCTION(mbas_init)
  47.   besRETURN_LONG(mb_init());
  48. besEND
  49.  
  50. besFUNCTION(mbas_dispose)
  51.   besRETURN_LONG(mb_dispose());
  52. besEND
  53.  
  54. besFUNCTION(mbas_open)
  55.   besRETURN_LONG(mb_open(AT bas));
  56. besEND
  57.  
  58. besFUNCTION(mbas_close)
  59.   besRETURN_LONG(mb_close(AT bas));
  60. besEND
  61.  
  62. besFUNCTION(mbas_load_str)
  63.   DIM AS const char PTR pgm;
  64.   besARGUMENTS("z")
  65.     AT pgm
  66.   besARGEND
  67.   besRETURN_LONG(mb_load_string(bas, pgm));
  68. besEND
  69.  
  70. besFUNCTION(mbas_load_file)
  71.   DIM AS const char PTR pgm;
  72.   besARGUMENTS("z")
  73.     AT pgm
  74.   besARGEND
  75.   besRETURN_LONG(mb_load_file(bas, pgm));
  76. besEND
  77.  
  78. besFUNCTION(mbas_run)
  79.   besRETURN_LONG(mb_run(bas));
  80. besEND
  81.  
  82. besFUNCTION(mbas_reset)
  83.   besRETURN_LONG(mb_reset(bas, false));
  84. besEND
  85.  

mbprime.sb
Code: ScriptBasic
  1. DECLARE SUB mb_init ALIAS "mbas_init" LIB "mb"
  2. DECLARE SUB mb_dispose ALIAS "mbas_dispose" LIB "mb"
  3. DECLARE SUB mb_open ALIAS "mbas_open" LIB "mb"
  4. DECLARE SUB mb_close ALIAS "mbas_close" LIB "mb"
  5. DECLARE SUB mb_load_str ALIAS "mbas_load_str" LIB "mb"
  6. DECLARE SUB mb_load_file ALIAS "mbas_load_file" LIB "mb"
  7. DECLARE SUB mb_run ALIAS "mbas_run" LIB "mb"
  8. DECLARE SUB mb_reset ALIAS "mbas_reset" LIB "mb"
  9.  
  10. mb_init()
  11. mb_open()
  12. mb_load_file("mbprime.bas")
  13. mb_run()
  14. mb_close()
  15. mb_dispose()
  16.  

mbprime.bas (MY-BASIC)
Code: [Select]
FOR i = 3 TO 5000
  f = 1
  FOR j = 2 TO SQR(i)
    IF i MOD j = 0 THEN f = 0 : EXIT
  NEXT j
  IF f = 1 THEN PRINT i," "
NEXT i
PRINT ,

Title: Re: MY-BASIC
Post by: John on April 21, 2015, 04:08:04 PM
If this is going to be of any use, Script BASIC needs to be able to at the minimum retrieve MY-BASIC variables. Can someone post a C example of doing this?

Is there a way I could return back to Script BASIC the current program in MY-BASIC workspace? (LIST to string variable)
Title: Re: MY-BASIC
Post by: wangrenxin on April 21, 2015, 07:17:44 PM
@John

1. In MY-BAIC use semicolon like 'PRINT ;' to generate a new line.
2. MB supports GOTO/GOSUB/RETURN, doesn't support FUNCTION/SUB routine yet.
3. Use mb_pop_XXX to retrieve values, and mb_push_XXX to return values, see the file extension https://github.com/paladin-t/my_basic/wiki/File-module (https://github.com/paladin-t/my_basic/wiki/File-module) for demo; search for 'mb_pop_'.
Title: Re: MY-BASIC
Post by: John on April 21, 2015, 07:28:46 PM
Quote
3. Use mb_pop_XXX to retrieve values, and mb_push_XXX to return values, see the file extension https://github.com/paladin-t/my_basic/wiki/File-module for demo; search for 'mb_pop_'.

Lets say I run a MY-BASIC script which sets an integer variable called myint. Once SB gets control again after the mb_run, I would like to get the value of myint from Script BASIC.

Can you post a C code snippet showing how to do the above?

I see no reference showing a script being run and getting a variable by name.
Title: Re: MY-BASIC
Post by: wangrenxin on April 21, 2015, 09:21:53 PM
You can't get a specific variable in C, but you can pass a variable from script.

Step 1. Write a C function:
Code: C
  1.         int watch(struct mb_interpreter_t* s, void** l) {
  2.                 int result = MB_FUNC_OK;
  3.                 int_t arg = 0;
  4.  
  5.                 mb_assert(s && l);
  6.  
  7.                 mb_check(mb_attempt_open_bracket(s, l));
  8.  
  9.                 mb_check(mb_pop_int(s, l, &arg)); // That's it!
  10.  
  11.                 mb_check(mb_attempt_close_bracket(s, l));
  12.  
  13.                 // arg is what you want.
  14.  
  15.                 return result;
  16.         }
  17.  

Step 2. Register it: mb_reg_fun(bas, watch);

Step 3. Now call it wherever in your script to watch a value of an expression:
Code: Text
  1.         WATCH(FOO)
  2.         WATCH(A + B * C)
  3.         WATCH(123)
  4.         ...
  5.  
Title: Re: MY-BASIC
Post by: John on April 21, 2015, 09:40:50 PM
void** l

What is l?

From Script BASIC I assume I'm passing a string constant  to my watch wrapped function which I assume is void** l.

You have seen the source to the Script BASIC MY-BASIC extension module. Can cobble together a function that would work within that environment? This is a surprise. I would of thought getting and setting of variables is core functionality when offering an embedded solution.
Title: Re: MY-BASIC
Post by: John on April 21, 2015, 09:58:23 PM
@Tony - Are the functions in the PDF for the C programmer to create, set, read MY-BASIC variables from the host language? If that is true, can't I create these variables first and assign them with the MY-BASIC script? I find it hard to believe you would create an embeddable BASIC and not allow the host and MY-BASIC to communicate. (passing variables between them) Remember you have no IO functionality to fall back on.

Title: Re: MY-BASIC
Post by: John on April 21, 2015, 10:30:41 PM
I gave it a shot trying to create a mb_getint() function but I'm back to the assert issue.

Code: C
  1. // MY-BASIC - Script BASIC extension module
  2.  
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <stdarg.h>
  7. #include <ctype.h>
  8. #include <math.h>
  9. #include <time.h>
  10. #include "../../basext.h"
  11. #include "cbasic.h"
  12.  
  13. #include "my_basic.h"
  14.  
  15.  
  16. /****************************
  17.  Extension Module Functions
  18. ****************************/
  19.  
  20. besVERSION_NEGOTIATE
  21.   RETURN_FUNCTION((int)INTERFACE_VERSION);
  22. besEND
  23.  
  24. besSUB_START
  25.   DIM AS long PTR p;
  26.   besMODULEPOINTER = besALLOC(sizeof(long));
  27.   IF (besMODULEPOINTER EQ NULL) THEN_DO RETURN_FUNCTION(0);
  28.   p = (long PTR)besMODULEPOINTER;
  29.   RETURN_FUNCTION(0);
  30. besEND
  31.  
  32. besSUB_FINISH
  33.   DIM AS long PTR p;
  34.   p = (long PTR)besMODULEPOINTER;
  35.   IF (p EQ NULL) THEN_DO RETURN_FUNCTION(0);
  36.   RETURN_FUNCTION(0);
  37. besEND
  38.  
  39.  
  40. /********************
  41.  MY-BASIC Functions
  42. ********************/
  43.  
  44. static struct mb_interpreter_t* bas = 0;
  45.  
  46. static int watch(struct mb_interpreter_t* s, void** l) {
  47.   int result = MB_FUNC_OK;
  48.   int_t arg = 0;
  49.   mb_assert(s && l);
  50.   mb_check(mb_attempt_open_bracket(s, l));
  51.   mb_check(mb_pop_int(s, l, &arg)); // That's it!
  52.   mb_check(mb_attempt_close_bracket(s, l));
  53.   // arg is what you want.
  54.   return result;
  55. }
  56.  
  57. besFUNCTION(mbas_init)
  58.   besRETURN_LONG(mb_init());
  59. besEND
  60.  
  61. besFUNCTION(mbas_dispose)
  62.   besRETURN_LONG(mb_dispose());
  63. besEND
  64.  
  65. besFUNCTION(mbas_open)
  66.   besRETURN_LONG(mb_open(AT bas));
  67. besEND
  68.  
  69. besFUNCTION(mbas_close)
  70.   besRETURN_LONG(mb_close(AT bas));
  71. besEND
  72.  
  73. besFUNCTION(mbas_load_str)
  74.   DIM AS const char PTR pgm;
  75.   besARGUMENTS("z")
  76.     AT pgm
  77.   besARGEND
  78.   besRETURN_LONG(mb_load_string(bas, pgm));
  79. besEND
  80.  
  81. besFUNCTION(mbas_load_file)
  82.   DIM AS const char PTR pgm;
  83.   besARGUMENTS("z")
  84.     AT pgm
  85.   besARGEND
  86.   besRETURN_LONG(mb_load_file(bas, pgm));
  87. besEND
  88.  
  89. besFUNCTION(mbas_run)
  90.   besRETURN_LONG(mb_run(bas));
  91. besEND
  92.  
  93. besFUNCTION(mbas_reset)
  94.   besRETURN_LONG(mb_reset(bas, false));
  95. besEND
  96.  
  97. besFUNCTION(mbas_getint)
  98.   DIM AS const char PTR expr;
  99.   besARGUMENTS("z")
  100.     AT expr
  101.   besARGEND
  102.   mb_reg_fun(bas, watch);
  103.   besRETURN_LONG(watch(bas, expr));
  104. besEND
  105.  

Code: ScriptBasic
  1. DECLARE SUB mb_init ALIAS "mbas_init" LIB "mb"
  2. DECLARE SUB mb_dispose ALIAS "mbas_dispose" LIB "mb"
  3. DECLARE SUB mb_open ALIAS "mbas_open" LIB "mb"
  4. DECLARE SUB mb_close ALIAS "mbas_close" LIB "mb"
  5. DECLARE SUB mb_load_str ALIAS "mbas_load_str" LIB "mb"
  6. DECLARE SUB mb_load_file ALIAS "mbas_load_file" LIB "mb"
  7. DECLARE SUB mb_run ALIAS "mbas_run" LIB "mb"
  8. DECLARE SUB mb_reset ALIAS "mbas_reset" LIB "mb"
  9. DECLARE SUB mb_getint ALIAS "mbas_getint" LIB "mb"
  10.  
  11. mb_init()
  12. mb_open()
  13. mb_load_file("mbprime.bas")
  14. mb_run()
  15. PRINT mb_getint("i"),"\n"
  16. mb_close()
  17. mb_dispose()
  18.  


jrs@laptop:~/sb/sb22/mybasic$ scriba mbprime.sb
3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101 103 107 109 113 127 131 137 139 149 151 157 163 167 173 179 181 191 193 197 199 211 223 227 229 233 239 241 251 257 263 269 271 277 281 283 293 307 311 313 317 331 337 347 349 353 359 367 373 379 383 389 397 401 409 419 421 431 433 439 443 449 457 461 463 467 479 487 491 499 503 509 521 523 541 547 557 563 569 571 577 587 593 599 601 607 613 617 619 631 641 643 647 653 659 661 673 677 683 691 701 709 719 727 733 739 743 751 757 761 769 773 787 797 809 811 821 823 827 829 839 853 857 859 863 877 881 883 887 907 911 919 929 937 941 947 953 967 971 977 983 991 997 1009 1013 1019 1021 1031 1033 1039 1049 1051 1061 1063 1069 1087 1091 1093 1097 1103 1109 1117 1123 1129 1151 1153 1163 1171 1181 1187 1193 1201 1213 1217 1223 1229 1231 1237 1249 1259 1277 1279 1283 1289 1291 1297 1301 1303 1307 1319 1321 1327 1361 1367 1373 1381 1399 1409 1423 1427 1429 1433 1439 1447 1451 1453 1459 1471 1481 1483 1487 1489 1493 1499 1511 1523 1531 1543 1549 1553 1559 1567 1571 1579 1583 1597 1601 1607 1609 1613 1619 1621 1627 1637 1657 1663 1667 1669 1693 1697 1699 1709 1721 1723 1733 1741 1747 1753 1759 1777 1783 1787 1789 1801 1811 1823 1831 1847 1861 1867 1871 1873 1877 1879 1889 1901 1907 1913 1931 1933 1949 1951 1973 1979 1987 1993 1997 1999 2003 2011 2017 2027 2029 2039 2053 2063 2069 2081 2083 2087 2089 2099 2111 2113 2129 2131 2137 2141 2143 2153 2161 2179 2203 2207 2213 2221 2237 2239 2243 2251 2267 2269 2273 2281 2287 2293 2297 2309 2311 2333 2339 2341 2347 2351 2357 2371 2377 2381 2383 2389 2393 2399 2411 2417 2423 2437 2441 2447 2459 2467 2473 2477 2503 2521 2531 2539 2543 2549 2551 2557 2579 2591 2593 2609 2617 2621 2633 2647 2657 2659 2663 2671 2677 2683 2687 2689 2693 2699 2707 2711 2713 2719 2729 2731 2741 2749 2753 2767 2777 2789 2791 2797 2801 2803 2819 2833 2837 2843 2851 2857 2861 2879 2887 2897 2903 2909 2917 2927 2939 2953 2957 2963 2969 2971 2999 3001 3011 3019 3023 3037 3041 3049 3061 3067 3079 3083 3089 3109 3119 3121 3137 3163 3167 3169 3181 3187 3191 3203 3209 3217 3221 3229 3251 3253 3257 3259 3271 3299 3301 3307 3313 3319 3323 3329 3331 3343 3347 3359 3361 3371 3373 3389 3391 3407 3413 3433 3449 3457 3461 3463 3467 3469 3491 3499 3511 3517 3527 3529 3533 3539 3541 3547 3557 3559 3571 3581 3583 3593 3607 3613 3617 3623 3631 3637 3643 3659 3671 3673 3677 3691 3697 3701 3709 3719 3727 3733 3739 3761 3767 3769 3779 3793 3797 3803 3821 3823 3833 3847 3851 3853 3863 3877 3881 3889 3907 3911 3917 3919 3923 3929 3931 3943 3947 3967 3989 4001 4003 4007 4013 4019 4021 4027 4049 4051 4057 4073 4079 4091 4093 4099 4111 4127 4129 4133 4139 4153 4157 4159 4177 4201 4211 4217 4219 4229 4231 4241 4243 4253 4259 4261 4271 4273 4283 4289 4297 4327 4337 4339 4349 4357 4363 4373 4391 4397 4409 4421 4423 4441 4447 4451 4457 4463 4481 4483 4493 4507 4513 4517 4519 4523 4547 4549 4561 4567 4583 4591 4597 4603 4621 4637 4639 4643 4649 4651 4657 4663 4673 4679 4691 4703 4721 4723 4729 4733 4751 4759 4783 4787 4789 4793 4799 4801 4813 4817 4831 4861 4871 4877 4889 4scriba: symbol lookup error: /home/jrs/sb/sb22/modules/mb.so: undefined symbol: assert
jrs@laptop:~/sb/sb22/mybasic$

Title: Re: MY-BASIC
Post by: wangrenxin on April 22, 2015, 02:16:02 AM
@John

You need only register once when open an interpreter structure, see the registering of 'beep' in '_on_startup' at 'main.c' for example.

Of course you could declare and assign variables in MY-BASIC script and communicate between MB and host; but you couldn't get or set it with the variable identifier. The way in MB to do script -> host is mb_pop_XXX functions, and host -> script with mb_push_XXX.

Eg. somehow in script like this:

Code: Text
  1. A = 0 ' Create and assign a variable.
  2. A = WATCH(A) ' Send it to host and assign with a new value sent from host.
  3.  

Add mb_push_XXX in 'watch' to send values from host to script.
Title: Re: MY-BASIC
Post by: wangrenxin on April 22, 2015, 04:21:17 AM
'watch' should be like:

Code: C
  1. int watch(struct mb_interpreter_t* s, void** l) {
  2.         int result = MB_FUNC_OK;
  3.         int_t arg = 0;
  4.  
  5.         mb_assert(s && l);
  6.  
  7.         mb_check(mb_attempt_open_bracket(s, l));
  8.  
  9.         mb_check(mb_pop_int(s, l, &arg)); // That's it!
  10.  
  11.         mb_check(mb_attempt_close_bracket(s, l));
  12.  
  13.         // do what ever you want with 'arg'.
  14.  
  15.         mb_check(mb_push_int(s, l, arg));
  16.  
  17.         return result;
  18. }
  19.  
Title: Re: MY-BASIC
Post by: John on April 22, 2015, 08:31:32 AM
This solution looks like I can only communicate with one variable at  a time.  :-\  To be honest, this is a kludge and you need a better way for the host and MY-BASIC to share its variables. I would like to be able to do something like the Perl extension module for SB.

Code: ScriptBasic
  1. DECLARE SUB pl_Init ALIAS "pl_Init" LIB "sbperl"
  2. DECLARE SUB pl_Eval ALIAS "pl_Eval" LIB "sbperl"
  3. DECLARE SUB pl_GetInt ALIAS "pl_GetInt" LIB "sbperl"
  4. DECLARE SUB pl_GetDbl ALIAS "pl_GetDbl" LIB "sbperl"
  5. DECLARE SUB pl_GetStr ALIAS "pl_GetStr" LIB "sbperl"
  6. DECLARE SUB pl_Destroy ALIAS "pl_Destroy" LIB "sbperl"
  7.  
  8. pl_Init
  9.  
  10. pl_code = """
  11. sub Average{
  12.   # get total number of arguments passed.
  13.   $n = scalar(@_);
  14.   $sum = 0;
  15.  
  16.   foreach $item (@_){
  17.      $sum += $item;
  18.   }
  19.   $average = $sum / $n;
  20.  
  21.   return $average;
  22. }
  23. """
  24. pl_Eval pl_code
  25. pl_Eval "$num = Average(10, 20, 30);"
  26. PRINT pl_GetInt("num"),"\n"
  27.  
  28. pl_Destroy
  29.  


jrs@laptop:~/sb/sb22/test$ scriba perlfunc.sb
20
jrs@laptop:~/sb/sb22/test$


Here is an example of embedding Script BASIC in BaCon and using the SQLite3 extension module and passing the resulting record set back to BaCon.

Code: [Select]
PRAGMA OPTIONS -I/home/jrs/sb/source
PRAGMA LDFLAGS scriba pthread
PRAGMA INCLUDE scriba.h getopt.h

PROTO scriba_destroy

DECLARE pProgram TYPE pSbProgram
DECLARE pVariable TYPE pSbData

pProgram = scriba_new(malloc,free)
ok = scriba_LoadConfiguration(pProgram,"/etc/scriba/basic.conf")
ok = scriba_SetFileName(pProgram, "E05.sb")
ok = scriba_LoadSourceProgram(pProgram)
ok = scriba_Run(pProgram,"")

vsn = scriba_LookupVariableByName(pProgram, "main::dbstr")
ok = scriba_GetVariable(pProgram, vsn, &pVariable)

dbstr$ = pVariable[0].v.s
SPLIT dbstr$ BY "|" TO row$ SIZE cnt

FOR x = 0 TO cnt-1
PRINT row$[x]
NEXT x

jrs@laptop:~/BaCon/B29$ ./bacon sqlext.bac
Converting 'sqlext.bac'... done.
Compiling 'sqlext.bac'... done.
Program 'sqlext' ready.
jrs@laptop:~/BaCon/B29$ ./sqlext
123-hello
234-cruel
345-world

jrs@laptop:~/BaCon/B29$

E05.sb
Code: ScriptBasic
  1. IMPORT sqlite.bas
  2.  
  3. db = sqlite::open("testsql")
  4.  
  5. sqlite::execute(db,"CREATE TABLE demo (someval integer, sometxt text);")
  6. sqlite::execute(db,"INSERT INTO demo VALUES (123,'hello');")
  7. sqlite::execute(db, "INSERT INTO demo VALUES (234, 'cruel');")
  8. sqlite::execute(db, "INSERT INTO demo VALUES (345, 'world');")
  9.  
  10. stmt = sqlite::query(db,"SELECT * FROM demo")
  11.  
  12. WHILE (sqlite::row(stmt) = sqlite::SQLITE3_ROW)
  13.   IF sqlite::fetchhash(stmt,column) THEN
  14.     dbstr &= column{"someval"} & "-" & column{"sometxt"} & "|"
  15.   END IF
  16. WEND
  17.  
  18. sqlite::close(db)
  19.  
Title: Re: MY-BASIC
Post by: wangrenxin on April 22, 2015, 07:15:26 PM
Ability of retrieving variables from host is useful in some case. I consider to implement not only retrieving, but also setting break point and single step evaluating; that will make up a debug API set.
Title: Re: MY-BASIC
Post by: John on April 22, 2015, 07:23:26 PM
Ability of retrieving variables from host is useful in some case. I consider to implement not only retrieving, but also setting break point and single step evaluating; that will make up a debug API set.

Script BASIC has a debugging mode (internal preprocessor) that Dave (SB VB/COM contributor) took advantage of in the IDE/Debugger he wrote.

(http://www.scriptbasic.org/forum/index.php?action=dlattach;topic=323.0;attach=364;image)
Title: Re: MY-BASIC
Post by: wangrenxin on April 22, 2015, 07:29:14 PM
Script BASIC has a debugging mode (internal preprocessor) that Dave (SB VB/COM contributor) took advantage of in the IDE/Debugger he wrote.

Interesting, that's considerable.
Title: Re: MY-BASIC
Post by: wangrenxin on April 23, 2015, 07:58:50 AM
@John
I wrote some debug APIs, you can retrieve and set variable value with identifier now:
https://github.com/paladin-t/my_basic/wiki/Write-a-debugger (https://github.com/paladin-t/my_basic/wiki/Write-a-debugger)
Title: Re: MY-BASIC
Post by: John on April 23, 2015, 08:20:06 AM
Looks like you're on the road to a great debugger for MY-BASIC. I think it would be easier to follow along if you can create a C program like AIR did initially to help me get your BASIC going. I can try your new code in SB as an extension module as it unfolds.

Markus (admin / CM on BP.org) is interested in embedding your BASIC in his Pascal based interpreter. Maybe you can get him to join us here.

Title: Re: MY-BASIC
Post by: John on April 23, 2015, 12:19:03 PM
Hi Tony,

I took a shot at getting the mb_debug_get functions working with Script BASIC. It works GREAT!

interface.c
Code: C
  1. // MY-BASIC - Script BASIC extension module
  2.  
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <stdarg.h>
  7. #include <ctype.h>
  8. #include <math.h>
  9. #include <time.h>
  10. #include "../../basext.h"
  11. #include "cbasic.h"
  12.  
  13. #include "my_basic.h"
  14.  
  15.  
  16. /****************************
  17.  Extension Module Functions
  18. ****************************/
  19.  
  20. besVERSION_NEGOTIATE
  21.   RETURN_FUNCTION((int)INTERFACE_VERSION);
  22. besEND
  23.  
  24. besSUB_START
  25.   DIM AS long PTR p;
  26.   besMODULEPOINTER = besALLOC(sizeof(long));
  27.   IF (besMODULEPOINTER EQ NULL) THEN_DO RETURN_FUNCTION(0);
  28.   p = (long PTR)besMODULEPOINTER;
  29.   RETURN_FUNCTION(0);
  30. besEND
  31.  
  32. besSUB_FINISH
  33.   DIM AS long PTR p;
  34.   p = (long PTR)besMODULEPOINTER;
  35.   IF (p EQ NULL) THEN_DO RETURN_FUNCTION(0);
  36.   RETURN_FUNCTION(0);
  37. besEND
  38.  
  39.  
  40. /********************
  41.  MY-BASIC Functions
  42. ********************/
  43.  
  44. static struct mb_interpreter_t* bas = 0;
  45.  
  46. static int watch(struct mb_interpreter_t* s, void** l) {
  47.   int result = MB_FUNC_OK;
  48.   int_t arg = 0;
  49.   mb_assert(s && l);
  50.   mb_check(mb_attempt_open_bracket(s, l));
  51.   mb_check(mb_pop_int(s, l, &arg)); // That's it!
  52.   mb_check(mb_attempt_close_bracket(s, l));
  53.   // arg is what you want.
  54.   return result;
  55. }
  56.  
  57. besFUNCTION(mbas_init)
  58.   besRETURN_LONG(mb_init());
  59. besEND
  60.  
  61. besFUNCTION(mbas_dispose)
  62.   besRETURN_LONG(mb_dispose());
  63. besEND
  64.  
  65. besFUNCTION(mbas_open)
  66.   besRETURN_LONG(mb_open(AT bas));
  67. besEND
  68.  
  69. besFUNCTION(mbas_close)
  70.   besRETURN_LONG(mb_close(AT bas));
  71. besEND
  72.  
  73. besFUNCTION(mbas_load_str)
  74.   DIM AS const char PTR pgm;
  75.   besARGUMENTS("z")
  76.     AT pgm
  77.   besARGEND
  78.   besRETURN_LONG(mb_load_string(bas, pgm));
  79. besEND
  80.  
  81. besFUNCTION(mbas_load_file)
  82.   DIM AS const char PTR pgm;
  83.   besARGUMENTS("z")
  84.     AT pgm
  85.   besARGEND
  86.   besRETURN_LONG(mb_load_file(bas, pgm));
  87. besEND
  88.  
  89. besFUNCTION(mbas_run)
  90.   besRETURN_LONG(mb_run(bas));
  91. besEND
  92.  
  93. besFUNCTION(mbas_reset)
  94.   besRETURN_LONG(mb_reset(bas, false));
  95. besEND
  96.  
  97. besFUNCTION(mbas_getint)
  98.   DIM AS mb_value_t mbval;
  99.   DIM AS const char PTR varname;
  100.   besARGUMENTS("z")
  101.     AT varname
  102.   besARGEND
  103.   mbval.type = MB_DT_INT;
  104.   mb_debug_get(bas, varname, &mbval);
  105.   besRETURN_LONG(mbval.value.integer);
  106. besEND
  107.  
  108. besFUNCTION(mbas_getdbl)
  109.   DIM AS mb_value_t mbval;
  110.   DIM AS const char PTR varname;
  111.   besARGUMENTS("z")
  112.     AT varname
  113.   besARGEND
  114.   mbval.type = MB_DT_REAL;
  115.   mb_debug_get(bas, varname, &mbval);
  116.   besRETURN_DOUBLE(mbval.value.float_point);
  117. besEND
  118.  
  119. besFUNCTION(mbas_getstr)
  120.   DIM AS mb_value_t mbval;
  121.   DIM AS const char PTR varname;
  122.   besARGUMENTS("z")
  123.     AT varname
  124.   besARGEND
  125.   mbval.type = MB_DT_STRING;
  126.   mb_debug_get(bas, varname, &mbval);
  127.   besRETURN_STRING(mbval.value.string);
  128. besEND
  129.  

mbvars.sb
Code: ScriptBasic
  1. DECLARE SUB mb_init ALIAS "mbas_init" LIB "mb"
  2. DECLARE SUB mb_dispose ALIAS "mbas_dispose" LIB "mb"
  3. DECLARE SUB mb_open ALIAS "mbas_open" LIB "mb"
  4. DECLARE SUB mb_close ALIAS "mbas_close" LIB "mb"
  5. DECLARE SUB mb_load_str ALIAS "mbas_load_str" LIB "mb"
  6. DECLARE SUB mb_load_file ALIAS "mbas_load_file" LIB "mb"
  7. DECLARE SUB mb_run ALIAS "mbas_run" LIB "mb"
  8. DECLARE SUB mb_getint ALIAS "mbas_getint" LIB "mb"
  9. DECLARE SUB mb_getdbl ALIAS "mbas_getdbl" LIB "mb"
  10. DECLARE SUB mb_getstr ALIAS "mbas_getstr" LIB "mb"
  11. DECLARE SUB mb_reset ALIAS "mbas_reset" LIB "mb"
  12.  
  13. mb_init()
  14. mb_open()
  15. mb_load_file("testvars.bas")
  16. mb_run()
  17. PRINT mb_getint("A"),"\n"
  18. PRINT FORMAT("%g\n",mb_getdbl("B"))
  19. PRINT mb_getstr("C$"),"\n"
  20. mb_close()
  21. mb_dispose()
  22.  

testvars.bas (MY-BASIC test script)
Code: [Select]
a = 123
b = 1.23
c$ = "One,Two,Three"

Output

jrs@laptop:~/sb/sb22/mybasic$ time scriba mbvars.sb
123
1.23
One,Two,Three

real   0m0.007s
user   0m0.000s
sys   0m0.005s
jrs@laptop:~/sb/sb22/mybasic$

Title: Re: MY-BASIC
Post by: John on April 23, 2015, 01:57:43 PM
I'm not having as good of luck with the mb_debug_set. (core dump)

Code: C
  1. besFUNCTION(mbas_setint)
  2.   DIM AS mb_value_t mbval;
  3.   DIM AS int usrval;
  4.   DIM AS const char PTR varname;
  5.   besARGUMENTS("zi")
  6.     AT varname, AT usrval
  7.   besARGEND
  8.   mbval.type = MB_DT_INT;
  9.   mbval.value.integer = usrval;
  10.   besRETURN_LONG(mb_debug_set(bas, varname, mbval));
  11. besEND
  12.  
  13. besFUNCTION(mbas_setdbl)
  14.   DIM AS mb_value_t mbval;
  15.   DIM AS double usrval;
  16.   DIM AS const char PTR varname;
  17.   besARGUMENTS("zr")
  18.     AT varname, AT usrval
  19.   besARGEND
  20.   mbval.type = MB_DT_REAL;
  21.   mbval.value.float_point = usrval;
  22.   besRETURN_LONG(mb_debug_set(bas, varname, mbval));
  23. besEND
  24.  
  25. besFUNCTION(mbas_setstr)
  26.   DIM AS mb_value_t mbval;
  27.   DIM AS const char PTR usrval;
  28.   DIM AS const char PTR varname;
  29.   besARGUMENTS("zz")
  30.     AT varname, AT usrval
  31.   besARGEND
  32.   mbval.type = MB_DT_STRING;
  33.   mbval.value.string = usrval;
  34.   besRETURN_LONG(mb_debug_set(bas, varname, mbval));
  35. besEND
  36.  

Code: ScriptBasic
  1. DECLARE SUB mb_init ALIAS "mbas_init" LIB "mb"
  2. DECLARE SUB mb_dispose ALIAS "mbas_dispose" LIB "mb"
  3. DECLARE SUB mb_open ALIAS "mbas_open" LIB "mb"
  4. DECLARE SUB mb_close ALIAS "mbas_close" LIB "mb"
  5. DECLARE SUB mb_load_str ALIAS "mbas_load_str" LIB "mb"
  6. DECLARE SUB mb_load_file ALIAS "mbas_load_file" LIB "mb"
  7. DECLARE SUB mb_run ALIAS "mbas_run" LIB "mb"
  8. DECLARE SUB mb_getint ALIAS "mbas_getint" LIB "mb"
  9. DECLARE SUB mb_getdbl ALIAS "mbas_getdbl" LIB "mb"
  10. DECLARE SUB mb_getstr ALIAS "mbas_getstr" LIB "mb"
  11. DECLARE SUB mb_setint ALIAS "mbas_setint" LIB "mb"
  12. DECLARE SUB mb_setdbl ALIAS "mbas_setdbl" LIB "mb"
  13. DECLARE SUB mb_setstr ALIAS "mbas_setstr" LIB "mb"
  14. DECLARE SUB mb_reset ALIAS "mbas_reset" LIB "mb"
  15.  
  16. mb_init()
  17. mb_open()
  18. mb_load_file("setvars.bas")
  19. mb_run()
  20. mb_setint("A", 123)
  21. mb_setdbl("B", 1.23)
  22. mb_setstr("C$", "One,Two,Three")
  23. mb_run()
  24. mb_close()
  25. mb_dispose()
  26.  

setvars.bas
Code: [Select]
PRINT a;
PRINT b;
PRINT c$;


jrs@laptop:~/sb/sb22/mybasic$ scriba mbvars.sb
0
0
(empty)
scriba: my_basic.c:3977: mb_debug_set: Assertion `s && n' failed.
Aborted (core dumped)
jrs@laptop:~/sb/sb22/mybasic$


At this point I don't plan to add any of the debugging (single step) features to the SB MY-BASIC extension module version.

Can you show us some examples of your IF enhancements with this release?
Title: Re: MY-BASIC
Post by: John on April 23, 2015, 06:38:49 PM
Tony,

I just noticed your profile on Github.

(https://avatars3.githubusercontent.com/u/2062224?v=3&s=460)

Wang Renxin

Chengdu City, China
Title: Re: MY-BASIC
Post by: John on April 23, 2015, 10:37:43 PM
I was able to compile the Script BASIC MY-BASIC extension module for Windows 32 bit. I have attached the DLL and this example in a zip.

mbvars.sb
Code: ScriptBasic
  1. DECLARE SUB mb_init ALIAS "mbas_init" LIB "mb"
  2. DECLARE SUB mb_dispose ALIAS "mbas_dispose" LIB "mb"
  3. DECLARE SUB mb_open ALIAS "mbas_open" LIB "mb"
  4. DECLARE SUB mb_close ALIAS "mbas_close" LIB "mb"
  5. DECLARE SUB mb_load_str ALIAS "mbas_load_str" LIB "mb"
  6. DECLARE SUB mb_load_file ALIAS "mbas_load_file" LIB "mb"
  7. DECLARE SUB mb_run ALIAS "mbas_run" LIB "mb"
  8. DECLARE SUB mb_getint ALIAS "mbas_getint" LIB "mb"
  9. DECLARE SUB mb_getdbl ALIAS "mbas_getdbl" LIB "mb"
  10. DECLARE SUB mb_getstr ALIAS "mbas_getstr" LIB "mb"
  11. DECLARE SUB mb_reset ALIAS "mbas_reset" LIB "mb"
  12.  
  13. mb_init()
  14. mb_open()
  15. mb_load_file("testvars.bas")
  16. mb_run()
  17. PRINT mb_getint("A"),"\n"
  18. PRINT FORMAT("%g\n",mb_getdbl("B"))
  19. PRINT mb_getstr("C$"),"\n"
  20. mb_close()
  21. mb_dispose()
  22.  

testvars.bas
Code: [Select]
a = 123
b = 1.23
c$ = "One,Two,Three"

Output

C:\scriptbasic32\mybasic>scriba mbvars.sb
123
1.23
One,Two,Three

C:\scriptbasic32\mybasic>

Title: Re: MY-BASIC
Post by: wangrenxin on April 23, 2015, 11:13:42 PM
I just noticed your profile on Github.

Haw haw, you found me :)

I polished my_basic.c, or it will trigger an assertion when you write sequenced mb_run.

The set function works fine for me, eg. code:
Code: Text
  1. PRINT A;
  2.  

Code: C
  1. mb_value_t val;
  2. val.type = MB_DT_INT;
  3. val.value.integer = 12345;
  4. mb_run(bas);
  5. mb_debug_set(bas, "A", val);
  6. mb_run(bas);
  7.  

I guess there maybe something wrong in besFUNCTION(mbas_setXXX)

An eg. for enhanced multi line IF:
Code: Text
  1. INPUT n
  2. IF n = 1 THEN
  3.         PRINT "Uno"
  4. ELSEIF n = 2 THEN
  5.         PRINT "Dos"
  6. ELSEIF n = 3 THEN
  7.         PRINT "Thres"
  8. ELSE
  9.         PRINT "Many"
  10. ENDIF
  11.  
Title: Re: MY-BASIC
Post by: John on April 23, 2015, 11:16:20 PM
Tony,

I'm getting a little farther with the Windows 32 bit version of mb.dll.

Do I need to download another version since you added the debug functions?

Code: ScriptBasic
  1. DECLARE SUB mb_init ALIAS "mbas_init" LIB "mb"
  2. DECLARE SUB mb_dispose ALIAS "mbas_dispose" LIB "mb"
  3. DECLARE SUB mb_open ALIAS "mbas_open" LIB "mb"
  4. DECLARE SUB mb_close ALIAS "mbas_close" LIB "mb"
  5. DECLARE SUB mb_load_str ALIAS "mbas_load_str" LIB "mb"
  6. DECLARE SUB mb_load_file ALIAS "mbas_load_file" LIB "mb"
  7. DECLARE SUB mb_run ALIAS "mbas_run" LIB "mb"
  8. DECLARE SUB mb_getint ALIAS "mbas_getint" LIB "mb"
  9. DECLARE SUB mb_getdbl ALIAS "mbas_getdbl" LIB "mb"
  10. DECLARE SUB mb_getstr ALIAS "mbas_getstr" LIB "mb"
  11. DECLARE SUB mb_setint ALIAS "mbas_setint" LIB "mb"
  12. DECLARE SUB mb_setdbl ALIAS "mbas_setdbl" LIB "mb"
  13. DECLARE SUB mb_setstr ALIAS "mbas_setstr" LIB "mb"
  14. DECLARE SUB mb_reset ALIAS "mbas_reset" LIB "mb"
  15.  
  16. mb_init()
  17. mb_open()
  18. mb_load_file("setvars.bas")
  19. mb_run()
  20. mb_setint("A", 123)
  21. PRINT "Got Here\n"
  22. mb_setdbl("B", 1.23)
  23. mb_setstr("C$", "One,Two,Three")
  24. mb_close()
  25. mb_dispose()
  26.  

Code: [Select]
a = 0
b = 0.0
c$ = ""


C:\sb22\mybasic>scriba mbvarset.sb
Got Here
Assertion failed!

Program: c:\scriptbasic\bin\scriba.exe
File: my_basic.c, Line 3889

Expression: 0 && "Memory already released"

This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.

C:\sb22\mybasic>

Title: Re: MY-BASIC
Post by: wangrenxin on April 23, 2015, 11:25:50 PM
Use mb_memdup when setting a string like:
Code: C
  1. const char* str = "One,Two,Three";
  2. mb_setstr("C$", mb_memdup(str, strlen(str) + 1);
  3.  

Or it will trigger the assertion.
Title: Re: MY-BASIC
Post by: John on April 23, 2015, 11:33:06 PM
I'm able to set integers and real/double/float but it fails on the string. I'll try your suggestion.

That still doesn't solve the Linux 64 bit version failing on all mb_set operations.  :-[
Title: Re: MY-BASIC
Post by: wangrenxin on April 23, 2015, 11:48:41 PM
That still doesn't solve the Linux 64 bit version failing on all mb_set operations.  :-[

It runs ok in 64 bit mode with Win/VS, I don't have a Linux environment on hand now. Could you post your full code again?
Title: Re: MY-BASIC
Post by: John on April 23, 2015, 11:57:29 PM
This code sets integer and double on Windows 32 but fails on Linux 64 bit.

Code: C
  1. // MY-BASIC - Script BASIC extension module
  2.  
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <stdarg.h>
  7. #include <ctype.h>
  8. #include <math.h>
  9. #include <time.h>
  10. #include "../../basext.h"
  11. #include "cbasic.h"
  12.  
  13. #include "my_basic.h"
  14.  
  15.  
  16. /****************************
  17.  Extension Module Functions
  18. ****************************/
  19.  
  20. besVERSION_NEGOTIATE
  21.   RETURN_FUNCTION((int)INTERFACE_VERSION);
  22. besEND
  23.  
  24. besSUB_START
  25.   DIM AS long PTR p;
  26.   besMODULEPOINTER = besALLOC(sizeof(long));
  27.   IF (besMODULEPOINTER EQ NULL) THEN_DO RETURN_FUNCTION(0);
  28.   p = (long PTR)besMODULEPOINTER;
  29.   RETURN_FUNCTION(0);
  30. besEND
  31.  
  32. besSUB_FINISH
  33.   DIM AS long PTR p;
  34.   p = (long PTR)besMODULEPOINTER;
  35.   IF (p EQ NULL) THEN_DO RETURN_FUNCTION(0);
  36.   RETURN_FUNCTION(0);
  37. besEND
  38.  
  39.  
  40. /********************
  41.  MY-BASIC Functions
  42. ********************/
  43.  
  44. static struct mb_interpreter_t* bas = 0;
  45.  
  46. static int watch(struct mb_interpreter_t* s, void** l) {
  47.   int result = MB_FUNC_OK;
  48.   int_t arg = 0;
  49.   mb_assert(s && l);
  50.   mb_check(mb_attempt_open_bracket(s, l));
  51.   mb_check(mb_pop_int(s, l, &arg)); // That's it!
  52.   mb_check(mb_attempt_close_bracket(s, l));
  53.   // arg is what you want.
  54.   return result;
  55. }
  56.  
  57. besFUNCTION(mbas_init)
  58.   besRETURN_LONG(mb_init());
  59. besEND
  60.  
  61. besFUNCTION(mbas_dispose)
  62.   besRETURN_LONG(mb_dispose());
  63. besEND
  64.  
  65. besFUNCTION(mbas_open)
  66.   besRETURN_LONG(mb_open(AT bas));
  67. besEND
  68.  
  69. besFUNCTION(mbas_close)
  70.   besRETURN_LONG(mb_close(AT bas));
  71. besEND
  72.  
  73. besFUNCTION(mbas_load_str)
  74.   DIM AS const char PTR pgm;
  75.   besARGUMENTS("z")
  76.     AT pgm
  77.   besARGEND
  78.   besRETURN_LONG(mb_load_string(bas, pgm));
  79. besEND
  80.  
  81. besFUNCTION(mbas_load_file)
  82.   DIM AS const char PTR pgm;
  83.   besARGUMENTS("z")
  84.     AT pgm
  85.   besARGEND
  86.   besRETURN_LONG(mb_load_file(bas, pgm));
  87. besEND
  88.  
  89. besFUNCTION(mbas_run)
  90.   besRETURN_LONG(mb_run(bas));
  91. besEND
  92.  
  93. besFUNCTION(mbas_reset)
  94.   besRETURN_LONG(mb_reset(bas, false));
  95. besEND
  96.  
  97. besFUNCTION(mbas_getint)
  98.   DIM AS mb_value_t mbval;
  99.   DIM AS const char PTR varname;
  100.   besARGUMENTS("z")
  101.     AT varname
  102.   besARGEND
  103.   mbval.type = MB_DT_INT;
  104.   mb_debug_get(bas, varname, &mbval);
  105.   besRETURN_LONG(mbval.value.integer);
  106. besEND
  107.  
  108. besFUNCTION(mbas_getdbl)
  109.   DIM AS mb_value_t mbval;
  110.   DIM AS const char PTR varname;
  111.   besARGUMENTS("z")
  112.     AT varname
  113.   besARGEND
  114.   mbval.type = MB_DT_REAL;
  115.   mb_debug_get(bas, varname, &mbval);
  116.   besRETURN_DOUBLE(mbval.value.float_point);
  117. besEND
  118.  
  119. besFUNCTION(mbas_getstr)
  120.   DIM AS mb_value_t mbval;
  121.   DIM AS const char PTR varname;
  122.   besARGUMENTS("z")
  123.     AT varname
  124.   besARGEND
  125.   mbval.type = MB_DT_STRING;
  126.   mb_debug_get(bas, varname, &mbval);
  127.   besRETURN_STRING(mbval.value.string);
  128. besEND
  129.  
  130. besFUNCTION(mbas_setint)
  131.   DIM AS mb_value_t mbval;
  132.   DIM AS int usrval;
  133.   DIM AS const char PTR varname;
  134.   besARGUMENTS("zi")
  135.     AT varname, AT usrval
  136.   besARGEND
  137.   mbval.type = MB_DT_INT;
  138.   mbval.value.integer = usrval;
  139.   besRETURN_LONG(mb_debug_set(bas, varname, mbval));
  140. besEND
  141.  
  142. besFUNCTION(mbas_setdbl)
  143.   DIM AS mb_value_t mbval;
  144.   DIM AS double usrval;
  145.   DIM AS const char PTR varname;
  146.   besARGUMENTS("zr")
  147.     AT varname, AT usrval
  148.   besARGEND
  149.   mbval.type = MB_DT_REAL;
  150.   mbval.value.float_point = usrval;
  151.   besRETURN_LONG(mb_debug_set(bas, varname, mbval));
  152. besEND
  153.  
  154. besFUNCTION(mbas_setstr)
  155.   DIM AS mb_value_t mbval;
  156.   DIM AS const char PTR usrval;
  157.   DIM AS const char PTR varname;
  158.   besARGUMENTS("zz")
  159.     AT varname, AT usrval
  160.   besARGEND
  161.   mbval.type = MB_DT_STRING;
  162.   mbval.value.string = usrval;
  163.   besRETURN_LONG(mb_debug_set(bas, varname, mbval));
  164. besEND
  165.  

Code: ScriptBasic
  1. DECLARE SUB mb_init ALIAS "mbas_init" LIB "mb"
  2. DECLARE SUB mb_dispose ALIAS "mbas_dispose" LIB "mb"
  3. DECLARE SUB mb_open ALIAS "mbas_open" LIB "mb"
  4. DECLARE SUB mb_close ALIAS "mbas_close" LIB "mb"
  5. DECLARE SUB mb_load_str ALIAS "mbas_load_str" LIB "mb"
  6. DECLARE SUB mb_load_file ALIAS "mbas_load_file" LIB "mb"
  7. DECLARE SUB mb_run ALIAS "mbas_run" LIB "mb"
  8. DECLARE SUB mb_getint ALIAS "mbas_getint" LIB "mb"
  9. DECLARE SUB mb_getdbl ALIAS "mbas_getdbl" LIB "mb"
  10. DECLARE SUB mb_getstr ALIAS "mbas_getstr" LIB "mb"
  11. DECLARE SUB mb_setint ALIAS "mbas_setint" LIB "mb"
  12. DECLARE SUB mb_setdbl ALIAS "mbas_setdbl" LIB "mb"
  13. DECLARE SUB mb_setstr ALIAS "mbas_setstr" LIB "mb"
  14. DECLARE SUB mb_reset ALIAS "mbas_reset" LIB "mb"
  15.  
  16. mb_init()
  17. mb_open()
  18. mb_load_file("setvars.bas")
  19. mb_run()
  20. mb_setint("A", 123)
  21. mb_setdbl("B", 1.23)
  22. PRINT "Got Here\n"
  23. mb_close()
  24. mb_dispose()
  25.  

setvars.bas
Code: [Select]
a = 0
b = 0.0
c$ = ""


jrs@laptop:~/sb/sb22/mybasic$ scriba mbvars.sb
scriba: my_basic.c:3977: mb_debug_set: Assertion `s && n' failed.
Aborted (core dumped)
jrs@laptop:~/sb/sb22/mybasic$


I'm recompiling the Windows 32 bit version with your string function change. I will report my finding shortly.
Title: Re: MY-BASIC
Post by: John on April 24, 2015, 12:22:37 AM
No luck with your change to fix the Windows mb_setstr() function. Here is my change to the function per your suggestion.

Code: C
  1. besFUNCTION(mbas_setstr)
  2.   DIM AS mb_value_t mbval;
  3.   DIM AS const char PTR usrval;
  4.   DIM AS const char PTR varname;
  5.   besARGUMENTS("zz")
  6.     AT varname, AT usrval
  7.   besARGEND
  8.   mbval.type = MB_DT_STRING;
  9.   usrval = mb_memdup(usrval, strlen(usrval) + 1);
  10.   mbval.value.string = usrval;
  11.   besRETURN_LONG(mb_debug_set(bas, varname, mbval));
  12. besEND
  13.  


C:\sb22\mybasic>scriba mbvarset.sb
Got Here
Assertion failed: 0 && "Memory already released", file my_basic.c, line 3889

This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.

C:\sb22\mybasic>

Title: Re: MY-BASIC
Post by: wangrenxin on April 24, 2015, 12:27:29 AM
Try add a debugging printf. Neither bas nor varname shouldn't be NULL under 64 bit.
Code: C
  1. besFUNCTION(mbas_setint)
  2.   DIM AS mb_value_t mbval;
  3.   DIM AS int usrval;
  4.   DIM AS const char PTR varname;
  5.   besARGUMENTS("zi")
  6.     AT varname, AT usrval
  7.   besARGEND
  8.   mbval.type = MB_DT_INT;
  9.   mbval.value.integer = usrval;
  10.   printf("0x%08x, 0x%08x\n", bas, varname);
  11.   besRETURN_LONG(mb_debug_set(bas, varname, mbval));
  12. besEND
  13.  
  14. besFUNCTION(mbas_setdbl)
  15.   DIM AS mb_value_t mbval;
  16.   DIM AS double usrval;
  17.   DIM AS const char PTR varname;
  18.   besARGUMENTS("zr")
  19.     AT varname, AT usrval
  20.   besARGEND
  21.   mbval.type = MB_DT_REAL;
  22.   mbval.value.float_point = usrval;
  23.   printf("0x%08x, 0x%08x\n", bas, varname);
  24.   besRETURN_LONG(mb_debug_set(bas, varname, mbval));
  25. besEND
  26.  
Title: Re: MY-BASIC
Post by: wangrenxin on April 24, 2015, 12:31:40 AM
No luck with your change to fix the Windows mb_setstr() function. Here is my change to the function per your suggestion.

Code: C
  1. besFUNCTION(mbas_setstr)
  2.   DIM AS mb_value_t mbval;
  3.   DIM AS const char PTR usrval;
  4.   DIM AS const char PTR varname;
  5.   besARGUMENTS("zz")
  6.     AT varname, AT usrval
  7.   besARGEND
  8.   mbval.type = MB_DT_STRING;
  9.   usrval = mb_memdup(usrval, strlen(usrval) + 1);
  10.   mbval.value.string = usrval;
  11.   besRETURN_LONG(mb_debug_set(bas, varname, mbval));
  12. besEND
  13.  


C:\sb22\mybasic>scriba mbvarset.sb
Got Here
Assertion failed: 0 && "Memory already released", file my_basic.c, line 3889

This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.

C:\sb22\mybasic>


Have you updated to latest revision including a change:
Code: C
  1. int mb_run(struct mb_interpreter_t* s) {
  2.         /* Run loaded and parsed script */
  3.         int result = MB_FUNC_OK;
  4.         _ls_node_t* ast = 0;
  5.         _running_context_t* running = 0;
  6.  
  7.         running = s->running_context;
  8.  
  9.         if(s->parsing_context)                <- added this line!!!
  10.                 safe_free(s->parsing_context);
  11.         ...
  12.  
Title: Re: MY-BASIC
Post by: John on April 24, 2015, 12:54:30 AM
I have no clue why the varname isn't being passed.  :o

Code: C
  1. besFUNCTION(mbas_setint)
  2.   DIM AS mb_value_t mbval;
  3.   DIM AS int usrval;
  4.   DIM AS const char PTR varname;
  5.   besARGUMENTS("zi")
  6.     AT varname, AT usrval
  7.   besARGEND
  8.   mbval.type = MB_DT_INT;
  9.   printf("|%s|\n", varname);
  10.   printf("0x%08x, 0x%08x\n", bas, varname);
  11.   mbval.value.integer = usrval;
  12.   besRETURN_LONG(mb_debug_set(bas, varname, mbval));
  13. besEND
  14.  


jrs@laptop:~/sb/sb22/mybasic$ scriba mbvars.sb
|(null)|
0x00820808, 0x00000000
scriba: my_basic.c:3977: mb_debug_set: Assertion `s && n' failed.
Aborted (core dumped)
jrs@laptop:~/sb/sb22/mybasic$


I'll redownload your code but I have to figure out why the varname isn't being passed in the m_setxxx but works fine with the mb_getxxx routines. I can't see anything obvious.

Title: Re: MY-BASIC
Post by: wangrenxin on April 24, 2015, 01:16:47 AM
Seems like something wrong in besARGUMENTS. It's defined in your attachment as:
Code: C
  1. #define besARGUMENTS(X) int iError; iError = pSt->basext_GetArgsF(pSt,pParameters,(X),
  2. #define besARGEND ); if( iError )return iError;
  3.  
So there might be some clue in basext_GetArgsF if you step into it to see where does the char* become NULL.
Title: Re: MY-BASIC
Post by: John on April 24, 2015, 01:22:34 AM
I'm passing varname the same way in mb_getxxx and it works fine.

Title: Re: MY-BASIC
Post by: John on April 24, 2015, 01:40:19 AM
There seems to be a bug in SB using the "zi" combo. If I reverse them it works.  >:(
Title: Re: MY-BASIC
Post by: wangrenxin on April 24, 2015, 01:48:51 AM
There seems to be a bug in SB using the "zi" combo. If I reverse them it works.  >:(

Unusual indeed.
Title: Re: MY-BASIC
Post by: John on April 24, 2015, 02:06:33 AM
This method (macro) also has a 5 argument limit. I'll go back to the old way which has a few more steps but rock solid.
Title: Re: MY-BASIC
Post by: John on April 24, 2015, 11:53:34 AM
Success!

Linux 64 (mb.so) and Window 32 (mb.dll) versions of the MY-BASIC Script BASIC extension module is attached.

interface.c
Code: C
  1. // MY-BASIC - Script BASIC extension module
  2.  
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <stdarg.h>
  7. #include <ctype.h>
  8. #include <math.h>
  9. #include <time.h>
  10. #include "../../basext.h"
  11. #include "cbasic.h"
  12.  
  13. #include "my_basic.h"
  14.  
  15.  
  16. /****************************
  17.  Extension Module Functions
  18. ****************************/
  19.  
  20. besVERSION_NEGOTIATE
  21.   RETURN_FUNCTION((int)INTERFACE_VERSION);
  22. besEND
  23.  
  24. besSUB_START
  25.   DIM AS long PTR p;
  26.   besMODULEPOINTER = besALLOC(sizeof(long));
  27.   IF (besMODULEPOINTER EQ NULL) THEN_DO RETURN_FUNCTION(0);
  28.   p = (long PTR)besMODULEPOINTER;
  29.   RETURN_FUNCTION(0);
  30. besEND
  31.  
  32. besSUB_FINISH
  33.   DIM AS long PTR p;
  34.   p = (long PTR)besMODULEPOINTER;
  35.   IF (p EQ NULL) THEN_DO RETURN_FUNCTION(0);
  36.   RETURN_FUNCTION(0);
  37. besEND
  38.  
  39.  
  40. /********************
  41.  MY-BASIC Functions
  42. ********************/
  43.  
  44. static struct mb_interpreter_t* bas = 0;
  45.  
  46. static int watch(struct mb_interpreter_t* s, void** l) {
  47.   int result = MB_FUNC_OK;
  48.   int_t arg = 0;
  49.   mb_assert(s && l);
  50.   mb_check(mb_attempt_open_bracket(s, l));
  51.   mb_check(mb_pop_int(s, l, &arg)); // That's it!
  52.   mb_check(mb_attempt_close_bracket(s, l));
  53.   // arg is what you want.
  54.   return result;
  55. }
  56.  
  57. besFUNCTION(mbas_init)
  58.   besRETURN_LONG(mb_init());
  59. besEND
  60.  
  61. besFUNCTION(mbas_dispose)
  62.   besRETURN_LONG(mb_dispose());
  63. besEND
  64.  
  65. besFUNCTION(mbas_open)
  66.   besRETURN_LONG(mb_open(AT bas));
  67. besEND
  68.  
  69. besFUNCTION(mbas_close)
  70.   besRETURN_LONG(mb_close(AT bas));
  71. besEND
  72.  
  73. besFUNCTION(mbas_load_str)
  74.   DIM AS const char PTR pgm;
  75.   besARGUMENTS("z")
  76.     AT pgm
  77.   besARGEND
  78.   besRETURN_LONG(mb_load_string(bas, pgm));
  79. besEND
  80.  
  81. besFUNCTION(mbas_load_file)
  82.   DIM AS const char PTR pgm;
  83.   besARGUMENTS("z")
  84.     AT pgm
  85.   besARGEND
  86.   besRETURN_LONG(mb_load_file(bas, pgm));
  87. besEND
  88.  
  89. besFUNCTION(mbas_run)
  90.   besRETURN_LONG(mb_run(bas));
  91. besEND
  92.  
  93. besFUNCTION(mbas_reset)
  94.   besRETURN_LONG(mb_reset(bas, false));
  95. besEND
  96.  
  97. besFUNCTION(mbas_getint)
  98.   DIM AS mb_value_t mbval;
  99.   DIM AS const char PTR varname;
  100.   besARGUMENTS("z")
  101.     AT varname
  102.   besARGEND
  103.   mbval.type = MB_DT_INT;
  104.   mb_debug_get(bas, varname, &mbval);
  105.   besRETURN_LONG(mbval.value.integer);
  106. besEND
  107.  
  108. besFUNCTION(mbas_getdbl)
  109.   DIM AS mb_value_t mbval;
  110.   DIM AS const char PTR varname;
  111.   besARGUMENTS("z")
  112.     AT varname
  113.   besARGEND
  114.   mbval.type = MB_DT_REAL;
  115.   mb_debug_get(bas, varname, &mbval);
  116.   besRETURN_DOUBLE(mbval.value.float_point);
  117. besEND
  118.  
  119. besFUNCTION(mbas_getstr)
  120.   DIM AS mb_value_t mbval;
  121.   DIM AS const char PTR varname;
  122.   besARGUMENTS("z")
  123.     AT varname
  124.   besARGEND
  125.   mbval.type = MB_DT_STRING;
  126.   mb_debug_get(bas, varname, &mbval);
  127.   besRETURN_STRING(mbval.value.string);
  128. besEND
  129.  
  130. besFUNCTION(mbas_setint)
  131.   DIM AS VARIABLE Argument;
  132.   DIM AS mb_value_t mbval;
  133.   DIM AS int usrval, i, rtnval;
  134.   DIM AS const char PTR varname;
  135.   IF (besARGNR < 2) THEN_DO RETURN_FUNCTION(EX_ERROR_TOO_FEW_ARGUMENTS);
  136.   DEF_FOR (i = 1 TO i <= 2 STEP INCR i)
  137.   BEGIN_FOR
  138.     Argument = besARGUMENT(i);
  139.     besDEREFERENCE(Argument);
  140.     IF (i EQ 1) THEN_DO varname = STRINGVALUE(Argument);
  141.     IF (i EQ 2) THEN_DO usrval = LONGVALUE(Argument);
  142.   NEXT
  143.   mbval.type = MB_DT_INT;
  144.   mbval.value.integer = usrval;
  145.   rtnval = mb_debug_set(bas, varname, mbval);
  146.   besRETURN_LONG(rtnval);
  147. besEND
  148.  
  149. besFUNCTION(mbas_setdbl)
  150.   DIM AS VARIABLE Argument;
  151.   DIM AS mb_value_t mbval;
  152.   DIM AS int i, rtnval;
  153.   DIM AS double usrval;
  154.   DIM AS const char PTR varname;
  155.   IF (besARGNR < 2) THEN_DO RETURN_FUNCTION(EX_ERROR_TOO_FEW_ARGUMENTS);
  156.   DEF_FOR (i = 1 TO i <= 2 STEP INCR i)
  157.   BEGIN_FOR
  158.     Argument = besARGUMENT(i);
  159.     besDEREFERENCE(Argument);
  160.     IF (i EQ 1) THEN_DO varname = STRINGVALUE(Argument);
  161.     IF (i EQ 2) THEN_DO usrval = DOUBLEVALUE(Argument);
  162.   NEXT
  163.   mbval.type = MB_DT_REAL;
  164.   mbval.value.float_point = usrval;
  165.   rtnval = mb_debug_set(bas, varname, mbval);
  166.   besRETURN_LONG(rtnval);
  167. besEND
  168.  
  169. besFUNCTION(mbas_setstr)
  170.   DIM AS VARIABLE Argument;
  171.   DIM AS mb_value_t mbval;
  172.   DIM AS int i, rtnval;
  173.   DIM AS const char PTR varname;
  174.   DIM AS const char PTR usrval;
  175.   IF (besARGNR < 2) THEN_DO RETURN_FUNCTION(EX_ERROR_TOO_FEW_ARGUMENTS);
  176.   DEF_FOR (i = 1 TO i <= 2 STEP INCR i)
  177.   BEGIN_FOR
  178.     Argument = besARGUMENT(i);
  179.     besDEREFERENCE(Argument);
  180.     IF (i EQ 1) THEN_DO varname = STRINGVALUE(Argument);
  181.     IF (i EQ 2) THEN_DO usrval = STRINGVALUE(Argument);
  182.   NEXT
  183.   mbval.type = MB_DT_STRING;
  184.   usrval = mb_memdup(usrval, strlen(usrval) + 1);
  185.   mbval.value.string = usrval;
  186.   besRETURN_LONG(mb_debug_set(bas, varname, mbval));
  187. besEND
  188.  

mbvars.sb
Code: ScriptBasic
  1. DECLARE SUB mb_init ALIAS "mbas_init" LIB "mb"
  2. DECLARE SUB mb_dispose ALIAS "mbas_dispose" LIB "mb"
  3. DECLARE SUB mb_open ALIAS "mbas_open" LIB "mb"
  4. DECLARE SUB mb_close ALIAS "mbas_close" LIB "mb"
  5. DECLARE SUB mb_load_str ALIAS "mbas_load_str" LIB "mb"
  6. DECLARE SUB mb_load_file ALIAS "mbas_load_file" LIB "mb"
  7. DECLARE SUB mb_run ALIAS "mbas_run" LIB "mb"
  8. DECLARE SUB mb_getint ALIAS "mbas_getint" LIB "mb"
  9. DECLARE SUB mb_getdbl ALIAS "mbas_getdbl" LIB "mb"
  10. DECLARE SUB mb_getstr ALIAS "mbas_getstr" LIB "mb"
  11. DECLARE SUB mb_setint ALIAS "mbas_setint" LIB "mb"
  12. DECLARE SUB mb_setdbl ALIAS "mbas_setdbl" LIB "mb"
  13. DECLARE SUB mb_setstr ALIAS "mbas_setstr" LIB "mb"
  14. DECLARE SUB mb_reset ALIAS "mbas_reset" LIB "mb"
  15.  
  16. mb_init
  17. mb_open
  18. mb_load_file "setvars.bas"
  19. mb_run
  20. mb_setint "A", 123
  21. mb_setdbl "B", 1.23
  22. mb_setstr "C$", "One,Two,Three"
  23. PRINT mb_getint("A"),"\n"
  24. PRINT FORMAT("%g\n", mb_getdbl("B"))
  25. PRINT mb_getstr("C$"),"\n"
  26. mb_close
  27. mb_dispose
  28.  

setvars.bas
Code: [Select]
a = 0
b = 0.0
c$ = ""

Output - Linux 64 bit

jrs@laptop:~/sb/sb22/mybasic$ time scriba mbvars.sb
123
1.23
One,Two,Three

real   0m0.006s
user   0m0.005s
sys   0m0.005s
jrs@laptop:~/sb/sb22/mybasic$


Output - Windows 32 bit

C:\sb22\mybasic>scriba mbvars.sb
123
1.23
One,Two,Three

C:\sb22\mybasic>

Title: Re: MY-BASIC
Post by: John on April 24, 2015, 03:04:58 PM
Tony,

Can you export a function like LIST but the return value would be a multi-line string version of the the program? If we had this ability, one could retrieve the current program into a SB string, mb_reset the MY-BASIC workspace and mb_load_str an edited version of the script.

Code: C
  1. static void _list_program(const char* sn, const char* cn) {
  2.         long lsn = 0;
  3.         long lcn = 0;
  4.         mb_assert(sn && cn);
  5.         lsn = atoi(sn);
  6.         lcn = atoi(cn);
  7.         if(lsn == 0 && lcn == 0) {
  8.                 long i = 0;
  9.                 for(i = 0; i < c->count; ++i) {
  10.                         printf("%d]%s\n", i + 1, c->lines[i]);
  11.                 }
  12.         } else {
  13.                 long i = 0;
  14.                 long e = 0;
  15.                 if(lsn < 1 || lsn > c->count) {
  16.                         printf("Line number %ld out of bound.\n", lsn);
  17.  
  18.                         return;
  19.                 }
  20.                 if(lcn < 0) {
  21.                         printf("Invalid line count %ld.\n", lcn);
  22.  
  23.                         return;
  24.                 }
  25.                 --lsn;
  26.                 e = lcn ? lsn + lcn : c->count;
  27.                 for(i = lsn; i < e; ++i) {
  28.                         if(i >= c->count)
  29.                                 break;
  30.  
  31.                         printf("%d]%s\n", i + 1, c->lines[i]);
  32.                 }
  33.         }
  34. }
  35.  
Title: Re: MY-BASIC
Post by: wangrenxin on April 24, 2015, 10:54:26 PM
Can you export a function like LIST but the return value would be a multi-line string version of the the program? If we had this ability, one could retrieve the current program into a SB string, mb_reset the MY-BASIC workspace and mb_load_str an edited version of the script.

_get_code is exactly what you are looking for. Note you need to free the return value if it's no longer in use.
Title: Re: MY-BASIC
Post by: John on April 25, 2015, 01:04:30 AM
There is no _get_code in the my_basic.h, my_basic.c or a dump of the shared object.

Code: [Select]
jrs@laptop:~/sb/sb22/modules$ nm mb.so
                 U acosf@@GLIBC_2.2.5
0000000000006f10 t _append_char_to_symbol
                 U asinf@@GLIBC_2.2.5
                 U __assert_fail
                 U atanf@@GLIBC_2.2.5
0000000000214940 b bas
0000000000003010 T bootmodu
0000000000214938 B __bss_start
0000000000214960 b buf.6267
0000000000009340 t _calc_expression
                 U ceilf@@GLIBC_2.2.5
0000000000006fc0 t _clear_array
0000000000003a20 t _compare_numbers
00000000000079a0 t _core_add
0000000000003de0 t _core_and
0000000000003fe0 t _core_close_bracket
000000000000bb30 t _core_dim
0000000000004ef0 t _core_div
000000000000ac40 t _core_do
0000000000003930 t _core_dummy_assign
0000000000003b60 t _core_else
0000000000003b90 t _core_elseif
0000000000004910 t _core_end
0000000000003b30 t _core_endif
0000000000006a40 t _core_equal
0000000000005440 t _core_exit
000000000000b0c0 t _core_for
0000000000007d80 t _core_gosub
00000000000052f0 t _core_goto
0000000000006390 t _core_greater
0000000000005cd0 t _core_greater_equal
000000000000b630 t _core_if
00000000000066f0 t _core_less
0000000000006030 t _core_less_equal
000000000000a5a0 t _core_let
00000000002141a0 d _core_libs
000000000000e8d0 t _core_mem
00000000000041e0 t _core_min
0000000000004be0 t _core_mod
0000000000004040 t _core_mul
000000000000d7b0 t _core_neg
0000000000006df0 t _core_next
000000000000e950 t _core_not
0000000000005990 t _core_not_equal
0000000000004010 t _core_open_bracket
0000000000003bf0 t _core_or
00000000000043a0 t _core_pow
0000000000007250 t _core_return
00000000000039c0 t _core_step
0000000000003bc0 t _core_then
00000000000039f0 t _core_to
0000000000003960 t _core_until
0000000000003990 t _core_wend
000000000000af00 t _core_while
                 U cosf@@GLIBC_2.2.5
                 U __ctype_b_loc
                 U __ctype_toupper_loc
0000000000007fe0 t _cut_symbol
00000000000076c0 t _destroy_object
0000000000007700 t _destroy_object_non_syntax
00000000000073b0 t _dispose_object
0000000000214598 d _DYNAMIC
0000000000214938 D _edata
00000000002149a0 B _end
0000000000214420 d _ERR_DESC
000000000000a9b0 t _execute_statement
                 U exit
0000000000214988 b _exp_assign
                 U exp@@GLIBC_2.2.5
0000000000005930 t _extract_string
                 U fclose
                 U fgets
0000000000003030 T finimodu
                 U floorf@@GLIBC_2.2.5
                 U fopen
                 U fread
                 U free
                 U fseek
                 U ftell
                 U fwrite
0000000000008fd0 t _get_array_index
0000000000002eb0 t _get_inputer.part.23
0000000000002ed0 t _get_printer.part.24
0000000000005660 t _get_priority_index
0000000000005480 t _get_size_of.part.11
0000000000214728 d _GLOBAL_OFFSET_TABLE_
0000000000007340 t _ht_clear
0000000000003910 t _ht_cmp_int
0000000000004380 t _ht_cmp_string
0000000000008ee0 t _ht_create.constprop.74
00000000000078a0 t _ht_destroy
0000000000005270 t _ht_find
0000000000007800 t _ht_foreach
00000000000048e0 t _ht_hash_int
0000000000004890 t _ht_hash_string
0000000000007de0 t _ht_set_or_insert
0000000000006e50 t _internal_object_to_public_value
00000000000054e0 t _is_expression_terminal
0000000000004700 t _is_flow
0000000000004810 t _is_identifier_char
0000000000004600 t _is_operator
0000000000004850 t _is_operator_char
00000000000058d0 t _is_string
                 U logf@@GLIBC_2.2.5
00000000000072e0 t _ls_clear
00000000000038f0 t _ls_cmp_data
0000000000003900 t _ls_cmp_extra
0000000000004390 t _ls_cmp_extra_string
0000000000007ce0 t _ls_create_node
0000000000007860 t _ls_destroy
0000000000002e90 t _ls_empty.part.22
0000000000007760 t _ls_foreach
0000000000007190 t _ls_free_extra
00000000000071d0 t _ls_popback
0000000000007d30 t _ls_pushback
00000000000070b0 t _ls_try_remove
0000000000002ef0 T ltrim
                 U malloc
0000000000214980 b _mb_allocated
0000000000003130 T mbas_close
0000000000003090 T mbas_dispose
00000000000033c0 T mbas_getdbl
0000000000003320 T mbas_getint
0000000000003460 T mbas_getstr
0000000000003040 T mbas_init
0000000000003200 T mbas_load_file
0000000000003180 T mbas_load_str
00000000000030e0 T mbas_open
00000000000032d0 T mbas_reset
0000000000003280 T mbas_run
0000000000003660 T mbas_setdbl
0000000000003530 T mbas_setint
00000000000037a0 T mbas_setstr
000000000000d280 T mb_attempt_close_bracket
000000000000ce10 T mb_attempt_func_begin
000000000000cea0 T mb_attempt_func_end
000000000000d1e0 T mb_attempt_open_bracket
000000000000c940 T mb_close
000000000000f820 T mb_debug_get
000000000000f8f0 T mb_debug_set
000000000000f980 T mb_debug_set_stepped_handler
000000000000c340 T mb_dispose
000000000000bfd0 T mb_dispose_value
0000000000006f80 t mb_free
000000000000f9e0 T mb_get_error_desc
000000000000f9b0 T mb_get_last_error
00000000000045a0 T mb_gets
000000000000d350 T mb_has_arg
000000000000c090 T mb_init
000000000000fbf0 T mb_load_file
000000000000fa20 T mb_load_string
0000000000007950 t mb_malloc
000000000000ff60 T mb_memdup
000000000000c5f0 T mb_open
000000000000d580 T mb_pop_int
000000000000d600 T mb_pop_real
000000000000d680 T mb_pop_string
000000000000d6f0 T mb_pop_usertype
000000000000d3c0 T mb_pop_value
000000000000e870 T mb_push_int
000000000000f120 T mb_push_real
000000000000f220 T mb_push_string
000000000000f770 T mb_push_usertype
000000000000d760 T mb_push_value
000000000000cde0 T mb_register_func
000000000000cdf0 T mb_remove_func
000000000000ce00 T mb_remove_reserved_func
000000000000cb40 T mb_reset
000000000000fd20 T mb_run
000000000000fed0 T mb_set_error_handler
000000000000ff30 T mb_set_inputer
000000000000ff00 T mb_set_printer
0000000000004560 t mb_strupr
000000000000f7d0 T mb_suspend
000000000000c020 T mb_ver
000000000000c030 T mb_ver_string
                 U memcpy
                 U memmove
                 U memset
0000000000214990 b _OBJ_BOOL_FALSE
0000000000214998 b _OBJ_BOOL_TRUE
0000000000011550 r _OBJ_INT_ZERO
0000000000007e80 t _open_constant
0000000000008940 t _parse_char
                 U pow@@GLIBC_2.2.5
00000000000113e0 r _PRECEDE_TABLE
0000000000011320 r __PRETTY_FUNCTION__.5458
00000000000112a7 r __PRETTY_FUNCTION__.5473
00000000000112e3 r __PRETTY_FUNCTION__.5479
000000000001109e r __PRETTY_FUNCTION__.5488
0000000000011056 r __PRETTY_FUNCTION__.5499
0000000000010ec4 r __PRETTY_FUNCTION__.5507
00000000000110cb r __PRETTY_FUNCTION__.5512
000000000001104a r __PRETTY_FUNCTION__.5519
0000000000011350 r __PRETTY_FUNCTION__.5525
0000000000011340 r __PRETTY_FUNCTION__.5534
0000000000011330 r __PRETTY_FUNCTION__.5545
0000000000011293 r __PRETTY_FUNCTION__.5588
0000000000010e30 r __PRETTY_FUNCTION__.5600
0000000000010cb0 r __PRETTY_FUNCTION__.5609
0000000000010c66 r __PRETTY_FUNCTION__.5624
0000000000010c90 r __PRETTY_FUNCTION__.5632
0000000000011372 r __PRETTY_FUNCTION__.5641
000000000001139b r __PRETTY_FUNCTION__.5645
0000000000011114 r __PRETTY_FUNCTION__.5681
0000000000011100 r __PRETTY_FUNCTION__.5686
00000000000110e0 r __PRETTY_FUNCTION__.5698
00000000000111b0 r __PRETTY_FUNCTION__.5704
0000000000011240 r __PRETTY_FUNCTION__.5733
0000000000010de0 r __PRETTY_FUNCTION__.5780
00000000000112d0 r __PRETTY_FUNCTION__.5785
0000000000010dd2 r __PRETTY_FUNCTION__.5789
0000000000010dfe r __PRETTY_FUNCTION__.5793
0000000000010ab0 r __PRETTY_FUNCTION__.5824
0000000000010aff r __PRETTY_FUNCTION__.5836
0000000000010af0 r __PRETTY_FUNCTION__.5851
0000000000010ae1 r __PRETTY_FUNCTION__.5875
0000000000010ad0 r __PRETTY_FUNCTION__.5907
0000000000010b0b r __PRETTY_FUNCTION__.5937
00000000000112c0 r __PRETTY_FUNCTION__.5945
00000000000111e6 r __PRETTY_FUNCTION__.5950
0000000000011180 r __PRETTY_FUNCTION__.5957
0000000000011190 r __PRETTY_FUNCTION__.5972
0000000000011170 r __PRETTY_FUNCTION__.5988
0000000000010f70 r __PRETTY_FUNCTION__.6000
0000000000010f8a r __PRETTY_FUNCTION__.6006
00000000000111f3 r __PRETTY_FUNCTION__.6015
0000000000011200 r __PRETTY_FUNCTION__.6022
00000000000110c0 r __PRETTY_FUNCTION__.6028
00000000000110b0 r __PRETTY_FUNCTION__.6033
0000000000011210 r __PRETTY_FUNCTION__.6044
0000000000011070 r __PRETTY_FUNCTION__.6065
0000000000011220 r __PRETTY_FUNCTION__.6073
00000000000111d0 r __PRETTY_FUNCTION__.6080
0000000000010ff0 r __PRETTY_FUNCTION__.6086
0000000000011140 r __PRETTY_FUNCTION__.6092
0000000000010b80 r __PRETTY_FUNCTION__.6104
0000000000011080 r __PRETTY_FUNCTION__.6118
0000000000011260 r __PRETTY_FUNCTION__.6134
0000000000011041 r __PRETTY_FUNCTION__.6154
0000000000010fa0 r __PRETTY_FUNCTION__.6166
0000000000011251 r __PRETTY_FUNCTION__.6181
0000000000010e42 r __PRETTY_FUNCTION__.6195
0000000000010cbb r __PRETTY_FUNCTION__.6206
0000000000010ce0 r __PRETTY_FUNCTION__.6213
0000000000010c80 r __PRETTY_FUNCTION__.6218
0000000000011310 r __PRETTY_FUNCTION__.6224
0000000000010ca0 r __PRETTY_FUNCTION__.6233
0000000000010e16 r __PRETTY_FUNCTION__.6242
0000000000010cc8 r __PRETTY_FUNCTION__.6251
00000000000113b0 r __PRETTY_FUNCTION__.6260
0000000000011393 r __PRETTY_FUNCTION__.6272
0000000000011367 r __PRETTY_FUNCTION__.6277
000000000001135f r __PRETTY_FUNCTION__.6287
0000000000010cd7 r __PRETTY_FUNCTION__.6297
0000000000010c70 r __PRETTY_FUNCTION__.6307
0000000000010c50 r __PRETTY_FUNCTION__.6329
0000000000010c30 r __PRETTY_FUNCTION__.6337
0000000000010c10 r __PRETTY_FUNCTION__.6345
0000000000010bf0 r __PRETTY_FUNCTION__.6354
0000000000010be5 r __PRETTY_FUNCTION__.6363
0000000000010bda r __PRETTY_FUNCTION__.6372
0000000000010bce r __PRETTY_FUNCTION__.6387
0000000000010bc0 r __PRETTY_FUNCTION__.6402
0000000000010bb0 r __PRETTY_FUNCTION__.6416
0000000000010ba1 r __PRETTY_FUNCTION__.6433
0000000000010b6d r __PRETTY_FUNCTION__.6442
0000000000010b60 r __PRETTY_FUNCTION__.6451
0000000000010b51 r __PRETTY_FUNCTION__.6460
0000000000010b40 r __PRETTY_FUNCTION__.6469
0000000000010b26 r __PRETTY_FUNCTION__.6478
0000000000010b17 r __PRETTY_FUNCTION__.6493
0000000000010a99 r __PRETTY_FUNCTION__.6508
0000000000010a92 r __PRETTY_FUNCTION__.6516
0000000000010a87 r __PRETTY_FUNCTION__.6526
0000000000010a7a r __PRETTY_FUNCTION__.6536
0000000000010a6d r __PRETTY_FUNCTION__.6545
0000000000010a50 r __PRETTY_FUNCTION__.6551
0000000000010a30 r __PRETTY_FUNCTION__.6556
0000000000010a10 r __PRETTY_FUNCTION__.6560
00000000000109f0 r __PRETTY_FUNCTION__.6566
00000000000109df r __PRETTY_FUNCTION__.6572
00000000000109d0 r __PRETTY_FUNCTION__.6578
0000000000011380 r __PRETTY_FUNCTION__.6594
0000000000010e51 r __PRETTY_FUNCTION__.6601
0000000000010e5b r __PRETTY_FUNCTION__.6620
0000000000010e65 r __PRETTY_FUNCTION__.6632
0000000000010e6f r __PRETTY_FUNCTION__.6644
0000000000010e79 r __PRETTY_FUNCTION__.6663
0000000000010e83 r __PRETTY_FUNCTION__.6682
0000000000010e90 r __PRETTY_FUNCTION__.6694
0000000000010eb0 r __PRETTY_FUNCTION__.6701
0000000000010ece r __PRETTY_FUNCTION__.6711
0000000000010ed8 r __PRETTY_FUNCTION__.6727
0000000000010ee4 r __PRETTY_FUNCTION__.6757
0000000000010eef r __PRETTY_FUNCTION__.6788
0000000000010f00 r __PRETTY_FUNCTION__.6819
0000000000010f20 r __PRETTY_FUNCTION__.6850
0000000000010f40 r __PRETTY_FUNCTION__.6881
0000000000010f50 r __PRETTY_FUNCTION__.6910
0000000000010f5a r __PRETTY_FUNCTION__.6922
0000000000010f63 r __PRETTY_FUNCTION__.6935
0000000000010f80 r __PRETTY_FUNCTION__.6955
0000000000010f96 r __PRETTY_FUNCTION__.6983
0000000000010faf r __PRETTY_FUNCTION__.6998
0000000000010fb8 r __PRETTY_FUNCTION__.7013
0000000000010fc3 r __PRETTY_FUNCTION__.7020
0000000000010fd0 r __PRETTY_FUNCTION__.7027
0000000000010fdb r __PRETTY_FUNCTION__.7034
0000000000011001 r __PRETTY_FUNCTION__.7052
000000000001100b r __PRETTY_FUNCTION__.7069
0000000000011014 r __PRETTY_FUNCTION__.7076
000000000001101f r __PRETTY_FUNCTION__.7086
000000000001102a r __PRETTY_FUNCTION__.7097
0000000000011036 r __PRETTY_FUNCTION__.7108
0000000000011273 r __PRETTY_FUNCTION__.7120
000000000001127c r __PRETTY_FUNCTION__.7131
0000000000011288 r __PRETTY_FUNCTION__.7138
000000000001129c r __PRETTY_FUNCTION__.7148
00000000000112b4 r __PRETTY_FUNCTION__.7157
00000000000112ef r __PRETTY_FUNCTION__.7165
00000000000112fc r __PRETTY_FUNCTION__.7172
0000000000011306 r __PRETTY_FUNCTION__.7181
0000000000010cef r __PRETTY_FUNCTION__.7188
0000000000010cf8 r __PRETTY_FUNCTION__.7204
0000000000010d01 r __PRETTY_FUNCTION__.7220
0000000000010d0a r __PRETTY_FUNCTION__.7236
0000000000010d15 r __PRETTY_FUNCTION__.7252
0000000000010d1f r __PRETTY_FUNCTION__.7268
0000000000010d28 r __PRETTY_FUNCTION__.7284
0000000000010d33 r __PRETTY_FUNCTION__.7300
0000000000010d3c r __PRETTY_FUNCTION__.7310
0000000000010d45 r __PRETTY_FUNCTION__.7326
0000000000010d4e r __PRETTY_FUNCTION__.7342
0000000000010d57 r __PRETTY_FUNCTION__.7358
0000000000010d61 r __PRETTY_FUNCTION__.7374
0000000000010d6b r __PRETTY_FUNCTION__.7390
0000000000010d75 r __PRETTY_FUNCTION__.7406
0000000000010d7e r __PRETTY_FUNCTION__.7422
0000000000010d87 r __PRETTY_FUNCTION__.7438
0000000000010d90 r __PRETTY_FUNCTION__.7451
0000000000010d99 r __PRETTY_FUNCTION__.7464
0000000000010da3 r __PRETTY_FUNCTION__.7477
0000000000010dac r __PRETTY_FUNCTION__.7491
0000000000010db5 r __PRETTY_FUNCTION__.7507
0000000000010dc0 r __PRETTY_FUNCTION__.7521
0000000000010dc9 r __PRETTY_FUNCTION__.7535
0000000000010df3 r __PRETTY_FUNCTION__.7552
0000000000010e0b r __PRETTY_FUNCTION__.7574
                 U printf
00000000000055a0 t _public_value_to_internal_object
                 U rand
0000000000007f20 t _register_func
0000000000008da0 t _remove_func
00000000000054b0 t _remove_source_object
0000000000002f50 T rtrim
0000000000004950 t _set_current_error
0000000000002e70 t _set_error_pos.part.8
                 U sinf@@GLIBC_2.2.5
0000000000004990 t _skip_struct
0000000000004ad0 t _skip_to
                 U __sprintf_chk
                 U sqrtf@@GLIBC_2.2.5
                 U __stack_chk_fail
000000000000e710 t _std_abs
000000000000deb0 t _std_acos
000000000000eaa0 t _std_asc
000000000000e010 t _std_asin
000000000000dd50 t _std_atan
000000000000ed80 t _std_ceil
000000000000f6d0 t _std_chr
000000000000e2d0 t _std_cos
                 U stderr
000000000000dbd0 t _std_exp
000000000000ec60 t _std_fix
000000000000eea0 t _std_floor
                 U stdin
000000000000cee0 t _std_input
000000000000f5f0 t _std_left
000000000000ea10 t _std_len
0000000000214000 d _std_libs
000000000000da70 t _std_log
000000000000f4a0 t _std_mid
000000000000a0e0 t _std_print
000000000000f3a0 t _std_right
000000000000f180 t _std_rnd
000000000000eb30 t _std_round
000000000000efc0 t _std_sgn
000000000000e430 t _std_sin
000000000000e590 t _std_sqr
000000000000f280 t _std_str
000000000000e170 t _std_tan
000000000000d960 t _std_val
                 U strcat
                 U strcmp
                 U strcpy
                 U strlen
                 U strtod
                 U strtol
                 U tanf@@GLIBC_2.2.5
0000000000002fe0 T trim
0000000000006da0 t _try_clear_intermediate_value.isra.19
0000000000008f60 t _try_get_value.constprop.75
0000000000003000 T versmodu
jrs@laptop:~/sb/sb22/modules$
Title: Re: MY-BASIC
Post by: wangrenxin on April 25, 2015, 02:47:31 AM
It's in main.c as well as _list_program.
Title: Re: MY-BASIC
Post by: John on April 25, 2015, 07:38:35 AM
It's in main.c as well as _list_program.

Can you make an exported - CORE version of this? The mb_assert() seems MIA if I try to use it.

Code: C
  1. static char* _get_code(_code_line_t* code) {
  2.         char* result = 0;
  3.         int i = 0;
  4.         mb_assert(code);
  5.         result = (char*)malloc((_MAX_LINE_LENGTH + 2) * code->count + 1);
  6.         result[0] = '\0';
  7.         for(i = 0; i < code->count; ++i) {
  8.                 result = strcat(result, code->lines[i]);
  9.                 if(i != code->count - 1)
  10.                         result = strcat(result, "\n");
  11.         }
  12.  
  13.         return result;
  14. }
  15.  

Title: Re: MY-BASIC
Post by: wangrenxin on April 25, 2015, 11:47:40 PM
Well, as you see, it's not a part of core, but a part of shell. The source code is only manipulatable at the shell layer, the core layer doesn't know what the source text is, it's not possible and doesn't make any sence to export _get_code only, the proper way to manipulate source code is maintain it yourself, maybe port some functions from main.c.
Title: Re: MY-BASIC
Post by: John on April 26, 2015, 12:10:50 AM
That makes sense. This means the posted binaries are the MY-BASIC Script BASIC extension modules for Windows 32 bit and Lunux (Ubuntu) 64 bit.

Thanks Tony for your help and additions to your code to make this a worth while adventure.

I'm glad to see Markus (http://forum.basicprogramming.org/index.php/topic,4855.0.html) (Cybermonkey) adding graphics primitives to My-BASIC. This might be a good project to generate a spark to ignite your Retro BASIC Gaming (http://retrogamecoding.org/board/index.php) forum/site. I would like to see MY-BASIC be the BASM (tutorial compiler) of interpreters.

(http://forum.basicprogramming.org/index.php?action=dlattach;topic=4855.0;attach=2337)

Code: [Select]
screen (512,512,"Fractal")

bx=0
by=0
bw=256*2
bh=256*2

sx=-2.2
sy=-1.7
sw=3.4
sh=3.4

cls

for x=bx to bx+bw
 for y=by to by+bh
   gx=(x-bx)/bw*sw+sx
   gy=(y-by)/bh*sh+sy
   zx=gx
   zy=gy
   for c=0 to 255
    col = c
    nzx=zx*zx - zy*zy + gx
    zy=2*zx*zy+gy
    zx=nzx
    if zx*zx + zy*zy > 4 then  col = c:  exit
  next
  r = col*256+col
  v = col*256+col*32
  b = col*256+col*64         
  ink (r,v,b)
  pset (x,y)
sync
 next
next

sync
do
sleep (15)
until keypressed=true
Title: Re: MY-BASIC
Post by: wangrenxin on April 26, 2015, 07:52:29 PM
Sounds great. I'll add a wiki page on linking with MY-BASIC as a lib later.

It seems guys at BP have made a lot of dedication with MB these days.
Title: Re: MY-BASIC
Post by: John on April 26, 2015, 07:56:49 PM
Markus is a smart guy and great programmer. I'm sure he will make you proud with his accomplishments.
Title: Re: MY-BASIC
Post by: wangrenxin on April 27, 2015, 12:11:59 AM
@John

See Link with MY-BASIC (https://github.com/paladin-t/my_basic/wiki/Link-with-MY_BASIC).
Title: Re: MY-BASIC
Post by: John on April 30, 2015, 03:08:27 PM
Here is an MY-BASIC / AllegroBASIC example from Markus (Cybermonkey) on the BP.org forum.

(http://forum.basicprogramming.org/index.php?action=dlattach;topic=4868.0;attach=2371;image)

Code: Text
  1. screen (800,600,"CircleTrap")
  2. KEY_ESC          = 59  
  3.  
  4. h = screenheight/2
  5. w = screenwidth/2
  6. paper (0,0,0)
  7. do
  8. cls
  9. t = tickcount/1000
  10. for i=1 to 360
  11.     ink (255-i,255,255)
  12.     circle (w+sin(i*90+t)*200,h+cos(i*90+t)*200,20+i)
  13. next
  14. sync
  15. sleep (12)
  16. until keystate (KEY_ESC) = true
  17. end
  18.  
Title: Re: MY-BASIC
Post by: Cybermonkey342 on May 01, 2015, 10:30:09 AM
Hi, I just registered ar Allbasic.info.
I think I can offer you a download of AllegroBASIC soon ... just have a little patience.
I just implemented loading and displaying bitmaps and sprites. (In Allegro4 a sprite is also a bitmap but the colour 255,0,255 isn't drawn).
Title: Re: MY-BASIC
Post by: John on May 01, 2015, 10:36:24 AM
Welcome Markus!

I'm glad you decided to join the rest of the BASIC developer that hang out here. I added you to the BASIC Developer's group so we are now a band of 13.

Looking forward to seeing the extension code you added to MY-BASIC. I'm hoping to pickup some tips for the SB SDL_gfx extension module.

John
Title: Re: MY-BASIC
Post by: wangrenxin on May 04, 2015, 01:40:08 AM
Welcome Markus!

Nice to hear that!

WRX.
Title: Re: MY-BASIC
Post by: John on May 17, 2015, 01:58:09 PM
Markus,

How are things going with AllegroBASIC? How about some news?  :)
Title: Re: MY-BASIC
Post by: wangrenxin on September 17, 2015, 12:46:52 AM
After several spare weekends passed, I'd be happy to tell you that MY-BASIC supports user defined sub routine now. A more elegant hello-world in MB is something like this:

Code: PHP
  1. def foo(a, b)
  2.     print a + " " + b;
  3. enddef
  4.  
  5. foo("Hello", "world!")
  6.  

Definitely you can return value in a sub routine as:
Code: PHP
  1. def bar(a, b)
  2.     return a + b
  3. enddef
  4.  
  5. c = bar(1, 2)
  6. print c
  7.  
Title: Re: MY-BASIC
Post by: John on September 17, 2015, 09:48:08 AM
Great news!

I would call them SUBs / FUNCTIONs rather than subroutines which in BASIC refers to a GOSUB routines.
Title: Re: MY-BASIC
Post by: Cybermonkey342 on September 17, 2015, 11:24:34 AM
Wow, that's great. i just made a new compile of AllegroBASIC and that works fine. I had not much time to code on that project since I am at the moment finalizing Pulsar2D. After that I might start over with AllegroBASIC again.

Oh, I found one issue: you can't assign real numbers to variables anymore. Is that intended? The following code fails e.g.:
Code: [Select]
pi = 3.141
The error tells something about an invalid character ...
Title: Re: MY-BASIC
Post by: John on September 17, 2015, 06:35:33 PM
I'm glad you haven't given up on AllegroBASIC. I plan to update the Script BASIC extension module of My-BASIC when you guys feel it's stable.

Title: Re: MY-BASIC
Post by: wangrenxin on September 17, 2015, 07:22:08 PM
Oh, I found one issue: you can't assign real numbers to variables anymore.
Quite a bug... Fixed in latest revision. Thanks for telling me.

I'm glad you haven't given up on AllegroBASIC. I plan to update the Script BASIC extension module of My-BASIC when you guys feel it's stable.
I believe it needs some time to test it and make this new feature robust. I plan to implement an OOP paradigm also, but won't start until exist mechanism stable, considering it takes about two years to decide to make sub routine (or function) from an idea... Keep going guys.
Title: Re: MY-BASIC
Post by: John on September 17, 2015, 09:53:43 PM
Thanks for the fix Tony and I'll generate a new set of share objects (SB ext. mod) of My-BASIC for folks to try.

Title: Re: MY-BASIC
Post by: John on September 18, 2015, 12:14:25 AM
Tony,

Your latest code seems to work for me. (Ubuntu 64 bit)

Code: ScriptBasic
  1. DECLARE SUB mb_init ALIAS "mbas_init" LIB "mb"
  2. DECLARE SUB mb_dispose ALIAS "mbas_dispose" LIB "mb"
  3. DECLARE SUB mb_open ALIAS "mbas_open" LIB "mb"
  4. DECLARE SUB mb_close ALIAS "mbas_close" LIB "mb"
  5. DECLARE SUB mb_load_str ALIAS "mbas_load_str" LIB "mb"
  6. DECLARE SUB mb_run ALIAS "mbas_run" LIB "mb"
  7.  
  8. mb_code = """
  9. def bar(a, b)
  10.    return a + b
  11. enddef
  12.  
  13. c = bar(1, 2.5)
  14. print c,"\n"
  15. """
  16. mb_init()
  17. mb_open()
  18. mb_load_str(mb_code)
  19. mb_run()
  20. mb_close()
  21. mb_dispose()
  22.  


jrs@laptop:~/sb/sb22/mybasic$ scriba testmb.sb
3.5
jrs@laptop:~/sb/sb22/mybasic$


Does your new subs & functions support recursive use?
Title: Re: MY-BASIC
Post by: wangrenxin on September 18, 2015, 01:11:38 AM
It's wonderful, John.
Title: Re: MY-BASIC
Post by: John on September 18, 2015, 02:23:50 AM
I'll give it a try running in a thread tomorrow.  8)
Title: Re: MY-BASIC
Post by: Cybermonkey342 on September 18, 2015, 08:24:52 AM
Oh, I found one issue: you can't assign real numbers to variables anymore.
Quite a bug... Fixed in latest revision. Thanks for telling me.

Thanks for fixing the bug. It works again as expected.
Title: Re: MY-BASIC
Post by: John on September 19, 2015, 08:55:34 PM
Tony,

I tried a simple SUB recursion test and it didn't work and segmentation faulted.

Code: [Select]
def plusone(a)
    if a <= 10 then
      a = a + 1
      print a, "\n"
      plusone(a)
    endif
enddef
 
plusone(1)

This works in Script BASIC.

Code: ScriptBasic
  1. sub plusone(a)
  2.   if a <= 10 then
  3.     a = a + 1
  4.     print a, "\n"
  5.     plusone(a)
  6.   end if
  7. end sub
  8.  
  9. plusone(1)
  10.  


jrs@laptop:~/sb/sb22/test$ scriba plusone.sb
2
3
4
5
6
7
8
9
10
11
jrs@laptop:~/sb/sb22/test$
Title: Re: MY-BASIC
Post by: wangrenxin on September 19, 2015, 11:04:35 PM
I tried a simple SUB recursion test and it didn't work and segmentation faulted.
I'll look over to fix it, and post it when it's done. Thanks for report.
Title: Re: MY-BASIC
Post by: wangrenxin on September 20, 2015, 06:41:42 AM
Hi John,

I've added recursive sub routine support in the latest revision.

Further more, I plan to implement tail recursion optimization later.
Title: Re: MY-BASIC
Post by: John on September 22, 2015, 06:38:52 PM
Seems to work. Have you also tested it with FUNCTIONs returning a value in a recursive mode?

Code: ScriptBasic
  1. DECLARE SUB mb_init ALIAS "mbas_init" LIB "mb"
  2. DECLARE SUB mb_dispose ALIAS "mbas_dispose" LIB "mb"
  3. DECLARE SUB mb_open ALIAS "mbas_open" LIB "mb"
  4. DECLARE SUB mb_close ALIAS "mbas_close" LIB "mb"
  5. DECLARE SUB mb_load_str ALIAS "mbas_load_str" LIB "mb"
  6. DECLARE SUB mb_run ALIAS "mbas_run" LIB "mb"
  7.  
  8. mb_code = """
  9. def plusone(a)
  10.    if a <= 10 then
  11.      a = a + 1
  12.      print a, "\n"
  13.      plusone(a)
  14.    endif
  15. enddef
  16.  
  17. plusone(1)
  18. """
  19. mb_init
  20. mb_open
  21. mb_load_str mb_code
  22. mb_run
  23. mb_close
  24. mb_dispose
  25.  
  26.  


jrs@laptop:~/sb/sb22/mybasic$ scriba mbrecur.sb
2
3
4
5
6
7
8
9
10
11
jrs@laptop:~/sb/sb22/mybasic$

Title: Re: MY-BASIC
Post by: wangrenxin on September 23, 2015, 10:33:25 PM
Seems to work. Have you also tested it with FUNCTIONs returning a value in a recursive mode?

I've fixed some bugs with sub routines in latest revision.

Now sub routines return a value in a recursive mode work fine, eg:

Code: ScriptBasic
  1. def fac(a)
  2.     if a = 0 then
  3.         return 1
  4.     endif
  5.  
  6.     return a * fac(a - 1)
  7. enddef
  8.  
  9. print fac(6);
  10.  
Title: Re: MY-BASIC
Post by: John on September 24, 2015, 12:52:07 AM
Tony,

No errors and I assume the value returned is correct. Can you show an example of CLASS/ENDCLASS? I couldn't find anything about it in the docs. It looks like you implemented the optimize tail recursion based on your Github readme.

Code: ScriptBasic
  1. DECLARE SUB mb_init ALIAS "mbas_init" LIB "mb"
  2. DECLARE SUB mb_dispose ALIAS "mbas_dispose" LIB "mb"
  3. DECLARE SUB mb_open ALIAS "mbas_open" LIB "mb"
  4. DECLARE SUB mb_close ALIAS "mbas_close" LIB "mb"
  5. DECLARE SUB mb_load_str ALIAS "mbas_load_str" LIB "mb"
  6. DECLARE SUB mb_run ALIAS "mbas_run" LIB "mb"
  7.  
  8. mb_code = """
  9. def fac(a)
  10.    if a = 0 then
  11.        return 1
  12.    endif
  13.  
  14.    return a * fac(a - 1)
  15. enddef
  16.  
  17. print fac(6);
  18. """
  19. mb_init
  20. mb_open
  21. mb_load_str mb_code
  22. mb_run
  23. mb_close
  24. mb_dispose
  25.  


jrs@laptop:~/sb/sb22/mybasic$ scriba mbfac.sb
720
jrs@laptop:~/sb/sb22/mybasic$

Title: Re: MY-BASIC
Post by: John on September 24, 2015, 01:08:16 AM
I thought I would give your precompiled Windows version a try in Wine and notice this error with a simple FOR/NEXT structure.

Interestingly it works fine in Script BASIC using your latest code base.

Code: ScriptBasic
  1. DECLARE SUB mb_init ALIAS "mbas_init" LIB "mb"
  2. DECLARE SUB mb_dispose ALIAS "mbas_dispose" LIB "mb"
  3. DECLARE SUB mb_open ALIAS "mbas_open" LIB "mb"
  4. DECLARE SUB mb_close ALIAS "mbas_close" LIB "mb"
  5. DECLARE SUB mb_load_str ALIAS "mbas_load_str" LIB "mb"
  6. DECLARE SUB mb_run ALIAS "mbas_run" LIB "mb"
  7.  
  8. mb_code = """
  9. for x = 1 to 5
  10. print x;
  11. next x
  12. """
  13. mb_init
  14. mb_open
  15. mb_load_str mb_code
  16. mb_run
  17. mb_close
  18. mb_dispose
  19.  


jrs@laptop:~/sb/sb22/mybasic$ scriba mbfornext.sb
1
2
3
4
5
jrs@laptop:~/sb/sb22/mybasic$



Title: Re: MY-BASIC
Post by: wangrenxin on September 24, 2015, 01:23:23 AM
Can you show an example of CLASS/ENDCLASS?

It's not implemented yet, I just reserved those keywords.

I thought I would give your precompiled Windows version a try in Wine and notice this error with a simple FOR/NEXT structure.

Sounds odd and interesting, I'll take a look on Linux natively and on Wine.
Title: Re: MY-BASIC
Post by: Cybermonkey342 on September 26, 2015, 02:21:20 PM
Sorry to tell you that I can't use the latest update. I can compile AllegroBASIC but it won't even start it gives me just a memory access error. The version before that update works fine, though. Seems to be the recursive subroutine support ...

EDIT: Hm, I tried compiling with GCC and it works, seems only TCC to be affected ...
Title: Re: MY-BASIC
Post by: John on September 26, 2015, 02:45:28 PM
Quote
EDIT: Hm, I tried compiling with GCC and it works, seems only TCC to be affected ...

That sure adds an interesting spin.

I wonder what Tony used to compile the .exe version he includes in the distribution?
Title: Re: MY-BASIC
Post by: wangrenxin on September 27, 2015, 08:09:51 PM
Hi guys,

I figured out that the memory corruption was caused by character list integers (I don't know the exact English term of it):

Code: C
  1. #define _SCOPE_META_ROOT 'ROOT'
  2. #define _SCOPE_META_REF 'REFS'
  3.  

VS, BCB, Clang, GCC support it properly, however, PellesC, TCC don't.

I fixed it by modifying it to:

Code: C
  1. #define _SCOPE_META_ROOT (1 << 0)
  2. #define _SCOPE_META_REF (1 << 1)
  3.  

Note: precompiled binaries are not updated.
Title: Re: MY-BASIC
Post by: Cybermonkey342 on October 19, 2015, 11:49:07 AM
Thanks for fixing that. I am working again on AllegroBASIC and actually found another issue (although I do not know, if this is intended).
Let's assume you want to use a sub without a paramater something like:
Code: [Select]
def drawbackground()
...
enddef
If you call now the sub I got a memory allocation error.
Workaround at the moment:
Code: [Select]
def drawbackground(void)
...
enddef
And this can be called like
Code: [Select]
drawbackground()without any errors.

I made another progress with AllegroBASIC - the timer works now correctly.

Best thing is that the memory leak isn't there anymore although I did nothing. Maybe because of the new version of MY-BASIC I use?
Title: Re: MY-BASIC
Post by: John on October 19, 2015, 03:04:53 PM
I can confirm.

Code: ScriptBasic
  1. DECLARE SUB mb_init ALIAS "mbas_init" LIB "mb"
  2. DECLARE SUB mb_dispose ALIAS "mbas_dispose" LIB "mb"
  3. DECLARE SUB mb_open ALIAS "mbas_open" LIB "mb"
  4. DECLARE SUB mb_close ALIAS "mbas_close" LIB "mb"
  5. DECLARE SUB mb_load_str ALIAS "mbas_load_str" LIB "mb"
  6. DECLARE SUB mb_run ALIAS "mbas_run" LIB "mb"
  7.  
  8. mb_code = """
  9. def bar(nul)
  10.  PRINT "In parameteless SUB";
  11. enddef
  12.  
  13. bar()
  14. """
  15. mb_init()
  16. mb_open()
  17. mb_load_str(mb_code)
  18. mb_run()
  19. mb_close()
  20. mb_dispose()
  21.  


jrs@laptop:~/sb/sb22/mybasic$ scriba mbnoprams.sb
In parameteless SUB
jrs@laptop:~/sb/sb22/mybasic$
Title: Re: MY-BASIC
Post by: John on October 20, 2015, 01:24:26 AM
Anything that is a valid variable will work as a placeholder.

Code: ScriptBasic
  1. DECLARE SUB mb_init ALIAS "mbas_init" LIB "mb"
  2. DECLARE SUB mb_dispose ALIAS "mbas_dispose" LIB "mb"
  3. DECLARE SUB mb_open ALIAS "mbas_open" LIB "mb"
  4. DECLARE SUB mb_close ALIAS "mbas_close" LIB "mb"
  5. DECLARE SUB mb_load_str ALIAS "mbas_load_str" LIB "mb"
  6. DECLARE SUB mb_run ALIAS "mbas_run" LIB "mb"
  7.  
  8. mb_code = """
  9. def bar(void)
  10.  PRINT void;
  11. enddef
  12.  
  13. bar(69)
  14. """
  15. mb_init()
  16. mb_open()
  17. mb_load_str(mb_code)
  18. mb_run()
  19. mb_close()
  20. mb_dispose()
  21.  


jrs@laptop:~/sb/sb22/mybasic$ scriba mbnoprams.sb
69
jrs@laptop:~/sb/sb22/mybasic$
Title: Re: MY-BASIC
Post by: wangrenxin on October 20, 2015, 05:12:32 AM
Hi guys,

I've figured out it's a bug, and fixed in latest revision. I think test coverage for new features are increasing, thank you.

I also added many new features recently, but not documented yet, such as generic LIST, DICT collections, garbage collection management for a new referenced usertype, and evaluating sub from C.

A simple LIST, DICT usage eg:

Code: [Select]
l = list(1, 2, 3)
d = dict("hah", l)
c = clone(d)
print get(get(c, "hah"), 0);
i = iterator(get(c, "hah"))
while move_next(i)
    print get(i);
wend

The memory is managed by Reference Counter and GC, so don't worry about leak or reference cycles.

Another example for referenced usertype. Assuming a FOO defined:

Code: C
  1. static void _str_dtor(struct mb_interpreter_t* s, void* ptr) {
  2.         char* str = (char*)ptr;
  3.  
  4.         mb_assert(s);
  5.  
  6.         free(str);
  7. }
  8.  
  9. static void* _str_clone(struct mb_interpreter_t* s, void* ptr) {
  10.         char* str = (char*)ptr;
  11.  
  12.         mb_assert(s);
  13.  
  14.         ptr = malloc(strlen(str) + 1);
  15.         memcpy(ptr, str, strlen(str) + 1);
  16.  
  17.         return ptr;
  18. }
  19.  
  20. static void _str_fmt(struct mb_interpreter_t* s, void* ptr, mb_print_func_t f) {
  21.         char* str = (char*)ptr;
  22.  
  23.         mb_assert(s);
  24.  
  25.         f(str);
  26. }
  27.  
  28. static int foo(struct mb_interpreter_t* s, void** l) {
  29.         int result = MB_FUNC_OK;
  30.         char* str = 0;
  31.         mb_value_t ret;
  32.  
  33.         mb_assert(s && l);
  34.  
  35.         mb_check(mb_attempt_open_bracket(s, l));
  36.         mb_check(mb_attempt_close_bracket(s, l));
  37.  
  38.         str = (char*)malloc(16);
  39.         memcpy(str, "hello", 6);
  40.         mb_check(mb_make_ref_value(s, str, &ret, _str_dtor, _str_clone, 0, 0, _str_fmt));
  41.         mb_check(mb_push_value(s, l, ret));
  42.  
  43.         return result;
  44. }
  45.  

We could use it as:

Code: [Select]
l = list()
push(l, foo())
a = clone(l)
l = nil
print pop(a);

A referenced usertype is also benefited by RC and GC.
Title: Re: MY-BASIC
Post by: Cybermonkey342 on October 20, 2015, 01:39:15 PM
Is there anything I have to call now additionally to the mb_close and mb_dispose functions? Now everything works fine except when the interpreter closes then I got a memory allocation error. (I think it's that, because I got a German error description: "Speicherzugriffsfehler".)
Title: Re: MY-BASIC
Post by: John on October 20, 2015, 09:51:24 PM
I'm seeing the same thing on exit. On a positive note the SUB now works without passing an argument.

Code: ScriptBasic
  1. DECLARE SUB mb_init ALIAS "mbas_init" LIB "mb"
  2. DECLARE SUB mb_dispose ALIAS "mbas_dispose" LIB "mb"
  3. DECLARE SUB mb_open ALIAS "mbas_open" LIB "mb"
  4. DECLARE SUB mb_close ALIAS "mbas_close" LIB "mb"
  5. DECLARE SUB mb_load_str ALIAS "mbas_load_str" LIB "mb"
  6. DECLARE SUB mb_run ALIAS "mbas_run" LIB "mb"
  7.  
  8. mb_code = """
  9. def bar()
  10.  PRINT "It Works!";
  11. enddef
  12.  
  13. bar()
  14. """
  15. mb_init()
  16. mb_open()
  17. mb_load_str(mb_code)
  18. mb_run()
  19. mb_close()
  20. mb_dispose()
  21.  


jrs@laptop:~/sb/sb22/mybasic$ scriba mbnoprams.sb
It Works!
Segmentation fault (core dumped)
jrs@laptop:~/sb/sb22/mybasic$

Title: Re: MY-BASIC
Post by: John on October 20, 2015, 10:14:19 PM
Cybermonkey342,

Will I be able to embed AllegroBASIC in Script BASIC like Tony's version?
Title: Re: MY-BASIC
Post by: wangrenxin on October 21, 2015, 12:02:11 AM
Is there anything I have to call now additionally to the mb_close and mb_dispose functions? Now everything works fine except when the interpreter closes then I got a memory allocation error. (I think it's that, because I got a German error description: "Speicherzugriffsfehler".)

Nothing additionally is needed, I didn't change "mb_xxx" function disciplines. Try the latest revision in which I've corrected some uninitialized memory issues please, it might solve the issue. It doesn't say any error when exiting, I compiled it with VC, PellesC, TCC on Windows, I'll test it with GCC and Clang on Linux and OSX later. Did it say "Speicherzugriffsfehler" with GCC?
Title: Re: MY-BASIC
Post by: John on October 21, 2015, 03:11:04 AM
Good: It no longer errors on exit.

Bad: It no longer executes the parameterless SUB like it did in the last round.

Code: Text
  1. def bar()
  2.   PRINT "It Works!";
  3. enddef
  4.  
  5. bar()
  6.  

Prints nothing.
Title: Re: MY-BASIC
Post by: wangrenxin on October 21, 2015, 04:36:48 AM
John,
The parameterless SUB works fine on my machine with your sample code, have you tried to rebuild it?
Title: Re: MY-BASIC
Post by: John on October 21, 2015, 10:09:49 AM
Your lastest version doesn't execute any code for me. (SUB or not) It doesn't error on exit like the previous version though.

I don't know what to say.
Title: Re: MY-BASIC
Post by: Cybermonkey342 on October 21, 2015, 01:44:44 PM
Is there anything I have to call now additionally to the mb_close and mb_dispose functions? Now everything works fine except when the interpreter closes then I got a memory allocation error. (I think it's that, because I got a German error description: "Speicherzugriffsfehler".)

Nothing additionally is needed, I didn't change "mb_xxx" function disciplines. Try the latest revision in which I've corrected some uninitialized memory issues please, it might solve the issue. It doesn't say any error when exiting, I compiled it with VC, PellesC, TCC on Windows, I'll test it with GCC and Clang on Linux and OSX later. Did it say "Speicherzugriffsfehler" with GCC?
Ah, "segmentation fault" is the correct term. Sorry, guys. I just compiled the latest version and still got the same error message. I compiled it with TCC.
EDIT: I got the same seg fault compiling it with GCC. That's on a Linux x64.
Title: Re: MY-BASIC
Post by: Cybermonkey342 on October 21, 2015, 01:47:21 PM
Cybermonkey342,

Will I be able to embed AllegroBASIC in Script BASIC like Tony's version?
Hm, I don't think so. AllegroBASIC is just a programm which calls a few Allegro functions and bind them to MY-BASIC.
That's the main function:
Code: [Select]
int main(int argc, char **argv)
{
atexit(_on_exit);
_on_startup();

if (argc>1) {
if(mb_load_file(bas, argv[1]) == MB_FUNC_OK)
mb_run(bas);
}
else {
printf ("AllegroBASIC 0.2\nUsage: allegrobasic[.exe] script.bas.\n");
}

return 0;
}
Title: Re: MY-BASIC
Post by: wangrenxin on October 21, 2015, 06:59:52 PM
Hi guys,

I got what's going wrong, there's a difference, you are probably using standard memory "malloc" "free" function, whereas I'm using the memory pool in "main.c" which doesn't fill released memory with any value, and it won't trigger error when accessing already released memory.

I'll deal with it. For the moment uncomment the "MB_ENABLE_GC" macro in "my_basic.h" to get around it.
Title: Re: MY-BASIC
Post by: wangrenxin on October 21, 2015, 08:29:04 PM
Hi all,

Fixed the seg fault with GC now.

FYI. it's recommended to use a memory pool (or object pool) instead of raw allocator. MB will generate many small objects which could be a bottleneck and cause memory fragments. A pool will relieve this situation. With the simple code below:

Code: [Select]
t = ticks()
for i = 0 to 10000000
s = s + i
next
t = ticks() - t
print t / 1000, "s";

On i7-4790, it takes ~4.3s with the pool in "main.c", ~11.1s without it.
Title: Re: MY-BASIC
Post by: John on October 21, 2015, 08:42:37 PM
Quote
I'll deal with it. For the moment uncomment the "MB_ENABLE_GC" macro in "my_basic.h" to get around it.

There is no such code in my_basic.h.

I will try your latest fix and see if things improve.

Title: Re: MY-BASIC
Post by: John on October 21, 2015, 08:57:07 PM
Things are back to normal again.

Code: ScriptBasic
  1. DECLARE SUB mb_init ALIAS "mbas_init" LIB "mb"
  2. DECLARE SUB mb_dispose ALIAS "mbas_dispose" LIB "mb"
  3. DECLARE SUB mb_open ALIAS "mbas_open" LIB "mb"
  4. DECLARE SUB mb_close ALIAS "mbas_close" LIB "mb"
  5. DECLARE SUB mb_load_str ALIAS "mbas_load_str" LIB "mb"
  6. DECLARE SUB mb_run ALIAS "mbas_run" LIB "mb"
  7.  
  8. mb_code = """
  9. def bar()
  10.  PRINT "It Works!";
  11. enddef
  12.  
  13. bar()
  14. """
  15. mb_init()
  16. mb_open()
  17. mb_load_str(mb_code)
  18. mb_run()
  19. mb_close()
  20. mb_dispose()
  21.  


jrs@laptop:~/sb/sb22/mybasic$ scriba mbnoprams.sb
It Works!
jrs@laptop:~/sb/sb22/mybasic$

Title: Re: MY-BASIC
Post by: Cybermonkey342 on October 22, 2015, 01:42:22 AM
Yes, it works again, also with TCC.
Title: Re: MY-BASIC
Post by: wangrenxin on January 01, 2016, 09:54:09 PM
I added a Stack Implementation in script (https://github.com/paladin-t/my_basic/wiki/Stack-module) wiki page, which would explain how to use prototype-based class in MY-BASIC quickly. Prototype-based programming is what I've done during last month. I'll add more explanation and complex sample script later.
Title: Re: MY-BASIC
Post by: John on January 01, 2016, 10:19:48 PM
Looks great Tony!

Addig OOP to MyBASIC is big step forward.
Title: Re: MY-BASIC
Post by: wangrenxin on January 08, 2016, 11:01:07 PM
Lambda abstraction supported by MY-BASIC now. Have a glance (https://github.com/paladin-t/my_basic/wiki/Lambda-abstraction)?
Title: Re: MY-BASIC
Post by: John on January 09, 2016, 02:21:54 PM
Looks interesting!

I will have to embed your latest in Script BASIC as an extension module and give it a spin.

I'm happy to see you making such great progress with MyBASIC.

BTW: I'm jealous of your outstanding markup language skills. You really make your docs look great!

Update:

I compiled a new 64 bit mb.so extension module using your new code base and all seems well.

setvars.bas
Code: [Select]
a = 0
b = 0.0
c$ = ""

Code: ScriptBasic
  1. DECLARE SUB mb_init ALIAS "mbas_init" LIB "mb"
  2. DECLARE SUB mb_dispose ALIAS "mbas_dispose" LIB "mb"
  3. DECLARE SUB mb_open ALIAS "mbas_open" LIB "mb"
  4. DECLARE SUB mb_close ALIAS "mbas_close" LIB "mb"
  5. DECLARE SUB mb_load_str ALIAS "mbas_load_str" LIB "mb"
  6. DECLARE SUB mb_load_file ALIAS "mbas_load_file" LIB "mb"
  7. DECLARE SUB mb_run ALIAS "mbas_run" LIB "mb"
  8. DECLARE SUB mb_getint ALIAS "mbas_getint" LIB "mb"
  9. DECLARE SUB mb_getdbl ALIAS "mbas_getdbl" LIB "mb"
  10. DECLARE SUB mb_getstr ALIAS "mbas_getstr" LIB "mb"
  11. DECLARE SUB mb_setint ALIAS "mbas_setint" LIB "mb"
  12. DECLARE SUB mb_setdbl ALIAS "mbas_setdbl" LIB "mb"
  13. DECLARE SUB mb_setstr ALIAS "mbas_setstr" LIB "mb"
  14. DECLARE SUB mb_reset ALIAS "mbas_reset" LIB "mb"
  15.  
  16. mb_init
  17. mb_open
  18. mb_load_file "setvars.bas"
  19. mb_run
  20. mb_setint "A", 123
  21. mb_setdbl "B", 1.23
  22. mb_setstr "C$", "One,Two,Three"
  23. PRINT mb_getint("A"),"\n"
  24. PRINT FORMAT("%g\n", mb_getdbl("B"))
  25. PRINT mb_getstr("C$"),"\n"
  26. mb_close
  27. mb_dispose
  28.  


jrs@laptop:~/sb/sb22/mybasic$ scriba mbvars.sb
123
1.23
One,Two,Three
jrs@laptop:~/sb/sb22/mybasic$


Code: [Select]
class animal
def speak(a)
print "default" + a;
enddef
endclass

class cat(animal)
def speak(a)
print "meow" + a;
enddef
endclass

class dog(animal)
def speak(a)
print "bark" + a;
enddef
endclass

c = new(cat)
d = new(dog)

c.speak("!")
d.speak("!")


jrs@laptop:~/sb/sb22/mybasic$ scriba mbclass.sb
meow!
bark!
jrs@laptop:~/sb/sb22/mybasic$


Code: [Select]
f = lambda (x, y) (return x * x + y * y)
print f(3, 4);


jrs@laptop:~/sb/sb22/mybasic$ scriba invoke.sb
25
jrs@laptop:~/sb/sb22/mybasic$



Code: ScriptBasic
  1. FUNCTION f(x,y)
  2.   f = x * x + y * y
  3. END FUNCTION
  4.  
  5. PRINT f(3, 4),"\n"
  6.  


jrs@laptop:~/sb/sb22/mybasic$ scriba lame_dah
25
jrs@laptop:~/sb/sb22/mybasic$


;D
Title: Re: MY-BASIC
Post by: wangrenxin on January 10, 2016, 02:35:53 AM
Thank you John, MY-BASIC will keep on evolving.
Title: Re: MY-BASIC
Post by: Cybermonkey342 on January 10, 2016, 07:09:33 AM
Hi Wang I've got a question. Maybe I do something wrong but my implemation of a drawtext function gives a memory leak if I add something to the output. For example the following BASIC code  gives that memory leak:
Code: [Select]
' mousetest
KEY_ESC          = 59
screen (640,480,"Mousetest")
hidemouse
do
cls

drawtext (100,100,"MouseX: "+str(mouseX))
drawtext (100,112,"MouseY: "+str(mouseY))
drawtext (100,124,"MouseButton: "+str(mousebutton))
drawtext (100,136,"MouseWheel: "+str(mousewheel))
if mousebutton = 1 then showmouse
if mousebutton = 2 then hidemouse
sync
until keystate (KEY_ESC) = true
end

I tried another way with the same result...
Code: [Select]
' mousetest
KEY_ESC          = 59
screen (640,480,"Mousetest")
hidemouse
do
cls
xm=str (mouseX)
drawtext (100,100,"MouseX: ")
drawtext (160,100,xm)
if mousebutton = 1 then showmouse
if mousebutton = 2 then hidemouse
sync
until keystate (KEY_ESC) = true
end

If I comment the line with str() out and do the following
Code: [Select]
xm="320"then there's no memory leak. So it seems to me that there is a problem with the str() function...?

EDIT: Seems to be confirmed. The following program which does not output anything has a memory leak:
Code: [Select]
' mousetest
KEY_ESC          = 59
screen (640,480,"Mousetest")
hidemouse
do
cls
xm=str (mouseX) 'instead of mousex I can also use a number but the result is still the same: memory leak
sync
until keystate (KEY_ESC) = true
end
Title: Re: MY-BASIC
Post by: John on January 19, 2016, 03:47:39 PM
FYI:

The MyBASIC STR() memory leak issue has been resolved. The info on that was lost in the forum restore from Jan. 10th 2016.

@OldBasicUser - Please rejoin the forum as your prior registration was lost in the restore.

@Charles Pegge - If you are reading this, please contact me so I can get your OxygenBasic site running on the new server.
Title: Re: MY-BASIC
Post by: wangrenxin on January 20, 2016, 02:17:02 AM
Happy to get back.
Title: Re: MY-BASIC
Post by: John on January 20, 2016, 12:03:22 PM
It's good to test your disaster recovery from time to time.  ::)
Title: Re: MY-BASIC
Post by: Cybermonkey342 on January 24, 2016, 08:41:26 AM
You can now download AllegroBASIC on: http://allegrobasic.pulsar2d.org/
Be sure to read the notes for Windows 10 if you are a Windows 10 user.
Title: Re: MY-BASIC
Post by: John on January 24, 2016, 10:29:47 AM
Thanks for allowing us to take your new BASIC for a test drive. It seems I had better luck than Tomaaz did.  :)

(http://files.allbasic.info/AllegroBASIC/ide.png)

(http://files.allbasic.info/AllegroBASIC/mbot.png)

(http://files.allbasic.info/AllegroBASIC/sprite.png)

(http://files.allbasic.info/AllegroBASIC/planets.png)
Title: Re: MY-BASIC
Post by: John on January 25, 2016, 08:50:36 PM
Here is AllegroBASIC running on Ubuntu 14.04 64 bit.

FYI: Console only, no IDE.


(http://files.allbasic.info/AllegroBASIC/mbot_u64.png)

(http://files.allbasic.info/AllegroBASIC/2d_u64.png)

(http://files.allbasic.info/AllegroBASIC/sprite_u64.png)


Title: Re: MY-BASIC
Post by: wangrenxin on January 26, 2016, 03:00:34 AM
Hi Markus,

The mandelbrot sample code came along with AllegroBASIC takes ~63 seconds on my i7 PC. Then I modified the code by commenting all graphics related lines, it costs almost the same duration. After that I tried to port it to a MY-BASIC shell version without graphics as well, it takes only ~15 seconds. I guess you were not using the memory pool, I recommend you to add a pool to optimize the memory performance of small chucks, since a simple implementation can even improve it more than 4 times faster. You can search for _open_mem_pool, mb_set_memory_manager(_pop_mem, _push_mem), _close_mem_pool() in shell/main.c to find my implementation.

MY-BASIC shell version without graphics:
Code: [Select]
miter=128
zm=120
time1=ticks()
for y=0 to 479
  for x=0 to 639
    zx=0
    zy=0
    cx= (x-320)/zm
    cy= (y-240)/zm
    i = miter
  while (zx*zx+zy*zy <4) and (i >0)
    tmp = zx * zx - zy * zy + cx
    zy = 2 * zx * zy + cy
    zx = tmp
    i=i-1
  wend
  next
next
time2=ticks()
time=(time2-time1)/1000
print time, " seconds.";
input
Title: Re: MY-BASIC
Post by: John on January 26, 2016, 10:31:41 AM
Here is the Script BASIC version for reference.

FYI: The Script BASIC version is doing 510 iterations compared to the MyBASIC version only doing 128. This was run on a fairly old laptop and nowhere close to the screaming machine you ran your test on. I gave it a try at 128 iterations and execution time only dropped by 2 10ths of a second.

(http://files.allbasic.info/ScriptBasic/gfx/sbgfxu64_mandelbrot2.png)

Code: ScriptBasic
  1. ' ScriptBasic GFX - Mandelbrot
  2.  
  3. IMPORT gfx.inc
  4.  
  5. s = gfx::Window(640,480,"ScriptBasic GFX Mandelbrot")
  6. ts = gfx::Time()
  7. FOR y = 0 TO 479
  8.   FOR x = 0 TO 639
  9.     cx = (x - 320) / 120
  10.     cy = (y - 240) / 120
  11.     rit = gfx::Mandelbrot(cx, cy, 510)
  12.     gfx::PixelRGBA s, x, y, rit * 12, rit * 8, rit * 4, 255
  13.   NEXT
  14. NEXT
  15. te = gfx::Time()
  16. gfx::stringColor s, 20, 15, "Time: " & FORMAT("%.4f",(te-ts)/1000) & " Seconds." & CHR(0), 0x000000ff
  17. gfx::Update
  18. WHILE gfx::KeyName(1) <> "+escape"
  19. WEND
  20. gfx::Close
  21.  
Title: Re: MY-BASIC
Post by: wangrenxin on January 26, 2016, 06:28:41 PM
John, that sounds so attractive that I can't refuse to read the source code of SB.
Title: Re: MY-BASIC
Post by: John on January 26, 2016, 07:16:49 PM
John, that sounds so attractive that I can't refuse to read the source code of SB.

It's a good read.  :)

Before you dig into the source, here is the same (128 iterations) but the Mandelbrot function is written in Script BASIC rather than C.

@Markus - You can drastically reduce the time if you don't update your canvas with each pixel. Just wait until the end and update it at one time, then grab your end time.

(http://files.allbasic.info/ScriptBasic/mbrot_native.png)

Code: ScriptBasic
  1. ' ScriptBasic GFX - Mandelbrot
  2.  
  3. IMPORT gfx.inc
  4.  
  5. FUNCTION Mandelbrot(cx, cy, iter)
  6.   LOCAL zx, zy, tp
  7.   zx = .0
  8.   zy = .0
  9.   tp = .0
  10.   WHILE zx * zx + zy * zy < 4 AND iter > 0
  11.     tp = zx * zx - zy * zy + cx
  12.     zy = 2 * zx * zy + cy
  13.     zx = tp
  14.     iter = iter - 1
  15.   WEND
  16.   Mandelbrot = iter
  17. END FUNCTION
  18.  
  19. s = gfx::Window(640,480,"Script BASIC SDL_gfx Mandelbrot")
  20. ts = gfx::Time()
  21. FOR y = 0 TO 479
  22.   FOR x = 0 TO 639
  23.     cx = (x - 320) / 120
  24.     cy = (y - 240) / 120
  25.     rit = Mandelbrot(cx, cy, 128)
  26.     gfx::PixelRGBA s, x, y, rit * 32, rit * 16, rit * 8, 255
  27.   NEXT
  28. NEXT
  29. te = gfx::Time()
  30. gfx::stringColor s, 20, 15, "Time: " & FORMAT("%.4f",(te-ts)/1000) & " Seconds." & CHR(0), 0x000000ff
  31. gfx::Update
  32. WHILE gfx::KeyName(1) <> "+escape"
  33. WEND
  34. gfx::Close
  35.  
Title: Re: MY-BASIC
Post by: Cybermonkey342 on January 28, 2016, 09:05:08 AM
Hi Markus,

The mandelbrot sample code came along with AllegroBASIC takes ~63 seconds on my i7 PC. Then I modified the code by commenting all graphics related lines, it costs almost the same duration. After that I tried to port it to a MY-BASIC shell version without graphics as well, it takes only ~15 seconds. I guess you were not using the memory pool, I recommend you to add a pool to optimize the memory performance of small chucks, since a simple implementation can even improve it more than 4 times faster. You can search for _open_mem_pool, mb_set_memory_manager(_pop_mem, _push_mem), _close_mem_pool() in shell/main.c to find my implementation.

MY-BASIC shell version without graphics:
Code: [Select]
miter=128
zm=120
time1=ticks()
for y=0 to 479
  for x=0 to 639
    zx=0
    zy=0
    cx= (x-320)/zm
    cy= (y-240)/zm
    i = miter
  while (zx*zx+zy*zy <4) and (i >0)
    tmp = zx * zx - zy * zy + cx
    zy = 2 * zx * zy + cy
    zx = tmp
    i=i-1
  wend
  next
next
time2=ticks()
time=(time2-time1)/1000
print time, " seconds.";
input
Yes, I don't use a memory pool, this looked too complicated for a C beignner ... maybe I can use your implementation of shell/main.c?

Okay, I tried your implementation, but can't compile it whether with TCC nor with GCC:
Quote
tcc: error: undefined symbol 'MB_SIZEOF_LST'
tcc: error: undefined symbol 'MB_SIZEOF_DCT'
Title: Re: MY-BASIC
Post by: John on January 28, 2016, 12:17:38 PM
Quote
Yes, I don't use a memory pool, this looked too complicated for a C beignner ...

I have to agree, memory management and garbage collection shouldn't be part the MyBASIC API and handled transparently.
Title: Re: MY-BASIC
Post by: wangrenxin on January 28, 2016, 11:21:24 PM
@Markus, I simplified it by modifying the constant part:

Code: C
  1.  
  2. /*
  3. ** {========================================================
  4. ** Memory manipulation
  5. */
  6.  
  7. static const size_t _SIZEOF_4BYTES = 4;
  8. static const size_t _SIZEOF_8BYTES = 8;
  9. static const size_t _SIZEOF_32BYTES = 32;
  10. static const size_t _SIZEOF_64BYTES = 64;
  11. static const size_t _SIZEOF_128BYTES = 128;
  12. static const size_t _SIZEOF_256BYTES = 256;
  13. static const size_t _SIZEOF_512BYTES = 512;
  14.  
  15. typedef unsigned _pool_chunk_size_t;
  16.  
  17. typedef union _pool_tag_t {
  18.         _pool_chunk_size_t size;
  19.         void* ptr;
  20. } _pool_tag_t;
  21.  
  22. typedef struct _pool_t {
  23.         size_t size;
  24.         char* stack;
  25. } _pool_t;
  26.  
  27. static int pool_count = 0;
  28.  
  29. static _pool_t* pool = 0;
  30.  
  31. static long alloc_count = 0;
  32. static long alloc_bytes = 0;
  33. static long in_pool_count = 0;
  34. static long in_pool_bytes = 0;
  35.  
  36. static long _POOL_THRESHOLD_COUNT = 0;
  37. static long _POOL_THRESHOLD_BYTES = 1024 * 1024 * 32;
  38.  
  39. #define _POOL_NODE_ALLOC(size) (((char*)malloc(sizeof(_pool_tag_t) + size)) + sizeof(_pool_tag_t))
  40. #define _POOL_NODE_PTR(s) (s - sizeof(_pool_tag_t))
  41. #define _POOL_NODE_NEXT(s) (*((void**)(s - sizeof(_pool_tag_t))))
  42. #define _POOL_NODE_SIZE(s) (*((_pool_chunk_size_t*)(s - sizeof(_pool_tag_t))))
  43. #define _POOL_NODE_FREE(s) do { free(_POOL_NODE_PTR(s)); } while(0)
  44.  
  45. static int _cmp_size_t(const void* l, const void* r) {
  46.         size_t* pl = (size_t*)l;
  47.         size_t* pr = (size_t*)r;
  48.  
  49.         if(*pl > *pr) return 1;
  50.         else if(*pl < *pr) return -1;
  51.         else return 0;
  52. }
  53.  
  54. static void _tidy_mem_pool(bool_t force) {
  55.         int i = 0;
  56.         char* s = 0;
  57.  
  58.         if(!force) {
  59.                 if(_POOL_THRESHOLD_COUNT > 0 && in_pool_count < _POOL_THRESHOLD_COUNT)
  60.                         return;
  61.  
  62.                 if(_POOL_THRESHOLD_BYTES > 0 && in_pool_bytes < _POOL_THRESHOLD_BYTES)
  63.                         return;
  64.         }
  65.  
  66.         if(!pool_count)
  67.                 return;
  68.  
  69.         for(i = 0; i < pool_count; i++) {
  70.                 while((s = pool[i].stack)) {
  71.                         pool[i].stack = (char*)_POOL_NODE_NEXT(s);
  72.                         _POOL_NODE_FREE(s);
  73.                 }
  74.         }
  75.  
  76.         in_pool_count = 0;
  77.         in_pool_bytes = 0;
  78. }
  79.  
  80. static void _open_mem_pool(void) {
  81. #define N 7
  82.         size_t szs[N];
  83.         size_t lst[N];
  84.         int i = 0;
  85.         int j = 0;
  86.         size_t s = 0;
  87.  
  88.         pool_count = 0;
  89.  
  90.         szs[i++] = _SIZEOF_4BYTES;
  91.         szs[i++] = _SIZEOF_8BYTES;
  92.         szs[i++] = _SIZEOF_32BYTES;
  93.         szs[i++] = _SIZEOF_64BYTES;
  94.         szs[i++] = _SIZEOF_128BYTES;
  95.         szs[i++] = _SIZEOF_256BYTES;
  96.         szs[i++] = _SIZEOF_512BYTES;
  97.  
  98.         mb_assert(i == N);
  99.  
  100.         memset(lst, 0, sizeof(lst));
  101.  
  102.         /* Find all unduplicated sizes */
  103.         for(i = 0; i < N; i++) {
  104.                 s = szs[i];
  105.                 for(j = 0; j < N; j++) {
  106.                         if(!lst[j]) {
  107.                                 lst[j] = s;
  108.                                 pool_count++;
  109.  
  110.                                 break;
  111.                         } else if(lst[j] == s) {
  112.                                 break;
  113.                         }
  114.                 }
  115.         }
  116.         qsort(lst, pool_count, sizeof(lst[0]), _cmp_size_t);
  117.  
  118.         pool = (_pool_t*)malloc(sizeof(_pool_t) * pool_count);
  119.         for(i = 0; i < pool_count; i++) {
  120.                 pool[i].size = lst[i];
  121.                 pool[i].stack = 0;
  122.         }
  123. #undef N
  124. }
  125.  
  126. static void _close_mem_pool(void) {
  127.         int i = 0;
  128.         char* s = 0;
  129.  
  130.         if(!pool_count)
  131.                 return;
  132.  
  133.         for(i = 0; i < pool_count; i++) {
  134.                 while((s = pool[i].stack)) {
  135.                         pool[i].stack = (char*)_POOL_NODE_NEXT(s);
  136.                         _POOL_NODE_FREE(s);
  137.                 }
  138.         }
  139.  
  140.         free((void*)pool);
  141.         pool = 0;
  142.         pool_count = 0;
  143. }
  144.  
  145. static char* _pop_mem(unsigned s) {
  146.         int i = 0;
  147.         _pool_t* pl = 0;
  148.         char* result = 0;
  149.  
  150.         ++alloc_count;
  151.         alloc_bytes += s;
  152.  
  153.         if(pool_count) {
  154.                 for(i = 0; i < pool_count; i++) {
  155.                         pl = &pool[i];
  156.                         if(s <= pl->size) {
  157.                                 if(pl->stack) {
  158.                                         in_pool_count--;
  159.                                         in_pool_bytes -= (long)(_pool_chunk_size_t)s;
  160.  
  161.                                         /* Pop from stack */
  162.                                         result = pl->stack;
  163.                                         pl->stack = (char*)_POOL_NODE_NEXT(result);
  164.                                         _POOL_NODE_SIZE(result) = (_pool_chunk_size_t)s;
  165.  
  166.                                         return result;
  167.                                 } else {
  168.                                         /* Create a new node */
  169.                                         result = _POOL_NODE_ALLOC(pl->size);
  170.                                         if((intptr_t)result == sizeof(_pool_tag_t)) {
  171.                                                 result = 0;
  172.                                         } else {
  173.                                                 _POOL_NODE_SIZE(result) = (_pool_chunk_size_t)s;
  174.                                         }
  175.  
  176.                                         return result;
  177.                                 }
  178.                         }
  179.                 }
  180.         }
  181.  
  182.         /* Allocate directly */
  183.         result = _POOL_NODE_ALLOC(s);
  184.         if((intptr_t)result == sizeof(_pool_tag_t)) {
  185.                 result = 0;
  186.         } else {
  187.                 _POOL_NODE_SIZE(result) = (_pool_chunk_size_t)s;
  188.         }
  189.  
  190.         return result;
  191. }
  192.  
  193. static void _push_mem(char* p) {
  194.         int i = 0;
  195.         _pool_t* pl = 0;
  196.  
  197.         if(--alloc_count < 0) {
  198.                 mb_assert(0 && "Multiple free.");
  199.         }
  200.         alloc_bytes -= _POOL_NODE_SIZE(p);
  201.  
  202.         if(pool_count) {
  203.                 for(i = 0; i < pool_count; i++) {
  204.                         pl = &pool[i];
  205.                         if(_POOL_NODE_SIZE(p) <= pl->size) {
  206.                                 in_pool_count++;
  207.                                 in_pool_bytes += _POOL_NODE_SIZE(p);
  208.  
  209.                                 /* Push to stack */
  210.                                 _POOL_NODE_NEXT(p) = pl->stack;
  211.                                 pl->stack = p;
  212.  
  213.                                 _tidy_mem_pool(false);
  214.  
  215.                                 return;
  216.                         }
  217.                 }
  218.         }
  219.  
  220.         /* Free directly */
  221.         _POOL_NODE_FREE(p);
  222. }
  223.  
  224. /* ========================================================} */
  225.  
  226.  

@John, But contexts are totally different from different users with C/C++, thus there's no one-fits-all memory pool solution, that's why C/C++ libs often accept customized memory allocator.
Title: Re: MY-BASIC
Post by: John on January 28, 2016, 11:45:22 PM
Wang,

The forum has syntax highlighting for most of the popular languages. Just use a [code=c] for syntax highlighting. (see change to your above example)
Title: Re: MY-BASIC
Post by: wangrenxin on January 29, 2016, 04:12:17 AM
The forum has syntax highlighting for most of the popular languages. Just use a [code=c] for syntax highlighting. (see change to your above example)

Wow, that is prettier and easier to read.
Title: Re: MY-BASIC
Post by: John on January 29, 2016, 08:55:08 PM
Can MyBASIC be embedded in itself?

Here (http://www.allbasic.info/forum/index.php?topic=387.msg4243#msg4243) is an example of Script BASIC being embedded in itself.
Here (http://www.allbasic.info/forum/index.php?topic=424.msg4633#msg4633) is the same but multi-threaded.
Title: Re: MY-BASIC
Post by: wangrenxin on January 30, 2016, 01:42:35 AM
Looks interesting. I shall give MB the ability to load and run nested MB code when I made a decision to introduce COROUTINE to MB.
Title: Re: MY-BASIC
Post by: Cybermonkey342 on February 05, 2016, 01:57:10 PM
@Markus, I simplified it by modifying the constant part:

Code: C
  1.  
  2. /*
  3. ** {========================================================
  4. ** Memory manipulation
  5. */
  6.  
  7. static const size_t _SIZEOF_4BYTES = 4;
  8. static const size_t _SIZEOF_8BYTES = 8;
  9. static const size_t _SIZEOF_32BYTES = 32;
  10. static const size_t _SIZEOF_64BYTES = 64;
  11. static const size_t _SIZEOF_128BYTES = 128;
  12. static const size_t _SIZEOF_256BYTES = 256;
  13. static const size_t _SIZEOF_512BYTES = 512;
  14.  
  15. typedef unsigned _pool_chunk_size_t;
  16.  
  17. typedef union _pool_tag_t {
  18.         _pool_chunk_size_t size;
  19.         void* ptr;
  20. } _pool_tag_t;
  21.  
  22. typedef struct _pool_t {
  23.         size_t size;
  24.         char* stack;
  25. } _pool_t;
  26.  
  27. static int pool_count = 0;
  28.  
  29. static _pool_t* pool = 0;
  30.  
  31. static long alloc_count = 0;
  32. static long alloc_bytes = 0;
  33. static long in_pool_count = 0;
  34. static long in_pool_bytes = 0;
  35.  
  36. static long _POOL_THRESHOLD_COUNT = 0;
  37. static long _POOL_THRESHOLD_BYTES = 1024 * 1024 * 32;
  38.  
  39. #define _POOL_NODE_ALLOC(size) (((char*)malloc(sizeof(_pool_tag_t) + size)) + sizeof(_pool_tag_t))
  40. #define _POOL_NODE_PTR(s) (s - sizeof(_pool_tag_t))
  41. #define _POOL_NODE_NEXT(s) (*((void**)(s - sizeof(_pool_tag_t))))
  42. #define _POOL_NODE_SIZE(s) (*((_pool_chunk_size_t*)(s - sizeof(_pool_tag_t))))
  43. #define _POOL_NODE_FREE(s) do { free(_POOL_NODE_PTR(s)); } while(0)
  44.  
  45. static int _cmp_size_t(const void* l, const void* r) {
  46.         size_t* pl = (size_t*)l;
  47.         size_t* pr = (size_t*)r;
  48.  
  49.         if(*pl > *pr) return 1;
  50.         else if(*pl < *pr) return -1;
  51.         else return 0;
  52. }
  53.  
  54. static void _tidy_mem_pool(bool_t force) {
  55.         int i = 0;
  56.         char* s = 0;
  57.  
  58.         if(!force) {
  59.                 if(_POOL_THRESHOLD_COUNT > 0 && in_pool_count < _POOL_THRESHOLD_COUNT)
  60.                         return;
  61.  
  62.                 if(_POOL_THRESHOLD_BYTES > 0 && in_pool_bytes < _POOL_THRESHOLD_BYTES)
  63.                         return;
  64.         }
  65.  
  66.         if(!pool_count)
  67.                 return;
  68.  
  69.         for(i = 0; i < pool_count; i++) {
  70.                 while((s = pool[i].stack)) {
  71.                         pool[i].stack = (char*)_POOL_NODE_NEXT(s);
  72.                         _POOL_NODE_FREE(s);
  73.                 }
  74.         }
  75.  
  76.         in_pool_count = 0;
  77.         in_pool_bytes = 0;
  78. }
  79.  
  80. static void _open_mem_pool(void) {
  81. #define N 7
  82.         size_t szs[N];
  83.         size_t lst[N];
  84.         int i = 0;
  85.         int j = 0;
  86.         size_t s = 0;
  87.  
  88.         pool_count = 0;
  89.  
  90.         szs[i++] = _SIZEOF_4BYTES;
  91.         szs[i++] = _SIZEOF_8BYTES;
  92.         szs[i++] = _SIZEOF_32BYTES;
  93.         szs[i++] = _SIZEOF_64BYTES;
  94.         szs[i++] = _SIZEOF_128BYTES;
  95.         szs[i++] = _SIZEOF_256BYTES;
  96.         szs[i++] = _SIZEOF_512BYTES;
  97.  
  98.         mb_assert(i == N);
  99.  
  100.         memset(lst, 0, sizeof(lst));
  101.  
  102.         /* Find all unduplicated sizes */
  103.         for(i = 0; i < N; i++) {
  104.                 s = szs[i];
  105.                 for(j = 0; j < N; j++) {
  106.                         if(!lst[j]) {
  107.                                 lst[j] = s;
  108.                                 pool_count++;
  109.  
  110.                                 break;
  111.                         } else if(lst[j] == s) {
  112.                                 break;
  113.                         }
  114.                 }
  115.         }
  116.         qsort(lst, pool_count, sizeof(lst[0]), _cmp_size_t);
  117.  
  118.         pool = (_pool_t*)malloc(sizeof(_pool_t) * pool_count);
  119.         for(i = 0; i < pool_count; i++) {
  120.                 pool[i].size = lst[i];
  121.                 pool[i].stack = 0;
  122.         }
  123. #undef N
  124. }
  125.  
  126. static void _close_mem_pool(void) {
  127.         int i = 0;
  128.         char* s = 0;
  129.  
  130.         if(!pool_count)
  131.                 return;
  132.  
  133.         for(i = 0; i < pool_count; i++) {
  134.                 while((s = pool[i].stack)) {
  135.                         pool[i].stack = (char*)_POOL_NODE_NEXT(s);
  136.                         _POOL_NODE_FREE(s);
  137.                 }
  138.         }
  139.  
  140.         free((void*)pool);
  141.         pool = 0;
  142.         pool_count = 0;
  143. }
  144.  
  145. static char* _pop_mem(unsigned s) {
  146.         int i = 0;
  147.         _pool_t* pl = 0;
  148.         char* result = 0;
  149.  
  150.         ++alloc_count;
  151.         alloc_bytes += s;
  152.  
  153.         if(pool_count) {
  154.                 for(i = 0; i < pool_count; i++) {
  155.                         pl = &pool[i];
  156.                         if(s <= pl->size) {
  157.                                 if(pl->stack) {
  158.                                         in_pool_count--;
  159.                                         in_pool_bytes -= (long)(_pool_chunk_size_t)s;
  160.  
  161.                                         /* Pop from stack */
  162.                                         result = pl->stack;
  163.                                         pl->stack = (char*)_POOL_NODE_NEXT(result);
  164.                                         _POOL_NODE_SIZE(result) = (_pool_chunk_size_t)s;
  165.  
  166.                                         return result;
  167.                                 } else {
  168.                                         /* Create a new node */
  169.                                         result = _POOL_NODE_ALLOC(pl->size);
  170.                                         if((intptr_t)result == sizeof(_pool_tag_t)) {
  171.                                                 result = 0;
  172.                                         } else {
  173.                                                 _POOL_NODE_SIZE(result) = (_pool_chunk_size_t)s;
  174.                                         }
  175.  
  176.                                         return result;
  177.                                 }
  178.                         }
  179.                 }
  180.         }
  181.  
  182.         /* Allocate directly */
  183.         result = _POOL_NODE_ALLOC(s);
  184.         if((intptr_t)result == sizeof(_pool_tag_t)) {
  185.                 result = 0;
  186.         } else {
  187.                 _POOL_NODE_SIZE(result) = (_pool_chunk_size_t)s;
  188.         }
  189.  
  190.         return result;
  191. }
  192.  
  193. static void _push_mem(char* p) {
  194.         int i = 0;
  195.         _pool_t* pl = 0;
  196.  
  197.         if(--alloc_count < 0) {
  198.                 mb_assert(0 && "Multiple free.");
  199.         }
  200.         alloc_bytes -= _POOL_NODE_SIZE(p);
  201.  
  202.         if(pool_count) {
  203.                 for(i = 0; i < pool_count; i++) {
  204.                         pl = &pool[i];
  205.                         if(_POOL_NODE_SIZE(p) <= pl->size) {
  206.                                 in_pool_count++;
  207.                                 in_pool_bytes += _POOL_NODE_SIZE(p);
  208.  
  209.                                 /* Push to stack */
  210.                                 _POOL_NODE_NEXT(p) = pl->stack;
  211.                                 pl->stack = p;
  212.  
  213.                                 _tidy_mem_pool(false);
  214.  
  215.                                 return;
  216.                         }
  217.                 }
  218.         }
  219.  
  220.         /* Free directly */
  221.         _POOL_NODE_FREE(p);
  222. }
  223.  
  224. /* ========================================================} */
  225.  
  226.  

@John, But contexts are totally different from different users with C/C++, thus there's no one-fits-all memory pool solution, that's why C/C++ libs often accept customized memory allocator.

Thanks, I tried that. Using the mempool, calculating the mandelbrot needs about 96 seconds. Without the mempool it needs about 110 seconds if AllegroBASIC was compiled with TCC. Using GCC it needs without mempool about 96 seconds and with mempool about 94 seconds. Not the wide difference as expected ...
Title: Re: MY-BASIC
Post by: John on February 05, 2016, 02:39:40 PM
Are those numbers based on showing each pixel as it's calculated?


Here is the above 10 second example but updating the canvas with each pixel. Can you post your numbers not updating the canvas until the end?

I think this good example of what I have been saying all along about interpreters. (Script BASIC specifically) I can go from 214 seconds to 1 second with a couple line changes. That should be the true goal of any real BASIC.

(http://files.allbasic.info/ScriptBasic/gfx/mbrot_perpix.png)

Code: ScriptBasic
  1. ' ScriptBasic GFX - Mandelbrot
  2.  
  3. IMPORT gfx.inc
  4.  
  5. FUNCTION Mandelbrot(cx, cy, iter)
  6.   LOCAL zx, zy, tp
  7.   zx = .0
  8.   zy = .0
  9.   tp = .0
  10.   WHILE zx * zx + zy * zy < 4 AND iter > 0
  11.     tp = zx * zx - zy * zy + cx
  12.     zy = 2 * zx * zy + cy
  13.     zx = tp
  14.     iter = iter - 1
  15.   WEND
  16.   Mandelbrot = iter
  17. END FUNCTION
  18.  
  19. s = gfx::Window(640,480,"Script BASIC SDL_gfx Mandelbrot")
  20. ts = gfx::Time()
  21. FOR y = 0 TO 479
  22.   FOR x = 0 TO 639
  23.     cx = (x - 320) / 120
  24.     cy = (y - 240) / 120
  25.     rit = Mandelbrot(cx, cy, 128)
  26.     gfx::PixelRGBA s, x, y, rit * 32, rit * 16, rit * 8, 255
  27.     gfx::Update
  28.   NEXT
  29. NEXT
  30. te = gfx::Time()
  31. gfx::stringColor s, 20, 15, "Time: " & FORMAT("%.4f",(te-ts)/1000) & " Seconds." & CHR(0), 0x000000ff
  32. gfx::Update
  33. WHILE gfx::KeyName(1) <> "+escape"
  34. WEND
  35. gfx::Close
  36.  
Title: Re: MY-BASIC
Post by: Cybermonkey342 on February 06, 2016, 01:01:04 AM
Yep, drawing each pixel ... The funny thing is, with RETROBASIC which uses SDL2 the reuslt is way faster. Only about 60 seconds compared to the 95 seconds with Allegro4.
If I don't draw each pixel it needs with AllegroBASIC and TCC 100 seconds, so it even takes longer than drawing every pixel!
Title: Re: MY-BASIC
Post by: John on February 06, 2016, 01:05:12 AM
I'm using SDL 1.2 64 bit with my examples.

That sounds way too strange to even know where to start to unravel that.

If I remove my SDL graphics code, it still runs about the same if I waited until the end to update the canvas. (10 seconds)
Title: Re: MY-BASIC
Post by: John on February 06, 2016, 09:33:09 PM
I think I found a happy middle of the road with this Mandelbrot benchmark. Doing the update of canvas when a line is completed is visually pleasing and relatively fast.

(http://files.allbasic.info/ScriptBasic/gfx/mbrot_line.png)

Code: ScriptBasic
  1. ' ScriptBasic GFX - Mandelbrot
  2.  
  3. IMPORT gfx.inc
  4.  
  5. FUNCTION Mandelbrot(cx, cy, iter)
  6.   LOCAL zx, zy, tp
  7.   zx = .0
  8.   zy = .0
  9.   tp = .0
  10.   WHILE zx * zx + zy * zy < 4 AND iter > 0
  11.     tp = zx * zx - zy * zy + cx
  12.     zy = 2 * zx * zy + cy
  13.     zx = tp
  14.     iter = iter - 1
  15.   WEND
  16.   Mandelbrot = iter
  17. END FUNCTION
  18.  
  19. s = gfx::Window(640,480,"Script BASIC SDL_gfx Mandelbrot")
  20. ts = gfx::Time()
  21. FOR y = 0 TO 479
  22.   FOR x = 0 TO 639
  23.     cx = (x - 320) / 120
  24.     cy = (y - 240) / 120
  25.     rit = Mandelbrot(cx, cy, 128)
  26.     gfx::PixelRGBA s, x, y, rit * 32, rit * 16, rit * 8, 255
  27.   NEXT
  28.   gfx::Update
  29. NEXT
  30. te = gfx::Time()
  31. gfx::stringColor s, 20, 15, "Time: " & FORMAT("%.4f",(te-ts)/1000) & " Seconds." & CHR(0), 0x000000ff
  32. gfx::Update
  33. WHILE gfx::KeyName(1) <> "+escape"
  34. WEND
  35. gfx::Close
  36.  

Here is the same by the line method but using the C Mandelbrot iterator.

(http://files.allbasic.info/ScriptBasic/gfx/mbrot_line_citer.png)

Code: ScriptBasic
  1. ' ScriptBasic GFX - Mandelbrot
  2.  
  3. IMPORT gfx.inc
  4.  
  5. s = gfx::Window(640,480,"Script BASIC SDL_gfx Mandelbrot")
  6. ts = gfx::Time()
  7. FOR y = 0 TO 479
  8.   FOR x = 0 TO 639
  9.     cx = (x - 320) / 120
  10.     cy = (y - 240) / 120
  11.     rit = gfx::Mandelbrot(cx, cy, 128)
  12.     gfx::PixelRGBA s, x, y, rit * 32, rit * 16, rit * 8, 255
  13.   NEXT
  14.   gfx::Update
  15. NEXT
  16. te = gfx::Time()
  17. gfx::stringColor s, 20, 15, "Time: " & FORMAT("%.4f",(te-ts)/1000) & " Seconds." & CHR(0), 0x000000ff
  18. gfx::Update
  19. WHILE gfx::KeyName(1) <> "+escape"
  20. WEND
  21. gfx::Close
  22.  
Title: Re: MY-BASIC
Post by: Cybermonkey342 on February 08, 2016, 11:24:14 AM
@Wang: I used the actual Github sources and ran into a problem ...
The following (part of the) program gives an error:

Code: [Select]
...
do
 cls
 x(i)=mousex
 y(i)=mousey
 gosub draw
 i=i+1
 if i>=1000 then i=i-1000
 sync

until keypressed=true
end

draw:
...
return

The error occurs in the line of the until statement:
Quote
Error: Line 23, Column 5: Wrong function reached in file _core_until
Any idea? Until I compiled it with the new sources it worked fine.
Title: Re: MY-BASIC
Post by: John on February 08, 2016, 11:30:23 AM
Maybe doing a DIF of the two would shed some light.
Title: Re: MY-BASIC
Post by: Cybermonkey342 on February 09, 2016, 11:30:14 AM
It also seems that the exit function does'nt work properly anymore. The following code does not draw a mandelbrot with the actual my-basic.c and .h files.
I am using now the older  ones which work fine. I hope you can fix that issues soon.
Code: Text
  1. screen (256,256,"Fractal")
  2.  
  3. bx=0
  4. by=0
  5. bw=256*1
  6. bh=256*1
  7.  
  8. sx=-2.2
  9. sy=-1.7
  10. sw=3.4
  11. sh=3.4
  12.  
  13. cls
  14. time1=tickcount
  15. for x=bx to bx+bw
  16.  for y=by to by+bh
  17.    gx=(x-bx)/bw*sw+sx
  18.    gy=(y-by)/bh*sh+sy
  19.    zx=gx
  20.    zy=gy
  21.    for c=0 to 255
  22.     col = c
  23.     nzx=zx*zx - zy*zy + gx
  24.     zy=2*zx*zy+gy
  25.     zx=nzx
  26.     if zx*zx + zy*zy > 4 then  col = c:  exit
  27.   next
  28.   r = col*256+col*32*0.5
  29.   v = col*256+col*64*0.5
  30.   b = col*256+col*32*0.8      
  31.   ink (r,v,b)
  32.   pset (x,y)
  33.  next
  34.  redraw
  35. next
  36. time2=tickcount
  37. ink (255,255,255)
  38. time=(time2-time1)/1000
  39. drawtext (0,0,"Time needed: "+str (time)+" seconds")
  40. sync
  41. inkey
Title: Re: MY-BASIC
Post by: wangrenxin on February 09, 2016, 11:52:19 PM
Marcus, which revision is the well worked one? I'd check it as soon as possible, but it's not easy to find a debug enviroument during Chinese new year.

EDIT: I finally get a debugger, try the latest revision. I fixed the wrong function error, and the EXIT issue; but there's still an issue with the EXIT statement and multiple line IF statement, I'll check it later seriously.
Title: Re: MY-BASIC
Post by: Cybermonkey342 on February 10, 2016, 08:48:55 AM
Thanks, and a Happy Chinese New Year. (新年好  ;))
Title: Re: MY-BASIC
Post by: wangrenxin on February 11, 2016, 06:14:11 AM
 ;)

I've fixed the EXIT bug with multiple line IF.
Title: Re: MY-BASIC
Post by: John on February 11, 2016, 03:18:59 PM
Thanks Wang!

I'll give it a try from the embedding standpoint and 64 bit Linux.

Curious. Would you have an interest in contributing to the C BASIC (http://www.basic-compiler.com/forum/) project with your C skills? Maybe converting MyBASIC source to C BASIC could act as a tutorial and make the code easier to read. Even if you have no interest in a make-over, your input would be appreciated if you have time.

Title: Re: MY-BASIC
Post by: wangrenxin on February 11, 2016, 10:50:45 PM
Thank you for inviting me, John. But I'm affraid it's difficult for me to dedicate to more hobby projects now. The CB forums looks interesting, I'll join and take a look around.
Title: Re: MY-BASIC
Post by: John on February 11, 2016, 11:44:58 PM
C BASIC is a fun project and not really a language. It's a preprocessor helper tool to make C look more like BASIC.

Title: Re: MY-BASIC
Post by: Cybermonkey342 on February 13, 2016, 01:16:23 AM
;)

I've fixed the EXIT bug with multiple line IF.

Sorry, but it still doesn't work as expected. I think the problem lies in line 26 of the above fractal example:
Code: [Select]
    if zx*zx + zy*zy > 4 then col = c:  exitThis only works with the older my-basic files. If I change the line into
Code: [Select]
if zx*zx + zy*zy > 4 then
 col = c
exit
endif
it even does not work with that older revision.
Title: Re: MY-BASIC
Post by: John on February 14, 2016, 09:53:52 AM
Is it just EXIT or any compound statement after a THEN?
Title: Re: MY-BASIC
Post by: wangrenxin on February 15, 2016, 07:35:44 PM
Markus, please check the latest revision.
Title: Re: MY-BASIC
Post by: John on February 15, 2016, 08:32:16 PM
Hi Wang,

Here is my quick test.

Code: [Select]
DECLARE SUB mb_init ALIAS "mbas_init" LIB "mb"
DECLARE SUB mb_dispose ALIAS "mbas_dispose" LIB "mb"
DECLARE SUB mb_open ALIAS "mbas_open" LIB "mb"
DECLARE SUB mb_close ALIAS "mbas_close" LIB "mb"
DECLARE SUB mb_load_str ALIAS "mbas_load_str" LIB "mb"
DECLARE SUB mb_run ALIAS "mbas_run" LIB "mb"

mb_code = """
x = 10 : y = 2 : z = 30

IF x = 1 THEN PRINT "One"; : GOTO Done
IF y = 2 THEN PRINT "Two"; : GOTO Done
IF z = 3 THEN PRINT "Three"; : GOTO Done

Done:

END
"""
mb_init()
mb_open()
mb_load_str(mb_code)
mb_run()
mb_close()
mb_dispose()


jrs@laptop:~/sb/sb22/mybasic$ scriba testmbthen.sb
Two
jrs@laptop:~/sb/sb22/mybasic$

Title: Re: MY-BASIC
Post by: Cybermonkey342 on February 22, 2016, 12:25:14 PM
Markus, please check the latest revision.
Yes, thanks it works now.
Although there's another issue now. If I check if the window was closed MY-BASIC now doesn't end the program anymore.
This does not work:
Code: [Select]
if windowclosed = true then
 end
endif
However, any other function (e.g. exit) is exceuted ...
Title: Re: MY-BASIC
Post by: wangrenxin on February 22, 2016, 06:10:28 PM
If I check if the window was closed MY-BASIC now doesn't end the program anymore.

The TRUE is defined as integer 1 and FALSE as integer 0 in MY-BASIC, that means 1 equals to true, but 2 not equals to true nor equals to false. It won't execute the END statement if windowclosed doesn't equal to 1. Currently, it's able to use following ways to test a condition steady.

1.
Code: Visual Basic
  1. if windowclosed <> false then
  2.  end
  3. endif
  4.  

2.
Code: Visual Basic
  1. if windowclosed then
  2.  end
  3. endif
  4.  

I would dismiss this confusion in later refactoring.
Title: Re: MY-BASIC
Post by: Cybermonkey342 on February 23, 2016, 10:40:28 AM
Oh, I think that's not the problem. My function does the following:
Code: [Select]
if (windowclosehandler!=0) {
windowclosehandler=1;
}
   

also this code works:
Code: [Select]
do
'... other code
until (keystate (KEY_ESC) = true) or (windowclosed=true)

And another question; is it possible to initialize an array with values? Would be handy for level data, something like:
Code: [Select]
dim x(2,2)=((1,1),(2,2))
Apart from that a DATA statement would be nice ...
Title: Re: MY-BASIC
Post by: wangrenxin on February 23, 2016, 06:03:21 PM
Markus,

I've tried a simple test case, which works fine without prompting anything as expected:

Code: PHP
  1. windowclosed = true
  2. if windowclosed = true then
  3.     end
  4. endif
  5. print "impossible";

So I think the problem is not simply within the test case. Would you provide a minimum full code which reproduce the bug?

It's not possible to initialize an array with values for the moment, I'll think over it.
Title: Re: MY-BASIC
Post by: wangrenxin on February 23, 2016, 07:17:19 PM
Markus, I've added a TO_ARRAY statement to make an array from a list, while lists are easy to initialize with data:

Code: PHP
  1. l = list(0, 1, 2)
  2. a = to_array(l)
  3. print a(0); a(1); a(2);
  4. print len(a);
Title: Re: MY-BASIC
Post by: John on February 23, 2016, 07:32:11 PM
Wang,

Does that work with string lists?

John
Title: Re: MY-BASIC
Post by: wangrenxin on February 23, 2016, 08:50:37 PM
Does that work with string lists?

Yes, but it needs to undefine the MB_SIMPLE_ARRAY macro in my_basic.h.
Title: Re: MY-BASIC
Post by: Cybermonkey342 on February 24, 2016, 08:48:05 AM
First thanks for the to_array statement. I'll try that later.
Here's the complete code (again the fractals):
Code: Text
  1. screen (256,256,"Fractal")
  2.  
  3. bx=0
  4. by=0
  5. bw=256
  6. bh=256
  7.  
  8. sx=-2.2
  9. sy=-1.7
  10. sw=3.4
  11. sh=3.4
  12.  
  13. cls
  14. time1=tickcount
  15. for x=bx to bx+bw
  16.  for y=by to by+bh
  17.    gx=(x-bx)/bw*sw+sx
  18.    gy=(y-by)/bh*sh+sy
  19.    zx=gx
  20.    zy=gy
  21.    for c=0 to 255
  22.     col = c
  23.     nzx=zx*zx - zy*zy + gx
  24.     zy=2*zx*zy+gy
  25.     zx=nzx
  26.     if zx*zx + zy*zy > 4 then
  27.     col = c
  28.     exit
  29.     endif
  30.   next
  31.   r = col*256+col*32*0.5
  32.   v = col*256+col*64*0.5
  33.   b = col*256+col*32*0.8      
  34.   ink (r,v,b)
  35.   pset (x,y)
  36.   if windowclosed = true then
  37.    end
  38.   endif
  39.  next
  40. redraw
  41. next
  42.  
  43. time2=tickcount
  44. ink (255,255,255)
  45. timex=(time2-time1)/1000
  46. drawtext (0,0,"Time needed: "+str (timex)+" seconds")
  47. sync
  48. inkey
  49. end

It's the lines 36 to 38. If I change the line 37 e.g. with exit (or any other statement), it is recognized, but not the end statement. Maybe because of the loops? This also didn't work with the old version. Only this did work:
Code: [Select]
if windowclosed = true then end
But in the actual version it doesn't work anymore.

Is it possible to convert lists to 2-dimensional arrays?
Title: Re: MY-BASIC
Post by: wangrenxin on February 24, 2016, 08:17:34 PM
Markus, thank your for your code, I figured out the problem due to your code. It went wrong since I'd refactored the FOR loop a few weeks ago. I've fixed it, and you can test it with following code:

Code: Text
  1. gosub sub
  2. end
  3. sub:
  4.     for j = 0 to 1
  5.         for i = 0 to 10
  6.             print i, ", ", j;
  7.             v = i > 3
  8.             if v = true then
  9.                 end ' Can be replaced with "return"
  10.             endif
  11.         next
  12.     next
  13.     return

Is it possible to convert lists to 2-dimensional arrays?

Yep it's possible. I prefer to implement it in script:

Code: Text
  1. def to_2d_array(l, d0, d1)
  2.     dim ret(d0, d1)
  3.     for j = 0 to d1 - 1
  4.         for i = 0 to d0 - 1
  5.             ret(i, j) = l(j * d0 + i)
  6.         next
  7.     next
  8.     return ret
  9. enddef
  10. a = to_2d_array(list(0, 1, 2, 3), 2, 2)
  11. print a(0, 0); a(1, 0); a(0, 1); a(1, 1);
Title: Re: MY-BASIC
Post by: John on February 24, 2016, 10:32:47 PM
Wang & Markus,

If you guys want to create a GeSHi (http://qbnz.com/highlighter/) syntax definition file for your BASIC languages, I will include them here on the forum for you to use.

Here is the Script BASIC (sb) syntax definition file.

Code: PHP
  1. <?php
  2. /*************************************************************************************
  3.  * sb.php
  4.  *
  5.  * Author: John Spikowski (support@scriptbasic.org)
  6.  *
  7.  * Script BASIC language file for GeSHi.
  8.  *
  9.  *************************************************************************************
  10.  *
  11.  *     This file is part of GeSHi.
  12.  *
  13.  *   GeSHi is free software; you can redistribute it and/or modify
  14.  *   it under the terms of the GNU General Public License as published by
  15.  *   the Free Software Foundation; either version 2 of the License, or
  16.  *   (at your option) any later version.
  17.  *
  18.  *   GeSHi is distributed in the hope that it will be useful,
  19.  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  20.  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21.  *   GNU General Public License for more details.
  22.  *
  23.  *   You should have received a copy of the GNU General Public License
  24.  *   along with GeSHi; if not, write to the Free Software
  25.  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  26.  *
  27.  ************************************************************************************/
  28.  
  29. $language_data = array (
  30.     'LANG_NAME' => 'Script BASIC',
  31.     'COMMENT_SINGLE' => array(),
  32.     'COMMENT_MULTI' => array(),
  33.     'COMMENT_REGEXP' => array(
  34.         // Comments (either single or multiline with _
  35.         1 => '/\'.*(?<! _)\n/sU',
  36.         ),
  37.     'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
  38.     'QUOTEMARKS' => array('"'),
  39.     'ESCAPE_CHAR' => '',
  40.     'KEYWORDS' => array(
  41.         1 => array(
  42.             'ABS', 'ACOS', 'ACOSECANT', 'ACTAN', 'ADDDAY', 'ADDHOUR', 'ADDMINUTE', 'ADDMONTH', 'ADDRESS', 'ADDSECOND', 'ADDWEEK', 'ADDYEAR', 'ALIAS', 'AND', 'AS', 'ASC', 'ASECANT', 'ASIN', 'ATAN', 'ATN',
  43.             'BIN', 'BINMODE', 'BY', 'BYVAL',
  44.             'CALL', 'CHDIR', 'CHOMP', 'CHR', 'CHR$', 'CINT', 'CLOSE', 'CLOSEALL', 'COMMAND', 'CONF', 'CONST', 'COS', 'COSECANT', 'COTAN', 'COTAN2', 'CRYPT', 'CURDIR', 'CVD', 'CVI', 'CVL', 'CVS',
  45.             'DAY', 'DECLARE', 'DELETE', 'DELTREE', 'DIRECTORY', 'DO', 'ELIF', 'ELSE', 'ELSEIF', 'ELSIF', 'END', 'ENDIF', 'ENVIRON', 'ENVIRON$', 'EOD', 'EOF', 'ERROR', 'ERROR$', 'EVEN', 'EXECUTE', 'EXIT', 'EXP',
  46.             'FALSE', 'FILE', 'FILEACCESSTIME', 'FILECOPY', 'FILECREATETIME', 'FILEEXISTS', 'FILELEN', 'FILEMODIFYTIME', 'FILEOWNER', 'FIX', 'FOR', 'FORK', 'FORMAT', 'FORMATDATE', 'FORMATTIME', 'FRAC', 'FREEFILE', 'FROM', 'FUNCTION',
  47.             'GCD', 'GLOBAL', 'GMTIME', 'GMTIMETOLOCALTIME', 'GO', 'GOSUB', 'GOTO',
  48.             'HCOS', 'HCOSECANT', 'HCTAN', 'HEX', 'HEX$', 'HOSTNAME', 'HOUR', 'HSECANT', 'HSIN', 'HTAN',
  49.             'ICALL', 'IF', 'IMAX', 'IMIN', 'IMPORT', 'INPUT', 'INSTR', 'INSTRREV', 'INT', 'ISARRAY', 'ISDEFINED', 'ISDIRECTORY', 'ISEMPTY', 'ISFILE', 'ISINTEGER', 'ISNUMERIC', 'ISREAL', 'ISSTRING', 'ISUNDEF',
  50.             'JOIN', 'JOKER',
  51.             'KILL',
  52.             'LBOUND', 'LCASE', 'LCASE$', 'LCM', 'LEFT', 'LEFT$', 'LEN', 'LET', 'LIB', 'LIKE', 'LINE', 'LOC', 'LOCAL', 'LOCALTIMETOGMTIME', 'LOCK', 'LOF', 'LOG', 'LOG10', 'LOOP', 'LOWER', 'LOWER$', 'LTRIM', 'LTRIM$',
  53.             'MAX', 'MAXINT', 'MID', 'MID$', 'MIN', 'MININT', 'MINUTE', 'MKD', 'MKD$', 'MKDIR', 'MKI', 'MKI$', 'MKL', 'MKL$', 'MKS', 'MKS$', 'MODULE', 'MONTH',
  54.             'NAME', 'NEXT', 'NEXTFILE', 'NO', 'NOT', 'NOW', 'NULL',
  55.             'OCT', 'OCT$', 'ODD', 'ON', 'OPEN', 'OPTION', 'OR', 'OUTPUT',
  56.             'PACK', 'PATTERN', 'PAUSE', 'PI', 'POP', 'POW', 'PRINT', 'PRINTNL',
  57.             'QUOTE',
  58.             'RANDOMIZE', 'REF', 'REGION', 'REPEAT', 'REPLACE', 'RESET', 'RESUME', 'RETURN', 'REWIND', 'RIGHT', 'RIGHT$', 'RND', 'ROUND', 'RTRIM', 'RTRIM$',
  59.             'SEC', 'SECANT', 'SEEK', 'SET', 'SGN', 'SIN', 'SLEEP', 'SPACE', 'SPACE$', 'SPLIT', 'SPLITA', 'SPLITAQ', 'SQR', 'STEP', 'STOP', 'STR', 'STR$', 'STRING', 'STRING$', 'STRREVERSE', 'STRREVERSE$', 'SUB', 'SWAP', 'SYSTEM',
  60.             'TAN', 'TAN2', 'TEXTMODE', 'THEN', 'TIME', 'TIMEVALUE', 'TO', 'TRIM', 'TRIM$', 'TRUE', 'TRUNCATE', 'TYPE',
  61.             'UBOUND', 'UCASE', 'UCASE$', 'UNDEF', 'UNPACK', 'UNTIL', 'UPPER', 'UPPER$',
  62.             'VAL', 'VAR', 'VBCALL', 'VBNEW', 'VBREL',
  63.             'WAITPID', 'WEEKDAY', 'WEND', 'WHILE', 'WILD',
  64.             'XOR',
  65.             'YEAR', 'YEARDAY'
  66.             ),
  67.         ),
  68.     'SYMBOLS' => array(
  69.         ),
  70.     'CASE_SENSITIVE' => array(
  71.         GESHI_COMMENTS => false,
  72.         1 => false,
  73.         2 => false,
  74.         3 => false,
  75.         4 => false,
  76.         5 => false,
  77.         6 => false
  78.         ),
  79.     'STYLES' => array(
  80.         'KEYWORDS' => array(
  81.             1 => 'color: #000080; font-weight: bold;',
  82.             ),
  83.         'COMMENTS' => array(
  84.             1 => 'color: #008000;'
  85.             ),
  86.         'BRACKETS' => array(
  87.             ),
  88.         'STRINGS' => array(
  89.             0 => 'color: #800000;'
  90.             ),
  91.         'NUMBERS' => array(
  92.             ),
  93.         'METHODS' => array(
  94.             ),
  95.         'SYMBOLS' => array(
  96.             ),
  97.         'ESCAPE_CHAR' => array(
  98.             0 => 'color: #800000; font-weight: bold;'
  99.             ),
  100.         'SCRIPT' => array(
  101.             ),
  102.         'REGEXPS' => array(
  103.             )
  104.         ),
  105.     'URLS' => array(
  106.         1 => '',
  107.         2 => '',
  108.         3 => '',
  109.         4 => '',
  110.         5 => '',
  111.         6 => ''
  112.         ),
  113.     'OOLANG' => false,
  114.     'OBJECT_SPLITTERS' => array(
  115.         ),
  116.     'REGEXPS' => array(
  117.         ),
  118.     'STRICT_MODE_APPLIES' => GESHI_NEVER,
  119.     'SCRIPT_DELIMITERS' => array(
  120.         ),
  121.     'HIGHLIGHT_STRICT_BLOCK' => array(
  122.         ),
  123.     'PARSER_CONTROL' => array(
  124.         'ENABLE_FLAGS' => array(
  125.             'BRACKETS' => GESHI_NEVER,
  126.             'SYMBOLS' => GESHI_NEVER,
  127.             'NUMBERS' => GESHI_NEVER
  128.             )
  129.         )
  130. );
  131.  
  132. ?>
  133.  
Title: Re: MY-BASIC
Post by: wangrenxin on February 25, 2016, 03:02:21 AM
It's nice to have, John.

Here's a keywords and reserved words list in MB:

NIL, MOD, AND, OR, NOT, IS, LET, DIM, IF, THEN, ELSEIF, ELSE, ENDIF, FOR, IN, TO, STEP, NEXT, WHILE, WEND, DO, UNTIL, EXIT, GOTO, GOSUB, RETURN, CALL, DEF, ENDDEF, CLASS, ENDCLASS, NEW, VAR, REFLECT, LAMBDA, MEM, TYPE, IMPORT, END

ABS, SGN, SQR, FLOOR, CEIL, FIX, ROUND, SRND, RND, SIN, COS, TAN, ASIN, ACOS, ATAN, EXP, LOG, ASC, CHR, LEFT, LEN, MID, RIGHT, STR, VAL, PRINT, INPUT

LIST, DICT, PUSH, POP, PEEK, INSERT, SORT, EXIST, INDEX_OF, GET, SET, REMOVE, CLEAR, CLONE, TO_ARRAY, ITERATOR, MOVE_NEXT
Title: Re: MY-BASIC
Post by: Cybermonkey342 on February 25, 2016, 11:14:49 AM
@Wang: Yeah, thanks it works again as expected. I think I can release a new version of AllegroBASIC this weekend.

@John: AllegroBASIC uses all keywords from MY-BASIC and the following additional keywords:

TRUE, FALSE(did you forget them Wang? ;)), SCREEN, SLEEP, SYNC, REDRAW, CIRCLE, FILLCIRCLE, INK, PAPER, CLS, PSET, RECTANGLE, FILLRECTANGLE, LINE, SCREENWIDTH, SCREENHEIGHT, KEYPRESSED, INKEY, DRAWTEXT, TEXTSIZE, PAINT, ELLIPSE, FILLELLIPSE, FILLTRIANGLE, TRIANGLE, KEYSTATE, MOUSEX, MOUSEY, MOUSEBUTTON, MOUSEWHEEL, SHOWMOUSE, HIDEMOUSE, TICKCOUNT, LOADBMP, LOADIMAGE, DRAWSPRITE, DRAWIMAGE, SETFPS, IMAGEWIDTH, IMAGEHEIGHT, ROTATESPRITE, SCALESPRITE, ROTATESCALEDSPRITE, LOADWAV, LOADSOUND, PLAYSOUND, STOPSOUND, FOPEN, FCLOSE, FPEEK, FPOKE, FREAD, FREAD_LINE, FWRITE, FWRITE_LINE, MESSAGEBOX, INPUTBOX, TIME, FILEEXISTS, WINDOWCLOSED
Title: Re: MY-BASIC
Post by: John on February 25, 2016, 07:20:13 PM
I put a combined mb (MyBASIC) syntax file on the server. If you add/change/remove keywords or enhance the the format I used for the Script BASIC file, let me know. (see changes to the last couple posts you guys made)
Title: Re: MY-BASIC
Post by: wangrenxin on February 25, 2016, 09:35:56 PM
@John, Thanks, it's prettier.

@Markus, Oops, forgot booleans indeed. I'm glad to help to make AllegroBASIC one more step forward.
Title: Re: MY-BASIC
Post by: Cybermonkey342 on February 26, 2016, 08:53:12 AM
@John: Cool, thanks a lot!

@Wang: The most work on AllegroBASIC is done by you!  ;)
(AllegroBASIC has just about 1,400 lines of code and MY-BASIC? 16,000?)
Title: Re: MY-BASIC
Post by: Cybermonkey342 on February 28, 2016, 04:02:32 AM
Allright guys, version 0.6 of AllegroBASIC is available on the homepage: http://allegrobasic.pulsar2d.org/
What's new?
Title: Re: MY-BASIC
Post by: wangrenxin on February 28, 2016, 05:49:44 PM
Cheers!
Title: Re: MY-BASIC
Post by: wangrenxin on February 29, 2016, 06:02:11 PM
I've added some new features to MY-BASIC:

1. A new keyword "ME" to MY-BASIC to represent a class instance itself inside its scope
2. Multi-line comment support by surrounding comment lines with "'[" and "']"

See an example below:

Code: Text
  1. class clz
  2.         var name = "Clz"
  3.         def tostring()
  4.                 return name ' Returns the "name"
  5.         enddef
  6.         def foo()
  7.                 print me; ' It will use the overridden "tostring"
  8.         enddef
  9. endclass
  10. c = new(clz)
  11. c.name = "Clz (Cloned)"
  12. clz.foo()
  13. c.foo()
  14. '[ Multi-line comment
  15. print "Won't print";
  16. print "Won't print neither";
  17. ']
  18. print "End";
  19.  

@John, Could you add "ME", "'[", "']", and triple dots "..." to the MB code shader? And is it possible to tell the shader the exact type of an identifier to color it, eg. identifiers after "class", "def", and comments between "'[" and "']", it's better if they could be processed distinctively from normal symbols.

@Markus, Removing the console window is friendly for most Windows guys, but it's still necessary when debugging a script, could you give an option to allow user to open a console window? Eg. adding a "console" statement. FYI. this is a sample to create a console window for GUI based applications on Windows http://stackoverflow.com/a/23457341/609345 (http://stackoverflow.com/a/23457341/609345).
Title: Re: MY-BASIC
Post by: John on February 29, 2016, 08:03:17 PM
Have peek at the GeSHi Project Site (http://qbnz.com/highlighter/) for the options. Attached is the current mb.php being used. I think the brackets and periods should go under the symbols section. You and Markus should work together on this and come up with a color scheme you like. You can do some pretty cool stuff with the definition file and making your code readable. Download the package and look at the existing .php language definition files as a guide.

Title: Re: MY-BASIC
Post by: wangrenxin on March 01, 2016, 02:14:52 AM
Sure, it looks worth studying.
Title: Re: MY-BASIC
Post by: John on March 01, 2016, 03:25:01 AM
I would let Markus take the lead on this as he has a SMF forum he could try it on before giving me the final definition file. The point I was trying to make is that you guys should at least agree on a color scheme and how specialized syntax is dealt with. I'm sure Markus will impress us.

Title: Re: MY-BASIC
Post by: wangrenxin on March 01, 2016, 10:15:00 PM
Hi,

I've added a new sample for MY-BASIC, YARD (Yet Another RPG Dungeon), at https://github.com/paladin-t/my_basic/tree/master/sample/yard (https://github.com/paladin-t/my_basic/tree/master/sample/yard). In which I used new features I've implemented these months.

Have fun.
Title: Re: MY-BASIC
Post by: John on March 03, 2016, 01:26:19 AM
I noticed you added a reset argument to mb_load_str.

I'm not sure how the game is suppose to work as I'm not a gamer. Q doesn't seem to quit.

Code: ScriptBasic
  1. DECLARE SUB mb_init ALIAS "mbas_init" LIB "mb"
  2. DECLARE SUB mb_dispose ALIAS "mbas_dispose" LIB "mb"
  3. DECLARE SUB mb_open ALIAS "mbas_open" LIB "mb"
  4. DECLARE SUB mb_close ALIAS "mbas_close" LIB "mb"
  5. DECLARE SUB mb_load_str ALIAS "mbas_load_str" LIB "mb"
  6. DECLARE SUB mb_run ALIAS "mbas_run" LIB "mb"
  7.  
  8. mb_code = """
  9. import "level.bas"
  10. import "player.bas"
  11.  
  12. print "Welcome to Yet Another RPG Dungeon!";
  13.  
  14. level.create()
  15. _role = new(player)
  16. _role.init(10, 2, 1)
  17. _role.dead_handler = lambda (_)
  18. (
  19.         print "- You are dead";
  20.         level.status = game_status.lose
  21. )
  22. level.start(_role)
  23. _turn = 1
  24. while _role.alive
  25.         print "[----  Turn ", _turn, ", HP ", _role.hp, ", ATK ", _role.atk, "  ----]";
  26.         level.format()
  27.         input _i$
  28.         cls()
  29.         if level.update(_i$) then
  30.                 _turn = _turn + 1
  31.         endif
  32. wend
  33. level.format()
  34. """
  35. mb_init()
  36. mb_open()
  37. mb_load_str(mb_code)
  38. mb_run()
  39. mb_close()
  40. mb_dispose()
  41.  


jrs@laptop:~/sb/sb22/mybasic$ scriba mb_dungeon.sb
Welcome to Yet Another RPG Dungeon!
[----  Turn 1, HP 10, ATK 2  ----]
<0, 0>
[Operations]
  E: Go east
  Q: Quit game


Title: Re: MY-BASIC
Post by: wangrenxin on March 03, 2016, 03:29:03 AM
I noticed you added a reset argument to mb_load_str.

Yes, pass with true for most cases.
I'm always cautious to change the API, but it's easy to get wrong with multi-line comments if I didn't add this parameter.

I'm not sure how the game is suppose to work as I'm not a gamer. Q doesn't seem to quit.

I forgot to mention pressing enter after chosen a command.
Title: Re: MY-BASIC
Post by: John on March 03, 2016, 08:26:01 AM
Quote
I forgot to mention pressing enter after chosen a command.

Tried that. No commands seem to work.
Title: Re: MY-BASIC
Post by: wangrenxin on March 03, 2016, 11:04:06 PM
@John, It accepts lower case command only, I've fixed this issue by checking both lower and upper case command input.
Title: Re: MY-BASIC
Post by: John on March 03, 2016, 11:30:46 PM
Not working and unpredictable and it maxes out my CPU(s).
Title: Re: MY-BASIC
Post by: wangrenxin on March 04, 2016, 01:27:38 AM
Not working and unpredictable and it maxes out my CPU(s).

So sad, it works fine on my Windows. I'll check it on Linux later.

But one odd thing is MB is single threaded, how could it burn both of your CPU cores to 100%...
Title: Re: MY-BASIC
Post by: John on March 04, 2016, 02:10:25 AM
Quote
But one odd thing is MB is single threaded, how could it burn both of your CPU cores to 100%...

Core leak.  :)
Title: Re: MY-BASIC
Post by: wangrenxin on March 11, 2016, 03:59:37 AM
@John, it works fine with my Windows, OSX and Linux (Raspbian for RasPi), could you provide more detailed information for the segment fault?

@All, I've added a short Interop with C# (https://github.com/paladin-t/my_basic/wiki/Interop-with-C%23) wiki.
Title: Re: MY-BASIC
Post by: John on March 11, 2016, 09:51:01 PM
My gut was right and Script BASIC is seeing your include as its include. What makes me smile is I didn't get a pre-run syntax error loading MyBASIC code.

I think this is a bug in Script BASIC as it interprets include if the first statement on the line as its own and ignores that it is part of a multi-line string.  :-\

The problem is the included code was inside the MyBASIC code block so MyBASIC was freaking out on multiple sets of the same functions.


jrs@laptop:~/sb/sb22/mybasic$ scriba dbgcon.sb mb_dungeon.sb
Application: ScriptBasic Remote Debugger - Linux
Version: 1.0
Source-File-Count: 9
Source-File: mb_dungeon.sb
Source-File: level.bas
Source-File: goal.bas
Source-File: entity.bas
Source-File: map.bas
Source-File: utils.bas
Source-File: monster.bas
Source-File: npc.bas
Source-File: player.bas
Line: 1
->


Title: Re: MY-BASIC
Post by: wangrenxin on March 14, 2016, 12:37:29 AM
Does SB take the import "xxx" as its own include? I'm afraid there's no better solution than changing the import word in MB or changing in SB.  :-\
Title: Re: MY-BASIC
Post by: John on March 14, 2016, 01:41:47 AM
It's a bug in Script BASIC I need to fix.

I have known about it for years.  ???
Title: Re: MY-BASIC
Post by: wangrenxin on March 17, 2016, 04:16:23 AM
Hi,

I found a way to simulate SELECT CASE in MY-BASIC without adding new keywords. Implemented as a select function as follow, which accepts a variable argument list with a boolean expression, a lambda expression, another boolean expression, and another lambda... The advantage is it accepts not only one constant equivalence case condition, but also a boolean expression with more sub conditions for one case; the disadvantage is it requires a very ugly single line code calling the select function. Maybe it's necessary to add multi-line code linking to MB now, just like what the underline _ does in VB.

Code: Text
  1. default = true ' For the default case
  2. def select(...)
  3.         l = len(...)
  4.         if l mod 2 <> 0 then
  5.                 print "Parameters not matched.";
  6.                 return
  7.         endif
  8.         for i = 0 to l - 1 step 2
  9.                 if ... then ' Evaluates a condition
  10.                         _ = ... ' Gets a lambda and executes it
  11.                         _()
  12.                         return
  13.                 else
  14.                         _ = ... ' Ignores a lambda argument
  15.                 endif
  16.         next
  17. enddef
  18. a = 85
  19. select(a >= 85, lambda () (print "A";), a >= 75, lambda () (print "B";), a >= 60, lambda () (print "C";), default, lambda () (print "D";))
  20.  
Title: Re: MY-BASIC
Post by: John on March 17, 2016, 09:11:19 PM
Script BASIC doesn't have a SELECT/CASE structure either. It does have a flexible IF that works just as well. Actually better as it doesn't have the traditional CASE compare / range / type restrictions.

Code: ScriptBasic
  1. a = 85
  2. IF a >= 85 THEN
  3.   PRINT "A\n"
  4. ELSE IF a >= 75 THEN
  5.   PRINT "B\n"
  6. ELSE IF a >= 60 THEN
  7.   PRINT "C\n"
  8. ELSE
  9.   PRINT "D\n"
  10. END IF
  11.  


jrs@laptop:~/sb/sb22/test$ scriba simcase.sb
A
jrs@laptop:~/sb/sb22/test$


Code: ScriptBasic
  1. DECLARE SUB mb_init ALIAS "mbas_init" LIB "mb"
  2. DECLARE SUB mb_dispose ALIAS "mbas_dispose" LIB "mb"
  3. DECLARE SUB mb_open ALIAS "mbas_open" LIB "mb"
  4. DECLARE SUB mb_close ALIAS "mbas_close" LIB "mb"
  5. DECLARE SUB mb_load_str ALIAS "mbas_load_str" LIB "mb"
  6. DECLARE SUB mb_run ALIAS "mbas_run" LIB "mb"
  7.  
  8. mb_code = """
  9.    default = true ' For the default case
  10.    def select(...)
  11.            l = len(...)
  12.            if l mod 2 <> 0 then
  13.                    print "Parameters not matched.";
  14.                    return
  15.            endif
  16.            for i = 0 to l - 1 step 2
  17.                    if ... then ' Evaluates a condition
  18.                            _ = ... ' Gets a lambda and executes it
  19.                            _()
  20.                            return
  21.                    else
  22.                            _ = ... ' Ignores a lambda argument
  23.                    endif
  24.            next
  25.    enddef
  26.    a = 85
  27.    select(a >= 85, lambda () (print "A";), a >= 75, lambda () (print "B";), a >= 60, lambda () (print "C";), default, lambda () (print "D";))
  28. """
  29. mb_init()
  30. mb_open()
  31. mb_load_str(mb_code)
  32. mb_run()
  33. mb_close()
  34. mb_dispose()
  35.  


jrs@laptop:~/sb/sb22/mybasic$ scriba mbcase.sb
A
jrs@laptop:~/sb/sb22/mybasic$


Title: Re: MY-BASIC
Post by: wangrenxin on March 17, 2016, 11:49:22 PM
It does have a flexible IF that works just as well. Actually better as it doesn't have the traditional CASE compare / range / type restrictions.

Yes, I can't agree more. IF has done it well.

John, does SB support separating a single statement into multi-lines? I'm a little bit refusing to add these features; but not quite sure.
Title: Re: MY-BASIC
Post by: John on March 18, 2016, 12:45:33 AM
Quote
does SB support separating a single statement into multi-lines?

Yes it does with the _ character.

Code: ScriptBasic
  1. FUNCTION test (arg1, _
  2.                arg2, _
  3.                arg3)
  4.  
Title: Re: MY-BASIC
Post by: wangrenxin on April 22, 2016, 04:54:05 AM
Finally, I added Unicode token support to MY-BASIC! For instance I can use Chinese variable now:

Code: Text
  1. &#21464;&#37327; = 22
  2. &#21478;&#19968;&#20010;&#21464;&#37327; = 7
  3. print &#21464;&#37327; / &#21478;&#19968;&#20010;&#21464;&#37327;;
  4.  
Title: Re: MY-BASIC
Post by: wangrenxin on April 22, 2016, 04:55:50 AM
Finally, I added Unicode token support to MY-BASIC! For instance I can use Chinese variable now:

Code: Text
  1. &#21464;&#37327; = 22
  2. &#21478;&#19968;&#20010;&#21464;&#37327; = 7
  3. print &#21464;&#37327; / &#21478;&#19968;&#20010;&#21464;&#37327;;
  4.  

Well, I meant this:
(http://41.media.tumblr.com/05f628361a80f6eaa0811f177b4aacc8/tumblr_o61abq2cXb1th0z8bo1_250.png)
Title: Re: MY-BASIC
Post by: wangrenxin on December 06, 2016, 07:28:57 AM
Added an inline data sequence module (https://github.com/paladin-t/my_basic/wiki/Inline-data-sequence-module), now it has a simple equivalent to retro DATA, READ, RESTORE statements :)
Title: Re: MY-BASIC
Post by: John on December 08, 2016, 05:45:08 PM
Great to see you still plugging away at the project. This is a nice enhancement for retro style BASIC compatibility.

Thanks for keeping us in the loop here on All BASIC.
Title: Re: MY-BASIC
Post by: wangrenxin on December 08, 2016, 06:52:37 PM
Yep, more stuff to add, although the procedure is very slow ;D
BTW. it also supports REM statement now for comment.
Title: Re: MY-BASIC
Post by: John on July 23, 2017, 01:04:23 PM
I recompiled the My-BASIC extension module for Script BASIC and all seems to have went well. The only thing I had to do is add the extra true argument to the mb_run() function wrapper.

Can you give us an update where things are with My-BASIC?

Title: Re: MY-BASIC
Post by: wangrenxin on July 24, 2017, 04:53:45 AM
Sure.

There are some minor bugfix, and some other major improvements for MY-BASIC since my last updating here.

   * Added support for applying `ITERATOR/MOVE_NEXT` and `FOR x IN y/NEXT` for collections, class and referenced usertype. https://github.com/paladin-t/my_basic/wiki/Use-iterators (https://github.com/paladin-t/my_basic/wiki/Use-iterators)
   * Added support for using a non-referenced usertype larger than `sizeof(void*)`. https://github.com/paladin-t/my_basic/wiki/Use-usertype-values#structure (https://github.com/paladin-t/my_basic/wiki/Use-usertype-values#structure)
   * Added interpreter forking functions.
   * Added a structured exception handling ability with interpreter forking. https://github.com/paladin-t/my_basic/wiki/Structured-exception-handling (https://github.com/paladin-t/my_basic/wiki/Structured-exception-handling)
   * Added a multiple condition branching, which is implemented in MY-BASIC code. https://github.com/paladin-t/my_basic/wiki/Multiple-condition (https://github.com/paladin-t/my_basic/wiki/Multiple-condition)
   * Added support for defining an alias for the `LAMBDA` keyword, which is helpful to write neat code. https://github.com/paladin-t/my_basic/wiki/Lambda-abstraction (https://github.com/paladin-t/my_basic/wiki/Lambda-abstraction)

Recently I'm working on an App powered by MY-BASIC, which will allow users to write game or application in an IDE with modern BASIC syntax. It's aimed to be similar as PICO-8. I'll initially release it for desktop (Windows), still WIP, yet details and releasing date are TBD.

There are also few API changes, which are easy to figure out.

BTW. don't forget to share your use cases with us via https://github.com/paladin-t/my_basic/issues/13 (https://github.com/paladin-t/my_basic/issues/13).