April 30, 2024, 06:02:06 PM

News:

IonicWind Snippit Manager 2.xx Released!  Install it on a memory stick and take it with you!  With or without IWBasic!


IWBasic v2.0 progress: compiler

Started by sapero, May 16, 2010, 02:48:12 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

sapero

June 18, 2010, 01:39:48 PM #25 Last Edit: June 18, 2010, 01:45:02 PM by sapero
Hmm, redimensioning static arrays is possible, but only when the new total size is not greater than the original allocation took.

int a[256]
redim a[4]     ' possible
redim a[16,16] ' possible
redim a[512]   ' not possible


It would be possible with pointers:
pointer p = 0
redim p[100] ' 100 bytes
redim p[@TYPEINT,100,100] ' integer matrix 100*100
redim p[0] ' delete

Brian

Hi, Sapero, thanks for the answer

Well, I suppose you could always DIM with a silly number, and then REDIM to the
required amount. Will that release the memory DIM'med in the first place?

Brian

sapero

June 19, 2010, 05:30:13 AM #27 Last Edit: June 19, 2010, 06:34:02 AM by sapero
Yes and not, it depends on the implementation, type of the variable, and where it is allocated.
If this will be a global variable, redim will not free the unused space, because the next global variable will be allocated always after the current (fixed location). Only enabled memory-swapping will free the memory, or better - will not allocate it in RAM until it is not touched (read/write).

The same allocation applies for local arrays in a subroutine  - the location of next variable is always after current variable, so even if you redim the array to 0, the space you initially declared will be reserved, but not freed.
It would be possible to allocate the array from stack - search for alloca function. Stack memory is automatically released when returning from a subroutine. The alloca function can be easily inlined, it modifies only the ESP register:
sub esp,memory_size
And the ESP value after subtracting points to allocated memory.
To free it, we need to add memory_size to ESP register. There is no problem if you have only one dynamic array. For two or more arrays, you may have a problem relocating the first array, because the current ESP is pointing to the last allocated array. It would require relocation of all the allocated arrays, probably invalidating dynamic array pointers copied to other parts in your program.
If you understand this, you'll see that using NEW/Delete is much easier

For dynamic arrays attached to a pointer variable (the second example in my previous response), there is no problem with REDIM because internally the code will call new/delete/realloc without taking care for other arrays. And if we are here, then REDIM is already useless, we have new/delete, only realloc is missing (easy to add).

Note: alloca function will not work with our current compiler if your saving the returned value in local variable. The pointer should be returned by reference:
declare myalloca(int size, pointer ppv)

sub test_alloca()
pointer array1, array2
myalloca(256, &array1) ' be sure to allocate 4*N bytes
myalloca(512, &array2)
' array1 is at array2+512
' total allocated size: 256+512
*<string>array1 = "hello"
*<string>array2 = "world"
' relocate array2 to 256 bytes (array1 cannot be relocated directly, because array2 is still allocated. If you need to relocate array1, just modify the pointer)
myalloca(-512/*old size*/+256/*new size*/, &array2)
' total allocated size: 256+512-512+256 = 256+256
' -- optional part --
' free both arrays
myalloca(-256, &array2)
myalloca(-256, &array1)
' or with single shoot: myalloca(-(256+256), &array1)
endsub

_asm
align 4
myalloca:
pop edx       ; return address
pop ecx       ; ppv
pop eax       ; size
sub esp,eax   ; allocate memory on the stack
mov [ecx],esp ; *ppv=esp
jmp edx       ; return
_endasm

Brian

Wow, that answer was like asking to read a Superman comic, and being given
War and Peace instead!

But from your explanation, I can see the logic in opting for dynamic arrays
attached to a pointer variable. As you point out, we can already do that

Thanks for the detailed info,

Brian

sapero

June 20, 2010, 01:43:32 PM #29 Last Edit: June 20, 2010, 01:59:42 PM by sapero
I have added $asm, $endasm, and $emit keywords, for inline assembly gurus ;)

There is additional $option "return 0|1|yes|no|on|off|enable|disable" if you want to return a value directly in eax register. If you turn this option ON, the compiler will not warn about missing return value, and will not return zero, as it does by default.
$option "return disable"
sub testsub(),int
$emit mov eax,7
return ' return 7
$emit mov eax,6
endsub ' return 6
$option "return enable"
print testsub()

sapero

June 23, 2010, 11:56:17 PM #30 Last Edit: June 24, 2010, 01:17:10 AM by sapero
I am now working on a bug - where previously defined constant is used as function's argument name and a select-case statement. The compiler was crashing (while Ebasic 1735 didn't):
$Include "windowssdk.inc"
Sub ShowErrors(Error as Int)
  Select Error
     Case 1

Error is defined as$define ERROR 0 ' wingdi.inc
Currently the compiler will throw "Name/constant conflict: Error" pointing to the line with "SUB" (instead crashing), and the CASE statement will show another error "invalid argument for comparision" (because the parameters passed to internal compiler function are invalid).

What I have planned:
1. Option for case sensitive names - Error and ERROR will be two different things.
2. Functions profiling (usage count and execution time) in debug mode. Will help you to optimize the code, you will know which function is too slow.
Timing and hit-count can be implemented before you actually call a function, and/or at the beginning/return of/from a function.

EDIT: OK, I have found the bug - it was caused by my optimizations, where constant names were replaced with values, without checking first if a variable with the same name is available.

LarryMc

My personal opinion is that having things case sensitive, even as an option, will cause more grief than benefit.

I have always seen things in IWBasic NOT being case sensitive as a real plus for the language.

And what happens when people share code with one not opting for case sensitive (like me) and the other person's code uses case sensitive and has a bunch of error/ERROR coding?

LarryMc
LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

sapero

Nothing, it will just compile, until you keep the code as is, or follow the rules defined by the author.

Please note that the assembler and linker are case sensitive.

EXPORT MySub
SUB    mySub

or' module 1
global MySub

' module 2
extern mysub

This will compile but not link, because the linker will fail to find MySub (export) or mysub (extern).

If case sensibility will be enabled, there will be no problem having a constant ERROR and a variable error (or even another mix like eRror). If you need it, just use $option "casesensitive=no", and this will apply only to current module.
When defining external variables and functions, you are forced to use the correct case independant from this option, because the linker is case sensitive, and each symbol must exactly match.

LarryMc

Now that you mentioned it I remember the linker being case sensitive.  The first time I ran into that it took me a while to figure out what my problem was.

Thanks for refreshing my memory.

LarryMc
LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

sapero

We can already add strings. What would you say if we could multiply them, like in Sinclair Basic (ZX Spectrum) ?

Example: create "1 item" or "2 items"

int items = ...
string s = str$(items) + " item" + ("s" * (items>0))

The operator would be string*boolean, returning string if boolean is true, or an empty string if boolean is false.

int boolean = true ' zero or anything
string booleanString = "true" * boolean + "false" * !boolean

LarryMc

I think that would be a nice little feature.

LarryMc
LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

sapero

I have added inlined version of IIF function: a?b:c. Note - the colon is not used as a separator for new instruction.

int boolean = true
print boolean ? "true" : "false"


As b,c you can pass any type of data, but the types should be equal. Mixing INT and FLOAT, or FLOAT+DOUBLE, or any other "bad" combination is allowed, but it must be handled by the function you are passing the value. The type of b is returned independing of the type of c.
Mixing types of different size is not allowed - for example integer + double returned from a function:
print boolean ? 1 : abs(5)


Optimizations progress: size of code generated by the new compiler is 21% smaller than current official compiler generates. Compared with a 2050 lines image parsing program.

Bugfixes: fixed conversion from uint to double, and uint64 to double.

sapero

June 29, 2010, 03:33:00 AM #37 Last Edit: June 29, 2010, 06:47:25 AM by sapero
Added option of case sensitive compilation:
$option "casesensitive"
After enabling it, __CASESENSITIVE__ preprocessor condition will be defined. Use $ifdef to detect it:
typedef byte schar
$ifdef __CASESENSITIVE__
typedef BYTE char
$endif


To use case sensitive compilation mode with windowssdk.inc, you will need to update the headers, because at least 7 files require small modification (additional typedef for BYTE) - wchar.inc, stdio.inc, stdlib.inc, SNADOS.inc, ntdef.inc, intsafe.inc, basetsd.inc. This update will include only the $ifdef part form the example above.

Case sensitive compilation mode does not affect build-in variable types, so char and CHAR is the same type.

---
Added static keyword, used to create a static variables in a subroutine which does not lose it's contents, and acts much like a global variable.

LarryMc

QuoteAdded option of case sensitive compilation

I'll show my ignorance  :-[ and ask:

Why would I need this? or How does this benefit me as a user? ???

LarryMc
LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

sapero

This is a feature, a preference. One likes it, one hates it. Here you can choose to use it or not.

Case sensitivity allows faster compilation because the compiler doesn't have to alter the case of everything in order to make comparisons.
Benefits?
* safely mix constants and variables with the same name (ERROR+error).
* "change" the value of a constant by defining it again, with different case.
* when using SI (International System of Units) derieved names, it will be possible to define F for faraday and f for gravity.

Look from the other side - someone is preffering case sensitivity, and is looking for Basic compiler...

LarryMc

Thanks for the explanation.

Now, is there a way that a novice (or senile, in my case) programmer  get into trouble selecting the option?

I only ask because one of the beauties of IWBasic is its simplicity in using.

That's not totally true.  I'm also asking because all of these neat new things you are adding will ultimately have to be fully documented for users.  And although your posts are always very precise and better than most of us who have English as our primary and only language, I know the pains you take in making your post.

Larry or me or someone else will have to put all of this in terms that a novice user can understand in the documentation.

LarryMc
LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

sapero

June 29, 2010, 08:40:05 AM #41 Last Edit: July 01, 2010, 01:04:52 PM by sapero
Not much, just a few "undefined variable" errors.
WINDOW w
w.hwnd = 7 ' error, hwnd is undefined. Should be hWnd
string s = left$("abc", 1) ' error, should be LEFT$


I'll add a hint to the error message: undefined variable hwnd. Did you mean hWnd?  (added).

LarryMc

Sounds good to me!

thanks for having patience with me, as you always do.

LarryMc
LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

Guilect


sapero

July 01, 2010, 07:07:07 AM #44 Last Edit: July 01, 2010, 09:36:34 AM by sapero
Added $ELIF directive:
$if version==1
... something
$elif version==2
... something
$endif


All the $IF directives are now allowed inside TYPE-ENDTYPE.

Structure definition can be now nested:
TYPE MyNestType,1
int t
TYPE pt
int x,y
ENDTYPE
ENDTYPE

MyNestType var
print var.t, var.pt.x

Nesting level is unlimited.

Now working with UNION... done. A nested union can have a name:
TYPE MYDATA
MYENUM nType
UNION u ' optional name
TYPE personal
string name    ' mydata.u.personal.name
string surname
ENDTYPE
ENDUNION
ENDTYPE

LarryMc

Now those are some awesome enhancements.!!!

LarryMc
LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

Ficko


zaphod

Hello Sapero !

Very good to see your enhancements. IW basic deserve that !

Do you need some beta testers ?

billhsln

As to the case sensitivity, will there be a list of which commands and special fields with their exact spelling?  (IE, hWnd and others like it).

Thanks,
Bill
When all else fails, get a bigger hammer.

sapero

Bill, if you enable case sensitive compilation, anything but build-in base types (and the list below) will be case sensitive - functions, constants, id's, variables, structures, typedefs.

The following will be case insensitive:
def, dim, $error, $warning, typedef, $typedef, $undef, gosub, goto, jump, label, ... the list is very big, it includes all the keywords defined as {command} in the .incc files.

Zaphod, this is up to Larry (Rock Ridge Farm), he is the owner. We have no beta testers yet.