IonicWind Software

IWBasic => General Questions => Topic started by: sapero on May 16, 2010, 02:48:12 AM

Title: IWBasic v2.0 progress: compiler
Post by: sapero on May 16, 2010, 02:48:12 AM
Hello,
I am the new IWBasic compiler coder. In this topic I will share with you what changes are made, and what I'm working on.
This topic will be modified as I'm progressing with the compiler.

Command line:sub sum(int a, int b),int
int c
_asm
mov eax,[a]
add eax,[b]
mov [c],eax
_endasm
return c
endsub

You can set command line options directly from the source code:
$option "name=value"
$option "name value"


Where name can be one of: /c or Codepage, /e or ErrorLimit, /i or IncludePath, /p or AsmVariables, /w or Warning, Return, Intrinsic, Optimization, CaseSensitive, novtable, oldlibslocation, strict, ZeroVariables, /m, /a, LibPath, QuoteLibPaths, ResolveLibs.
Value depends on the current option, and can be:int a,b,c,d ' the default is 'right', the 'd' variable is defined first.

Push/pop option value is to save/restore the current value. If you want to modify a option for a few lines in your code, use:
$option "name push" ' save current
$option "name new_value" ' modify
...
$option "name pop" ' restore

Numbers passed to $option can be formatted in decimal, or hexadecimal with 0x prefix.
$option "codepage 65001"
$option "codepage 0xFDE9"

Currently implemented warning filters:

Special constants:

Strings:int count = 2
print "found ", count, " item", "s"*(count<>1)



Unicode strings:
String Literals:uint i = `abcd`iwstring w[4]
w[0] = L`ä`
w[1] = L`ó`
w[2] = L`æ­¦`
w[3] = L`\0` ' =0; =`\x0`; =L`\x0`

istring s[4]
s[0] = `A`,0

Preprocessor:$ifndef UNICODE
$error "This file must be compiled with UNICODE condition"
$endif
$if (VERSION > 0x0202) and (SUBVERSION <> 0)
...
$endif

$ifdef TRIAL_VERSION
$elifdef DEMO_VERSION
$else
$endif


Subroutines:sub function()
static POINT pt
static int x
static def y as int
static dim z as int
sub cdecl blah()
global sub cdecl blah()


Labels:label outside
'goto cleanup <- undefined, unless defined in global namespace
'goto subroutine1 <- error

sub subroutine1()
'goto outside <- undefined
goto cleanup
cleanup:
endsub

sub subroutine2()
'goto outside <- undefined
goto cleanup
cleanup:
endsub


Language:char array[8]
declare extern function(...)
function(array)
? 1,2,3
import __argc as int
import __wargv as pointer ' call __wgetmainargs to initialize
import __argv as pointer ' call __getmainargs to initialize

class CC
declare import CC()
declare import _CC()
declare import method()
endclass



New variable types:
Inline assembler:$emit nop

Mixing Basic with Assembler:type mytype
int a
int b
endtype

typedef DWORD uint
declare iVal as int
declare sVal as string
declare tVal as mytype ' TYPE/ENDTYPE
declare dVal as DWORD  ' typedef

print iVal, iVal[1]
print sVal
print tVal.a, tVal.b
print tVal[1].a, tVal[1].b
print dVal

_asm
segment .data
iVal: dd 6, 5, 4, 3, 2, 1
sVal: db "hello", 0
tVal: dd 100,101, 200,201
dVal: dd 500
segment .text
_endasm



Constants:autodef = 1234567890uq
if (typeof(autodef) = @TYPEINT64)
print "type of 1234567890uq is INT64"
elseif (typeof(autodef) = @TYPEUINT64)
print "type of 1234567890uq is UINT64"
endif
int     binary   =        /*  optional zero's-> */ 00000000000000000000000000011000b ' Bin
uint   ubinary   =                                 00000000000000000000000000011000bu ' Bin Unsigned
int64   binary64 = 0100000000000000000000000000000010000000000000000000000000011000bq ' Bin Quadword
uint64 ubinary64 = 1000000000000000000000000000000010000000000000000000000000011000buq ' Bin Unsigned Quadword

enum myenum
minusone = -1
zero
one
two = one+1
six = 2+2*2
endenum

print minusone, zero, one, two, six


Operators:if (a == b) then equal()
if (a = b) then equal() ' still there
if (a != b) then notEqual()
if (a && b) then BothTrue()
if (!a && !b) then BothFalse()
SetWindowLong(hwnd, GWL_STYLE, styles & ~WS_VISIBLE) ' hide window


Code generation:+, -, *, /, %, and, &, or, |, ^ (aka XOR), <<, >>, = (or ==)int a = 1+2|4|8|@MINBOX

Intrinsic functions:

Loops:

Other:
Title: Re: IWBasic v2 progress: compiler
Post by: sapero on May 24, 2010, 06:39:42 AM
I am thinking to add a $pragma directive to the compiler. It will make possible to set the command-line options directly from your source code.
Examples:
$pragma compiler "include=..\\zlib" ' additional include search path, relative to current file path.
$pragma compiler "include=$(ProjectDir)\\..\\zlib" ' additional include search path, relative to project path.
$pragma pack "push{,number}|pop|default|number" ' change default structure packing
$pragma warning "disable=1234" ' disable warning 1234
$pragma compiler "codepage=65001" ' use utf-8 codepage for unicode strings

$pragma linker "libs=..\\zlib\\lib" ' add library search path, relative to current file path.


EDIT: The $OPTION keyword has been extended, so there is no need to add a new $PRAGMA keyword.
Title: Re: IWBasic v2 progress: compiler
Post by: aurelCB on May 24, 2010, 07:22:30 AM
That would be great Sapero.
If i may say something abut backslash using.
Is it not enugh one backslash not two?
Title: Re: IWBasic v2 progress: compiler
Post by: sapero on May 24, 2010, 07:46:20 AM
You can use single backslashes, but only if the next character is not one of 0,1,2,3,4,5,6,7,x,\,t,n," and optionally r,` characters inside character constants.
If you invite me for a beer, I'll add a option to disable escape sequenes ;)
Title: Re: IWBasic v2 progress: compiler
Post by: LarryMc on May 24, 2010, 07:55:15 AM
If it were me I'd leave it as \\.

If you add an option to disable it then you need to make sure it doesn't break existing code that is using \\.

LarryMc
Title: Re: IWBasic v2 progress: compiler
Post by: aurelCB on May 24, 2010, 08:08:27 AM
Ok guys i understand, i just ask..
Title: Re: IWBasic v2 progress: compiler
Post by: Steven Picard on May 24, 2010, 10:13:53 AM
Or, you could do something similar to C#:

String myVar = "c:\\directory\\something";

Sting myVar = @"c:\directory\something";

Of course, in the last option you cannot include escape sequences like "\n\r".
Title: Re: IWBasic v2 progress: compiler
Post by: sapero on May 24, 2010, 04:17:09 PM
I am now working on optimized operations on constants.
int a = 1 + 2
This simple program currently will generate code to add 1 and 2, but in the future it will evaluate the expression at compile time.

I have already a working idea, the implementation can handle basic operators like +, -, *, /, %, and, &, or, |, ^ (known as xor), <<, >>. It handles integers and floating point constants, with exception for shifts.
Title: Re: IWBasic v2 progress: compiler
Post by: sapero on May 25, 2010, 03:15:11 AM
Done, ID's are now recognized and evaluated, if possible.

There is also POWER operator. A simple "2^8" expression could be evaluated too.
I think to evaluate only integers, because the raw floating point result ("1.2^3.4") can be controlled by the end-user (FPU precision), and the user should have full control over it.
Title: Re: IWBasic v2 progress: compiler
Post by: sapero on May 25, 2010, 04:17:44 AM
Shifts added for 32 and 64 bit integers. Any idea how to handle floats?
1. do nothing, forward to default handling    // current
2. convert to int or int64, shift, convert back
3. shift the raw float/double bits, keep sign bit (or shift it too)
4. separately shift mantissa and exponent
Title: Re: IWBasic v2 progress: compiler
Post by: Ficko on May 25, 2010, 05:47:56 AM
Honestly I don’t have any real life mock up why to shift a floating number at all  :P
but may someone can come up with some reason.
Just leave this question open for feedback for a while.

Otherwise I would vote for 3 (shift it too) but I can’t tell you why just sounds logical. ;D
Title: Re: IWBasic v2 progress: compiler
Post by: sapero on May 26, 2010, 02:45:37 PM
Added missing interfacing between assembler raw data and Basic variables:
declare rectangles as WINRECT
'unsupported yet: declare name[2] as type
'unsupported yet: declare name1,name2 as type

print rectangles.left, rectangles.top, rectangles.right, rectangles.bottom
print rectangles[1].left

_asm
segment .data
rectangles: dd 1,2,10,11 ; rectangles[0]
           dd 3,4,30,31 ; rectangles[1]
segment .text
_endasm


This addition is planned:
declare rectangles as WINRECT = 1,2,10,11 {, next rectangle coordinates}
Title: Re: IWBasic v2 progress: compiler
Post by: LarryMc on May 26, 2010, 03:17:30 PM
I like that.
I could have really used this on the Visual Designer!!!
declare rectangles as WINRECT = 1,2,10,11 {, next rectangle coordinates}
                                                                                  ^
                                                                                  ||
Is it your intention to make a space a delimiter in the parameter list?
Just curious.


LarryMc
Title: Re: IWBasic v2 progress: compiler
Post by: sapero on May 26, 2010, 03:39:11 PM
I used the same syntax as Paul in his help file: function(required, required {, optional {, optional}}).
I don't remember where I saw it. Spaces are optional, only comma character is the delimiter.
declare rectangles as WINRECT=1,2,3,4,5,6,7,8
Title: Re: IWBasic v2 progress: compiler
Post by: LarryMc on May 26, 2010, 03:49:29 PM
My bad!
You had it exactly right.  I just misread it.
Senior moment!!! Sanctuary! Sanctuary! ;D

LarryMc
Title: Re: IWBasic v2 progress: compiler
Post by: Ficko on May 26, 2010, 11:30:27 PM
I like that feature very much as well! :)
Title: Re: IWBasic v2 progress: compiler
Post by: sapero on May 28, 2010, 04:01:16 PM
I am working now on basic optimizations for function/method calls. If you pass a constant number, the value will be pushed on the stack without storing it first in register(s). Because we have floats and doubles, and you are not restricted to pass a float where a float should be. The compiler will convert types silently, if possible:

INT/UINT to int,uint,int64,uint64,float,double,comref,pointer,string,wstring
INT64/UINT64 to int,uint,int64,uint64,float,double
...
Example int->float:
declare go(float f)
go(1)

Integer 1 will be converted to 32-bit float value (0x3F800000) using processor specific FPU commands. Because there can happen data loss or rounding, you should be able to control how the processor should convert between integers and floats. I think I'll add additional command line switch (/F - from Float), where you just pass the "FCW" - Floating point Control Word, providing custom precision (24,53,64 bits) and one from four rounding modes.
It can be a number (0-15, 2bits:precision, 2bits:rounding), or a string: /Fnearest|up|down|toward,24|53|64.
Or should I just keep it as is, using some default settings from operating system, and then you could control the FPU mode by saving all constants in variables (to hide it from the optimization)? What do you think?

By the way, the first topic has been updated - Labels.
Title: Re: IWBasic v2 progress: compiler
Post by: sapero on June 01, 2010, 12:58:21 PM
IWBasic 2 is now able to evaluate expressions in a new conditional keyword $IF:
$ifndef MYVERSION
 $warning "MYVERSION was not defined, assuming default value"
 $define MYVERSION 0
$endif

$if (1=2) or (MYVERSION < 1)
$error "i'm sorry, but something here is wrong"
$endif


Unicode UTF8 file marker (BOM) is now handled for each parsed command/source/include file.
The CONST, $DEFINE and $IF keyword can handle more operators: =, ==, <>, !=, +, -, *, %, /, |, or, || (xor), &, &&, and, <<, >>, !, ~, >, >=, <, <=


Enum has been extended:
enum myenum
one
two = one+1 ' including all operators
three
minusone = -1
endenum
Title: Re: IWBasic v2 progress: compiler
Post by: LarryMc on June 01, 2010, 01:54:16 PM
Meant to ask about this earlier:
$ifndef MYVERSION
  $warning "MYVERSION was not defined, assuming default value"
  $define MYVERSION 0
$endif

$if (1=2) or (MYVERSION < 1)
$error "i'm sorry, but something here is wrong"
$endif


What do the $warning and $error lines actually do?

LarryMc
Title: Re: IWBasic v2 progress: compiler
Post by: sapero on June 01, 2010, 02:22:03 PM
$warning and $error will display a string in Build window, in the IDE (stderror file stream).
$warning does nothing more, $error terminates compilation.

Sometimes you need to stop the compilation if some conditions are invalid, for example outdated header:
$include "designer.inc"
$if designer_header_version < 2
  $error "this example requires an updated version (2) of designer.inc"
Title: Re: IWBasic v2 progress: compiler
Post by: LarryMc on June 01, 2010, 02:33:13 PM
Makes perfectly good sense.
Thanks for the explanation.

LarryMc
Title: Re: IWBasic v2 progress: compiler
Post by: sapero on June 04, 2010, 09:12:19 AM
For today, we have in addition:

__FILE__ and __LINE__ macros you will probably love when compiling in debug mode, to display 'professional' info to your debug window.
print "current error filter: 0x", hex$(__WARNINGFILTER__)
print "current codepage: ", __CODEPAGE__
print "current file: ", __FILE__
print "current line number: ", __LINE__ :
print "compiler version: 0x", hex$(__IWVER__)


$option "warning push" ' optional: save current mask
$option "warning disable:0001"
sub mysub(int pValue)
int t
mysub(t)
endsub
$option "warning pop" ' optional: restore saved mask


$option "/p 1"
sub mysub3(int t)
_asm
mov eax,[t]
_endasm
endsub
$option "/p 0" ' optional: turn it off


I have planned to add new $PRAGMA keyword, but if we already have $OPTION, then why not to extend it?
Title: Re: IWBasic v2 progress: compiler
Post by: sapero on June 06, 2010, 07:41:23 AM
The $USE directive has now additional feature: it will first search for the library in location(s) relative to current file path. If it finds one, the full path at compile time will be passed to linker, else the library will be accessed in defaut way.

Now if you want to share source code with .lib file, just put the library in the same directory where is the source or include file with $use directive. There is no need to copy it to installdir/libs.

$use "mylib.lib" ' if exists CurrentFileDir\mylib.lib - use it, else do default
$use "libraries\\mylib.lib" ' if exists CurrentFileDir\libraries\mylib.lib - use it, else do default
$use "..\\libraries\\mylib.lib" ' if exists CurrentFileParentDir\libraries\mylib.lib - use it, else do default



Imported variables:
You can now import variables form DLL's:import __argc as int
import __wargv as pointer ' call __wgetmainargs to initialize
import __argv as pointer ' call __getmainargs to initialize

$use "msvcrt.lib"
declare cdecl import, __getmainargs(pointer argc, pointer ppargv, pointer ppenv, int expand_wildcards, pointer new_mode)
declare cdecl import, __wgetmainargs(pointer argc, pointer ppwargv, pointer ppwenv, int expand_wildcards, pointer new_mode)

int argc, new_mode, a
pointer pargv, penv
pointer pwargv, pwenv

' initialize __argc and __argv
__getmainargs(&argc, &pargv, &penv, 0, &new_mode)
' initialize __argc and __wargv
__wgetmainargs(&argc, &pwargv, &pwenv, 0, &new_mode)

print "you passed ", __argc-1, "arguments"
for a=0 to __argc-1
print " arg ", a, "= ",*<string>(*<pointer>__argv[a])
print "warg ", a, "= ",*<wstring>(*<pointer>__wargv[a])
next a

Compile as varImport.exe (console target), open command prompt and type: varImport 123 abc "z:\program files"

Imported methods
You can now import methods from DLL's:
classdef.incclass CExporter
declare import CExporter()
declare import _CExporter()
declare import TestMethod()
endclass

DllMain.eba (dll code, compile and create import library)$include "classdef.inc"
export CExporter@CExporter
export CExporter@_CExporter
export CExporter@TestMethod

sub CExporter::CExporter()
print "CExporter constructor called"
endsub

sub CExporter::_CExporter()
print "CExporter destructor called"
endsub

sub CExporter::TestMethod()
print "CExporter TestMethod called"
endsub

WinMain.eba (exe code)$include "classdef.inc"
$use "DllMain.lib"

CExporter c
c.TestMethod()


-------------------------------
June, 7th

The compiler supports intrinsic functions, currently hardcoded in the compiler. Maybe in the future the compiler will read instructions from special library, or from binary file.
Programs that use intrinsic functions are faster because they do not have the overhead of function calls, but may be larger because of the additional code created.

DEFINE_GUID has also intrinsic form, for global and local variables:
GUID _IID_ICustomGuid
DEFINE_GUID(_IID_ICustomGuid, 1, 2,3, 4,5,6,7,8,9,10,12) ' no function call, no code generation
blah()

sub blah()
GUID g
DEFINE_GUID(g, 1, 2,3, 4,5,6,7,8,9,10,11) ' only 4 simple assembly instructions

if (g==_IID_ICustomGuid) ' you can compare two UDT's of the same type
print "equal"
else
print "not equal"
endif
endsub


--------------
June, 17

Added pre-incrementation, post-incrementation, pre-decrementation, post-decrementation operators:
variable++
variable--
++variable
--variable

All the expressions are returning a value, which can be used directly in another expression:

Print numbers 3,2,1,0
int v = 4
while (v--) ' or --v
 print v
endwhile


int x = 4
print x++ ' will print 4, and x will be set to 5. Return current value, then modify
print ++x ' will print 6, and x will be set to 6; First modify, then return new value



Note: when used as function argument, the execution flows from right to left:
print x++,x++ ' will print x+1, x


-------------
Added operator & for strings and wstrings - will be usefull when passing an string as LPARAM in SendMessageA/W
int address = &"text"
address = &L"text"
SendMessageA(d1.hwnd, WM_SETTEXT, 0, &"caption")
Title: Re: IWBasic v2 progress: compiler
Post by: sapero on June 18, 2010, 08:59:28 AM
Added BREAK keyword, to terminate the execution of the nearest enclosing loop (FOR-NEXT, DO-UNTIL, WHILE-ENDWHILE)

WHILE (ShouldEnterThisBlock)
 if (!InitializeDevice()) then break
 if (!SetDeviceParams()) then break

 for a=0 to 4
   if (a=1) then break ' quit from for. BREAK inside FOR will internally use BREAKFOR.
 next a

break
endwhile


Cosmetic change: (s)char and (s)word can be passed to WHILE condition.
char c = 2

while (c)
 print c



Added typecasting: word() schar() ... double(). Currently only casting to double is implemented. This is very usefull when you are using CRT string routines like sprintf, and need to output a float:
sprintf(buffer, "%f", double(VariableOrConst))


Optimizations
I have added some optimizations to code generation - when calling a subroutine/method, assigning a value, and in other places. This is in experimental phase, every day something is changed, and by default is disabled. To enable optimizations, put the line below, above the code you want to be optimized:$option "optimization=on"

I have also added some optimizations to the 'unoptimizable' code parts - removed operand size specifier in assembly instructions like "mov reg,value" or push value. If you want to use this optimization, add the following option to additional assembler options (in project options dialog): -O1. The assembler will find "push 0", and seeing -O1 option, will generate 2 instead 5 bytes of code for the push instruction. Previously the PUSH instruction included operand size specifier "push dword 0", and nasm was disallowed from optimizing it.

June, 19
Optimized DELETE, WHILE and UNTIL.
"WHILE number" and "UNTIL number" will not compare, if "number" is known at compile time.
do
  print
until 1

This example will generate code only for PRINT, as if do-until was not there.


Added T modifier for strings: T"". If you write unicode+ansi friendly programs, use T"string" to generate a string or wstring, based on the current UNICODE condition. If the condition is defined, T"" will generate unicode string, else an ansi string.
$ifdef UNICODE
declare import, testme alias testmeW(wstring p)
$else
declare import, testme alias testmeA(string p)
$endif

testme(T"hello")



Added two new variable types: TSTRING and ITSTRING
TSTRING = T"hello"
$ifdef UNICODE
   ' the first line was WSTRING = L"hello"
$else
   ' the first line was STRING = "hello"
$endif
Title: Re: IWBasic v2 progress: compiler
Post by: Brian on June 18, 2010, 11:50:44 AM
Hi, Sapero,

Is there room for a REDIM command, or is that already in your plans?

Brian
Title: Re: IWBasic v2 progress: compiler
Post by: sapero on June 18, 2010, 01:39:48 PM
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
Title: Re: IWBasic v2 progress: compiler
Post by: Brian on June 19, 2010, 02:57:48 AM
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
Title: Re: IWBasic v2 progress: compiler
Post by: sapero on June 19, 2010, 05:30:13 AM
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
Title: Re: IWBasic v2 progress: compiler
Post by: Brian on June 19, 2010, 10:22:31 AM
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
Title: Re: IWBasic v2 progress: compiler
Post by: sapero on June 20, 2010, 01:43:32 PM
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()
Title: Re: IWBasic v2 progress: compiler
Post by: sapero on June 23, 2010, 11:56:17 PM
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.
Title: Re: IWBasic v2 progress: compiler
Post by: LarryMc on June 24, 2010, 07:25:02 AM
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
Title: Re: IWBasic v2 progress: compiler
Post by: sapero on June 24, 2010, 07:53:30 AM
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.
Title: Re: IWBasic v2 progress: compiler
Post by: LarryMc on June 24, 2010, 08:07:26 AM
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
Title: Re: IWBasic v2 progress: compiler
Post by: sapero on June 24, 2010, 09:48:47 AM
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
Title: Re: IWBasic v2 progress: compiler
Post by: LarryMc on June 24, 2010, 10:21:47 AM
I think that would be a nice little feature.

LarryMc
Title: Re: IWBasic v2 progress: compiler
Post by: sapero on June 28, 2010, 06:22:09 PM
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.
Title: Re: IWBasic v2 progress: compiler
Post by: sapero on June 29, 2010, 03:33:00 AM
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.
Title: Re: IWBasic v2 progress: compiler
Post by: LarryMc on June 29, 2010, 06:44:18 AM
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
Title: Re: IWBasic v2 progress: compiler
Post by: sapero on June 29, 2010, 07:41:18 AM
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...
Title: Re: IWBasic v2 progress: compiler
Post by: LarryMc on June 29, 2010, 08:25:19 AM
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
Title: Re: IWBasic v2 progress: compiler
Post by: sapero on June 29, 2010, 08:40:05 AM
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).
Title: Re: IWBasic v2 progress: compiler
Post by: LarryMc on June 29, 2010, 08:55:09 AM
Sounds good to me!

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

LarryMc
Title: Re: IWBasic v2 progress: compiler
Post by: Guilect on June 30, 2010, 03:20:11 PM
QuoteAdded static keyword
:)
Title: Re: IWBasic v2 progress: compiler
Post by: sapero on July 01, 2010, 07:07:07 AM
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
Title: Re: IWBasic v2 progress: compiler
Post by: LarryMc on July 01, 2010, 07:34:33 AM
Now those are some awesome enhancements.!!!

LarryMc
Title: Re: IWBasic v2 progress: compiler
Post by: Ficko on July 01, 2010, 07:52:39 AM
Quote from: Larry McCaughn on July 01, 2010, 07:34:33 AM
Now those are some awesome enhancements.!!!

LarryMc

Yep, keep going!  ;D :D
Title: Re: IWBasic v2 progress: compiler
Post by: zaphod on July 01, 2010, 10:01:46 AM
Hello Sapero !

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

Do you need some beta testers ?
Title: Re: IWBasic v2 progress: compiler
Post by: billhsln on July 01, 2010, 10:25:16 AM
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
Title: Re: IWBasic v2 progress: compiler
Post by: sapero on July 01, 2010, 11:00:57 AM
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.
Title: Re: IWBasic v2 progress: compiler
Post by: billhsln on July 01, 2010, 11:33:18 AM
I was thinking more in the line of w1.hWnd and other things that are already predefined.

We do:

WINDOW w1

under that w1.hWnd is valid, but w1.hwnd is not.  That is the list I was wondering about, since we have no control over those field names.

Thanks,
Bill
Title: Re: IWBasic v2 progress: compiler
Post by: sapero on July 01, 2010, 01:11:58 PM
The compiler will search in all possible locations (using case insensitive method) to give you a hint, with the proper case: "did you meant TheSymbol ?"

sub b()
point p
endsub

Error message: File: x.eba (19) unknown type point, did you meant POINT ?
Title: Re: IWBasic v2 progress: compiler
Post by: Ficko on July 01, 2010, 01:14:48 PM
Quote from: sapero on July 01, 2010, 01:11:58 PM
to give you a hint with the proper case: "did you mean hWnd ?"

And propably you have some enchanced Intellisense for the enchanced compiler in your mind as well ?  ;D ;)
Title: Re: IWBasic v2 progress: compiler
Post by: sapero on July 03, 2010, 04:43:34 AM
The compiler could generate intellisense database for use in the IDE, why not?

New additions:
* variable = new type
* variable = new type[count]
* typedef newtype structureName
* typedef newtype className
* typedef newtype interfaceName
* interface name, base_interface interface IMyInterface, IUnknown ... endinterface
* LEN(className)

If A in "typedef A B" is already defined as something other than B, the compiler will show an error:
typedef MYPOINT POINT
typedef MYPOINT POINTL ' Error: MYPOINT already defined as struct POINT



Added NOVTABLE option for classes:
$option "novtable on" ' yes, enable, on, 1
class CClass
int m_value
endclass
$option "novtable off" ' no, disable, off, 0

I am planning to add support for classes with the base on a structure, so novtable will be a great feature:
class CRect, WINRECT
"declare virtual" will be automatically disabled while novtable option is active, because a class without virtual functions table cannot have virtual methods.
Title: Re: IWBasic v2 progress: compiler
Post by: LarryMc on July 03, 2010, 12:37:29 PM
OK, time for me to be the 'village idiot' again.

What does the NOVTABLE option do for me as a regular IWBasic user?
How does it benefit me and/or why would I want to use it?

LarryMc
Title: Re: IWBasic v2 progress: compiler
Post by: sapero on July 03, 2010, 01:14:55 PM
It is used when you want to create a class compatible with a structure, where size of the class must be eual to size of structure.

It does not shift all class variables by 4 bytes forward.
Currently if you build a class compatible with WINRECT, and will access Left member, you need to cast the 'this' pointer to WINRECT

class CWinRect ' compatible with WINRECT
' pointer _VTABLE_  ' hidden class member at offset +0
' int left -> not possible, we are at offset +4 where is WINRECT.top
int top
int right
int bottom
declare GetLeft(),int
declare GetTop(),int
endclass

sub CWinRect::GetLeft(),int
return*<WINRECT>this.left ' same as *<int>this
endsub

sub CWinRect::GetTop(),int
return top ' or return*<WINRECT>this.top
endsub


When you turn off vftable, the first variable in our class will be at offset +0, as it is in regular structure:
$option "novtable on"
class CWinRect
int left ' -> possible, we are at offset +0
int top
int right
int bottom
endclass

Or without $option:
class CWinRect, WINRECT
endclass


In Aurora you could define a class with the same name as previously defined structure, but still to access structure members in a method of your class, you needed to cast 'this' pointer.
class RECT
{
declare width(),int {return *(RECT)this.right - *(RECT)this.left;}
}


So, to make it easier and remove the casting, use novtable option, and access all members directly.


Example program:
class CWinRect
int left
int top
int right
int bottom
endclass

CWinRect c

c.left  = 1
c.top   = 2
c.right  = 3
c.bottom = 4

pointer p = &c
print "values:", *<int>p[0], *<int>p[1], *<int>p[2], *<int>p[3]
print "offsets: ", &c.left-&c, &c.top-&c, &c.right-&c, &c.bottom-&c

Output:
values:4206666 1 2 3
offsets: 4 8 12 16


With vtable disabled:
values: 1 2 3 4
offsets: 0 4 8 12
Title: Re: IWBasic v2 progress: compiler
Post by: LarryMc on July 03, 2010, 02:21:20 PM
So, would the default would be "novtable off" ?

LarryMc
Title: Re: IWBasic v2 progress: compiler
Post by: sapero on July 03, 2010, 06:12:23 PM
Yes, vtable by default will be enabled (novtable off).
The new compiler must be compatible with previous versions, so any changes will be enabled only at user request.

Additional tools like NEW without braces, or derieved interfaces, which do not interfere with the official syntax, are available at any time.

---
Improved error tracking:
* duplicate declaration is now detected better than proviously, and the (clickable) location of original definition will be shown
File: new.eba (8) Error: duplicate definition of variable or label: bottom
File: new.eba (7) See previous declaration

* whenever possible, the word (variable/function/class/method/typedef) name will be displayed, if it causes an error. Example: duplicate definition/class/interface.

With the new improvement, I have found two duplicates in rpc includes: a symbol was defined as pointer in file A, and as structure in file B.
Title: Re: IWBasic v2 progress: compiler
Post by: sapero on July 04, 2010, 10:27:11 AM
Added structured exceptions handling:
$include "windowssdk.inc" ' need EXCEPTION_POINTERS and EXCEPTION_RECORD
int a=0
try
print "dividing by zero"
print 1/a
print "divide ok"
endtry

catch
print "exception code: 0x", hex$(GetExceptionCode())

pointer pep = GetExceptionInformation()
settype pep,EXCEPTION_POINTERS

print "exception address: 0x", hex$(*pep.*<EXCEPTION_RECORD>ExceptionRecord.ExceptionAddress)
endcatch

Output:dividing by zero
exception code : 0xC0000094
exception address: 0x40141E
finished


LEAVE will immediatelly quit from try-endtry block.
THROW requires an argument (a pointer, number, string) - generates in-place exception with code=0, passing the pointer to use in the next catch block:
try
throw "unable to divide by zero"
endtry

catch
pointer pep = GetExceptionInformation()
settype pep,EXCEPTION_POINTERS
settype *pep.ExceptionRecord, EXCEPTION_RECORD
' optional validation
' *pep.*ExceptionRecord.ExceptionCode must be 0
' *pep.*ExceptionRecord.NumberParameters must be >0
if (!*pep.*ExceptionRecord.ExceptionCode and *pep.*ExceptionRecord.NumberParameters)
' get the first integer from ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]
int pText = *pep.*ExceptionRecord.ExceptionInformation[0]
'print hex$(&"unable to divide by zero")
'print hex$(pText)
print *<string>pText
endif
endcatch


Some internals for advanced users:
Pointer to EXCEPTION_POINTERS structure is stored at ThreadEnvironmentBlock->UserReserved[0]. It will be allocated once, when handling the first exception.
The format of data stored in TEB->UserReserved[0] is:
type SEH_TLS ' custom structure
EXCEPTION_POINTERS ep ' to make GetExceptionInformation compatible with MSDN
EXCEPTION_RECORD er
CONTEXT ctx
BOOL HadException ' if TRUE, next CATCH will execute
endtype

GetExceptionInformation will return a direct pointer to this structure, initialized to the snapshot of thread state, when an exception occured.
Because EXCEPTION_POINTERS is the first member, GetExceptionInformation can be used to gain access to EXCEPTION_POINTERS and SEH_TLS.
When entering TRY block, the HadException member will be set to FALSE, if the SEH_TLS structure has been allocated.
When entering CATCH block, there will be a check if HadException is TRUE. If SEH_TLS is not allocated (no exception) or when HadException is FALSE, execution will continue at ENDCATCH.

GetExceptionCode and GetExceptionInformation are intrinsic, so there is no function call, just inline code. GetExceptionInformation can return NULL, if there was no exception previously, but inside catch-endcatch it will always return a valid pointer.

Nesting level for TRY block is unlimited, each level takes 44 bytes from stack memory to save important CPU registers, and the code address of ENDTRY, where a jump is made on exception.

TODO:
* handle goto inside try-endtry.
sub function1()
try
try
goto     ' todo
break    ' handled
breakfor ' handled
return   ' handled
end      ' handled
endtry
endtry
endsub
Title: Re: IWBasic v2 progress: compiler
Post by: sapero on July 05, 2010, 04:17:17 PM
Added construction and destruction for classes defined in a structure (any level)
class myclass
declare myclass()
declare _myclass()
endclass

type child
myclass c
endtype

type mytype
myclass a
child   b
endtype

mytype t
end

sub myclass::myclass()
print "constructor"
endsub

sub myclass::_myclass()
print "destructor"
endsub


Output:
constructor
constructor
destructor
destructor


EDIT: the same applied to new and delete.
Title: Re: IWBasic v2 progress: compiler
Post by: sapero on November 27, 2010, 11:01:34 PM
There are the latest updates:
* New "strict"option - the compilerwill be showing all possible typos. For example, if you use undefined variable type in function declaration, you will be notified about.
declare mysub(MYTYPE p) ' use of undefined type
typedef MYTYPE int ' declaration

* ebstd.incc header will be parsed first, then all other incc files, using the default sorting algo from FindNextFile.
* Added additional location for include-directory list: INCLUDE environment variable. The search order for searching files accessed by $INCLUDE is:
  1. The directory of currently parsed file
  2. The Include directory
  3. User directory list added in the /i command lines witch or "IncludePath" option
  4. The Bin directory
  5. The list from INCLUDE environment variable. The format is same as in PATH variable: "c:\dir1;d:\dir2;e:\dir2\dir 5; ... z:\last dir".

IDE updates:
* Clicking a keyword with CONTROL key pressed with select the whole word.
* Added fold points to do-until, for-next, while-endwhile, if-else-endif, select-endselect.

There is an additional tool for configuring per user global (default) settings. You can choose which options should be ON/OFF: case sensitive compilation, default state for autodefine, state for strict option, ..., additional preprocessor definitions and additional include directories.
This is a small property sheet program.
Title: Re: IWBasic v2 progress: compiler
Post by: Brian on November 28, 2010, 03:20:10 AM
Looking good, Sapero - I will certainly be ordering the new version
when it surfaces

Can't be left behind...

Brian
Title: Re: IWBasic v2 progress: compiler
Post by: Barney on November 28, 2010, 05:43:54 AM
Hopefully I will be getting my new credit card just in time to purchase v2.0 :) It's looking very nice. I also hope that one day (sooner rather than later) we'll also have a 64-bit version, too.

Barney
Title: Re: IWBasic v2 progress: compiler
Post by: LarryMc on November 29, 2010, 03:19:55 PM
Quote from: sapero on July 03, 2010, 06:12:23 PM
Yes, vtable by default will be enabled (novtable off).
The new compiler must be compatible with previous versions, so any changes will be enabled only at user request.

Additional tools like NEW without braces, or derieved interfaces, which do not interfere with the official syntax, are available at any time.

---
Improved error tracking:
* duplicate declaration is now detected better than proviously, and the (clickable) location of original definition will be shown
File: new.eba (8) Error: duplicate definition of variable or label: bottom
File: new.eba (7) See previous declaration

* whenever possible, the word (variable/function/class/method/typedef) name will be displayed, if it causes an error. Example: duplicate definition/class/interface.

With the new improvement, I have found two duplicates in rpc includes: a symbol was defined as pointer in file A, and as structure in file B.
When you get this error
File: new.eba (8) Error: duplicate definition of variable or label: bottom
File: new.eba (7) See previous declaration

the See Previous line # is one greater then the actual line.

LarryMc
Title: Re: IWBasic v2 progress: compiler
Post by: sapero on November 29, 2010, 05:23:56 PM
Thanks for this info!
Fixed.

I have added two special return types: FPU and __m128. The names are temporary (I am open for suggesions).

The FPU type marks a function as returning a float/double in the ST0 FPU register (for Bass users).
type FPU
endtype

declare GetFpu(),FPU

print GetFpu()
end


$asm
align 4
GetFpu:
fld qword [mydata]
ret

segment .data
mydata:
dq 1.23456789
$endasm


The __m128 type marks a function as returning an array of 4 floats or two doubles in XMM0 register (SSE users). Because the data is 128-bit, it is copied to temporary heap memory, in the same way as you would return a structure or string.
union __m128
float m128_f32[4]
float f32[4]
double d64[2]
endunion

declare get_xmm_value(),__m128

__m128 v = get_xmm_value()

print v.m128_f32[0], v.f32[1], v.f32[2], v.f32[3]

end
$asm
align 4
get_xmm_value:
movups xmm0,[myvalue]
ret

segment .data
align 16

myvalue:
dd 1.0, 2.0, 3.0, 4.0
$endasm


I forgot to say in my previous reply, that console programs, when running from the IDE will be executed in the default command processor window, and the window will be paused when your program terminates. You don't need to wait for a key press before terminating.
Title: Re: IWBasic v2 progress: compiler
Post by: Ficko on November 30, 2010, 04:06:42 AM
Awesome !  :D
Title: Re: IWBasic v2 progress: compiler
Post by: LarryMc on November 30, 2010, 11:21:27 AM
Sapero

This is why my INI file code was broke and not due to you new headers.
The IF statement in test one is what was in my existing code and worked fine in EB/IWB (ver prior to last).
It doesn't work in the current version.

test two works with all versions.

LarryMc

openconsole

string tp=getstartpath()+ "test.cfg"
string section= "position"
string key= "left"

print "start"
print
print "Len(tp) ",Len(tp)
print "Len(section) ",Len(section)
print "Len(key) ",Len(key)
print
print "test one"
If ((Len(tp) > 0) & (Len(section) > 0) & (Len(key) > 0))
print "success"
else
print "failure"
EndIf
print
print "test two"
If (tp<>"" & section<>"" & key<>"")
print "success"
else
print "failure"
EndIf
print
print "finished"
waitcon
closeconsole
end
Title: Re: IWBasic v2 progress: compiler
Post by: sapero on November 30, 2010, 02:23:30 PM
Larry, your program displays twice Success. There was a bug in the "compare" code part (optimizations), but I have fixed it a week ago. You must still have the buggy parser.

int a=1, b=1
if ((a+1)>b) then action() ' BUG: never true
Title: Re: IWBasic v2 progress: compiler
Post by: LarryMc on November 30, 2010, 03:28:23 PM
I downloaded the newest installer I could find (dated 11/23/10) and it has that bug in it.

Reckon LarryS hasn't gotten around to a newer installer with your latest.

So, to keep going forward with the Visual Designer 2.0 I just changed the comparisons to <>"".

Thanks Sapero

LarryMc
Title: Re: IWBasic v2 progress: compiler
Post by: sapero on January 16, 2011, 04:35:43 AM
Added automatic string conversion (from/to unicode) when returning from a function:
$define UNICODE
$define WIN32_LEAN_AND_MEAN
$include "windowssdk.inc"

MessageBoxW(0, function1(), L"ansi->unicode")
MessageBoxA(0, function2(), "unicode->ansi")

sub function1(),wstring
return "hello" ' will be converted to unicode, using the current codepage
endsub

sub function2(),string
return L"hello" ' will be converted to ansi, using the current codepage
endsub


Added $ELIFDEF and $ELIFNDEF. All the $IF/$ELSE conditions can be mixed:
$IFDEF something
...
$elif VERSION>3
...
$elif !(VERSION<3)
...
$ELIFDEF DEMO_VERSION
...
$ELIFNDEF TIME_LIMITED
...
$ELSE
...
$ENDIF


Added single-byte initializer for structures (use it instead calling RtlZeroMemory):
sub ExecuteProcess()
STARTUPINFO si = 0 ' up to 255
STATDATA sdata

sdata.formatetc = 0


Added partial interface support for NEW command:
The CLSID and IID are automatically created from interface name: _CLSID_name, _IID_Iname, so it is not possible (yet) to create a new instance of an interface with different name as the class.
IProgressDialog unk = new IProgressDialog
'IProgressDialog unk = new IProgressDialog[1] ' count is ignored
'IProgressDialog unk = new(IProgressDialog,1) ' count is ignored


The compiler created temporary files in /bin directory. This is no more true: the temporary $$$lib.link will be created in the current-directory by default, or it will append the data to a file specified in LIB_LINK_PATH environment variable. The IWBasic IDE, when compiling a project, initializes LIB_LINK_PATH environment variable to PROJECT_DIR\$$$lib.link before compiling all source files, so that the parser will append all referenced .lib files to PROJECT_DIR\$$$lib.link file.

When using the /P option (for easier variables access in inline assembly) the compiler will check all formal and local variable names for possible conflict with assembly reserved keywords. Use mixed case in variable names if you get a warning.
$option "/P"
sub asm_test(int ret) ' warning: 'ret' variable is conflicting with ret/retn instruction.
sub asm_test(int Ret) ' no warning


Added #define - very helpful for ResEdit fans. Converting #define to $define each time you save the resource script, is now optional.

Added "ZeroVariables" option - when active, all local variables will be initialized to zero.

Added a check to the part handling assignments - it will warn you if the number you want to assign exceeds the bounds of target variable:
SCHAR a = 128 ' warning
a = -129 ' warning
SWORD b = 32768 - warning
b = -32769 ' warning


Added a new item to Tools menu: Edit compiler options. It will open a property sheet where you can set the default state of 11 compiler options, define additional include paths, and specify some default conditions or constants.

Comments in inline assembler will have the color of a comment (green).
Title: Re: IWBasic v2 progress: compiler
Post by: sapero on January 20, 2011, 05:31:35 PM
Added $REGION and $ENDREGION - just another version of 'REGION and 'ENDREGION.
The optimizer now includes tracking of esi,si,edi,di,ebx,bx,bl registers - if they are not modified in a subroutine, the assembly code will not include the code for saving and restoring them.

Working on a plugin system for the parser, which will make possible to generate code for any platform/cpu (Windows/Linux/Mac/Arm/Pic/Atmel...), assembler, or additional high level compiler.
Title: Re: IWBasic v2 progress: compiler
Post by: LarryMc on January 20, 2011, 06:21:07 PM
Quote from: sapero on January 20, 2011, 05:31:35 PM
Working on a plugin system for the parser, which will make possible to generate code for any platform/cpu (Windows/Linux/Mac/Arm/Pic/Atmel...), assembler, or additional high level compiler.

NICE!!!!!!!!!!!!!!

LarryMc
Title: Re: IWBasic v2 progress: compiler
Post by: Doc on January 20, 2011, 08:00:38 PM
Ditto what LarryMc said for sure!

-Doc-
Title: Re: IWBasic v2 progress: compiler
Post by: Barney on January 21, 2011, 12:11:25 AM
Quote from: sapero on January 20, 2011, 05:31:35 PMWorking on a plugin system for the parser, which will make possible to generate code for any platform/cpu (Windows/Linux/Mac/Arm/Pic/Atmel...), assembler, or additional high level compiler.
Now you are talking!  :)
Nice!

Barney
Title: Re: IWBasic v2 progress: compiler
Post by: Logman on January 21, 2011, 06:35:10 AM
As always, you are doing a bang up job--good enough to keep me with you.

I do have a few thoughts about missing capabilities in IWBasic that I think would substantially improve the language:

1. Have we given any thought to adding a capability to use/create MACROS in IWBasic?

2. If I'm not mistaking, the IDE doesn't have an auto indent capability when writing code. I really miss this.

3. The IWBasic compiler doesn't remove unused code like other compilers I've used. Is this still true? Might be a consideration down the road.

4. One of the greatest features of the IWBasic compiler is that it is a multi-pass compiler, which means we can put code anywhere in the program and don't have to declare all subs and etc. beforehand. I hope IWBasic remains a multi-pass compiler.

5. I'd like to see built-in Mutex and Thread capability rather than having to use the Win API to build code to do these processes.

6. Since I habitually incorporate assembly code in my IWBasic programs, I'd like to be able to update the NASM compiler in the BIN directory to keep pace with NASM development.  

7. Probably still a long way off, but IWBasic really needs to be implemented in 64-bit over the next year.

Just some thoughts.

By the way, I'd be willing to help out by writing and maintaining an IWBasic User's Manual if no one else is doing this.

Logman ;D
Title: Re: IWBasic v2 progress: compiler
Post by: LarryMc on January 21, 2011, 06:56:27 AM
Quote2. If I'm not mistaking, the IDE doesn't have an auto indent capability when writing code. I really miss this.
I don't know when it was added but I know EB 1.735 has auto indent.
It's down at the botton of the dialog where you set the IDE code colors.

LarryMc
Title: Re: IWBasic v2 progress: compiler
Post by: Brian on January 21, 2011, 08:47:52 AM
Quote from: sapero on January 20, 2011, 05:31:35 PM
Working on a plugin system for the parser, which will make possible to generate code for any platform/cpu (Windows/Linux/Mac/Arm/Pic/Atmel...), assembler, or additional high level compiler.

Fancy that - my last program was written for the PC, and I was asked if it was
possible to produce it for the Mac, as well. Not at all possible now.
But very possible in the future, methinks. Good news!

Brian
Title: Re: IWBasic v2 progress: compiler
Post by: talun on January 22, 2011, 12:30:03 AM
QuoteWorking on a plugin system for the parser, which will make possible to generate code for any platform/cpu (Windows/Linux/Mac/Arm/Pic/Atmel...), assembler, or additional high level compiler.

Console and/or GUI mode?

Sergio
Title: Re: IWBasic v2 progress: compiler
Post by: ckoehn on January 22, 2011, 06:49:23 AM
Great!  Now if I can find a compiler for WinCE.  Need it already!!!  Been doing some programming for GPS Units and using eVB which works but is outdated.  ;D

Clint
Title: Re: IWBasic v2 progress: compiler
Post by: LarryMc on January 23, 2011, 03:25:10 PM
We're getting closer to the release of Ver 2.0.
I'm basically the holdup; trying to get all the changes/enhancements documented in the help file.
I've got it to the floorboard but I'm always slow at documentation.

LarryMc
Title: Re: IWBasic v2 progress: compiler
Post by: Logman on January 24, 2011, 05:10:18 AM
Boy, don't I feel stupid. I've been using the IDE for two years now without the indent feature--wishing it had one--and all along it did. I searched in the manual for this and since I didn't initially see it, I've just lived with it.

Thanks  for pointing this our Larry. I sure missed it.

Can't wait for the release of 2.0.

Logman
Title: Re: IWBasic v2 progress: compiler
Post by: sapero on January 25, 2011, 10:07:05 AM
Sergio, what do you mean with gui/console? These two are not related with the compiler, the linker cares about the subsystem.

Added OEM string modifier, to create strings with diacritical characters, which can be displayed in console window without calling CharToOem api:
print OEM"Ã,,…äáàâã"
Internally the string is encoded to an unicode string using the current codepage, then CharToOemW api is called, to convert it to console OEM. This api on Windows ME/98/95 is supported by Microsoft layer for unicode, so you will need to install it on the older systems, if you want to compile prorams with the OEM modifier.
The compiler will warn you if it fails to load unicows.dll.
On Windows 2000 or newer, the required api is available in user32.dll.

I have now a question: how would you like to set IWBasic IDE to unicode mode (utf8) ?
a) File/New/IWBasic unicode source file.
b) a popup menu named "Encoding" with ansi and utf8 items.
c) other (describe).
Title: Re: IWBasic v2 progress: compiler
Post by: Barney on January 25, 2011, 02:27:15 PM
Quote from: sapero on January 25, 2011, 10:07:05 AM
I have now a question: how would you like to set IWBasic IDE to unicode mode (utf8) ?
a) File/New/IWBasic unicode source file.
b) a popup menu named "Encoding" with ansi and utf8 items.
c) other (describe).
a option is probably the best for most users
I'd prefer b option but not as a popup menu. A switch on the toolbar will do nicely.

Barney
Title: Re: IWBasic v2 progress: compiler
Post by: talun on January 26, 2011, 01:48:32 AM

QuoteSergio, what do you mean with gui/console? These two are not related with the compiler, the linker cares about the subsystem.

Hi Sapero,

I'm sorry but I was unclear.
I wanted to know if you can create GUI applications using the normal IWBASIC syntax without having to resort to specific functions of the operating system (linux, MAC...).

bye

Sergio
Title: Re: IWBasic v2 progress: compiler
Post by: sapero on January 26, 2011, 04:05:26 AM
Hopefully, the compiler's plugin will be responsible for conversion of the internal Basic commands for the target operating system.
Any configuration will be passed to the compiler in some universal form, for example: in the $OPTION directive:
$OPTION "plugin linux\qt.dll option1=value1 option2=value2 ..."

For example a plugin for Android OS could generate a complete java project, and then launch apkbuilder.bat to create an .apk file (or an native Linux executable) ready to upload to user's phone.
Title: Re: IWBasic v2 progress: compiler
Post by: Egil on January 26, 2011, 05:21:51 AM
Quote from: sapero on January 25, 2011, 10:07:05 AM
I have now a question: how would you like to set IWBasic IDE to unicode mode (utf8) ?
a) File/New/IWBasic unicode source file.
b) a popup menu named "Encoding" with ansi and utf8 items.
c) other (describe).

Option a would be my choice :)

Egil
Title: Re: IWBasic v2 progress: compiler
Post by: sapero on January 27, 2011, 04:15:56 AM
Added $MACRO directive:
$macro sum(a,b) (a+b)
$macro sum(a,b,c) (a+b+c)

print sum(1,2)
print sum(1,2,4)


A macro will override a function with the same name and number of parameters:
declare import,sum(int a,int b),int
declare import,sum(int a,int b,int c),int
print sum(1,2) ' function
$macro sum(a,b) (a+b)
print sum(1,2) ' macro
print sum(1,2,3) ' function


You can call a function from inside your macro:
$macro ListboxDeleteAllItems(win,id) (SENDMESSAGE(win,LB_RESETCONTENT,0,0,id))

ListboxDeleteAllItems(d1,IDC_MYLISTBOX)


A macro can be undefined: $UNDEF MacroName NumberOfParameters
$undef sum 2
$endef sum 3


To check if a macro is defined, use $IFDEF MacroName.
Title: Re: IWBasic v2 progress: compiler
Post by: Logman on January 27, 2011, 05:07:31 AM
Horay for MACROS.

Logman  :)
Title: Re: IWBasic v2 progress: compiler
Post by: sapero on January 28, 2011, 12:07:14 PM
Macros are supported in enumerations and $IF conditions.

Added a special macro: defined(name) - returns TRUE if the parameter 'name' is defined. The 'defined' keyword is now reserved.
$define MYCOND
$define WIN32
'$define MAC

$if defined(WIN32) && defined(MAC)
$error "WIN32 and MAC is defined"
$elif defined(WIN32) && defined(MYCOND)
$error "WIN32 and MYCOND is defined"
$elif defined(WIN32) && !defined(MYCOND)
$error "WIN32 is defined, but MYCOND is not defined"
$elif defined(MAC) && defined(MYCOND)
$error "MAC and MYCOND is defined"
$elif defined(MAC) && !defined(MYCOND)
$error "MAC is defined, but MYCOND is not defined"
$else
$error "unhandled case"
$endif


The look-up precedence in macros is:
1. symbols from macro definition - $macro name(this, and_this) (expression)
2. variables
3. constants
So if you refer "A" symbol in a macro, the compiler will first try to find macro parameter A, then A variable, and finally an constant A.
Title: Re: IWBasic v2 progress: compiler
Post by: LarryMc on January 28, 2011, 03:25:22 PM
As I mentioned earlier I'm working on the Docs for Ver 2.0.
Right now I figure I'm around 1/2 way through adding all that needs to be added to support the V2.0 changes (not including what Sapero has added in the last few days).

I generated a PDF help file a few minutes ago.  It has 86 more pages than the version I have that came with EB 1.737.

LarryMc
Title: Re: IWBasic v2 progress: compiler
Post by: WayneA on January 29, 2011, 06:00:40 PM
This is an exciting time in the history of IBasic and its derivatives.

Great work sapero!
Title: Re: IWBasic v2 progress: compiler
Post by: sapero on January 30, 2011, 03:11:26 AM
Thanks!
Added support for multiple expressions in a single macro, use ":" to separate them
$macro INITPOINT(pt,xx,yy) (pt.x=xx : pt.y=yy)

POINT p
INITPOINT(p,3,4)


Note: the = operator inside a macro will always assign a value, and == will compare. This exception makes possible to assign values in macros.

If you define a macro with multiple expressions, only the first expression (leftmost) can be used to return a value. The return value from additional expressions will be ignored, and if neccessary, temporary strings or UDT's will be deleted.
$macro mymacro(a,b)(a:b)
print mymacro(APPEND("a","b"), APPEND("c","d"))

The first APPEND will be printed, the second APPEND will be executed and it's temporary result will be deleted before the macro returns.

$END directive will mark the end of file, any text following it will be ignored.
Title: Re: IWBasic v2 progress: compiler
Post by: sapero on February 09, 2011, 01:42:14 PM
The LEN statement can be now used in expressions requiring a constant value, known at compile time. Almost any expression passed to LEN is supported, but string.
const MYCONST = len(1) + len(int) + len(myarray[1,2,3,4,5]) + len(my_int_variable) + len(*<POINT>p)

A function name passed to LEN will return the size of this subroutine. But the subroutine must exists in current source file (or in any included file). In this case, LEN will complete while assembling.

A new statement SIZEOF will always return the size in bytes of memory reserved for a variable (numbers, arrays, strings, classes, ...). SIZEOF will always evaluate at compile time, without generating code. SIZEOF(1) is 4, sizeof(string) is 255, and so on.
iwstring iw[32]
' compute the maximum number of characters
const NumberOfCharacters = sizeof(iw) / sizeof(iw[0])
print NumberOfCharacters ' 32


A subroutine definition can wrap to multiple lines. There is only one requirement (as for today): the "_" character must be the last in a line, not even space is allowed.
sub multiline( /*comments go here*/_
int a,_
int b)
print a,b
endsub


GLOBAL keyword is now accepting multiple variables:
GLOBAL a,b,c,d1

Added more options and command line switches, see first post.
The parser will load $$$lib.link file to memory, to prevent generating multiple libs with the same name. Relative libs can be resolved (to full paths) at compile time, and optionally the relative or full paths can be quoted.

BUGFIX: if you compile a file with tilde in the name (like "~.eba" or "~.iwb"), the assembler stops with critical error at the first "%line" macro (such file name should be quoted).
Title: Re: IWBasic v2 progress: compiler
Post by: sapero on February 13, 2011, 07:22:22 AM
I have finished with the first implementation of thread-private variables
Quote from: MSDNThread Local Storage (TLS) is the mechanism by which each thread in a given multithreaded process allocates storage for thread-specific data. In standard multithreaded programs, data is shared among all threads of a given process, whereas thread local storage is the mechanism for allocating per-thread data.
declare import,CreateThread(pointer q,int q,int q, pointer q,int q,pointer q),int
declare import,WaitForSingleObject(int q,int q)
declare import,CloseHandle(int q)

' define some per-thread variables
thread int x,y
thread POINT pt

' main thread
x = 1
y = 2
pt.x = 3
pt.y = 4

print "main thread:"
DumpVariables(0) ' shows 1,2,3,4

' run a secondary thread

print "\nsecondary thread:" ' shows 0,0,0,0
int  dwId
int hThread = CreateThread(0,0,&DumpVariables,0,0,&dwId)
if (hThread)
WaitForSingleObject(hThread, -1)
CloseHandle(hThread)
endif

sub DumpVariables(int reserved)
print "thread int x = ",x
print "thread int y = ",y
print "thread POINT pt.x = ", pt.x
print "thread POINT pt.y = ", pt.y
endsub


The thread keyword must be specified first, to take effect (first in a line). The compiler updates an internal UDT as it sees the thread variables, so if you want to share thread variables between multiple source files, define them in an include file, or use the same order in all source files.
Title: Re: IWBasic v2 progress: compiler
Post by: Logman on February 14, 2011, 05:05:15 AM
Nice work Sapero. It will be great having a native THREAD command/capability in IWBasic. Will there be an accompanying MUTEX command?

Logman
Title: Re: IWBasic v2 progress: compiler
Post by: sapero on February 14, 2011, 06:10:18 AM
Threads and mutexes are native resources, easy to use and implement a wrapper. Each time I need to use a mutex, I do it in a different way. Using the direct apis is always better than calling a general and very limited command. A Lock/Unlock mutex commands could be implemented in a simple class with two methods. But is we start writing wrappers for all possible things, it will be Basic-MFC (with the M renamed) :)
Could you give me a suggestion, example code - how do you see it?

Recent changes:
You can include an .asm file directly from your IWBasic source file, using the build-in $INCLUDE directive. You can also add .asm file to your IWBasic project. File name extension must be .asm, to handle it correctly.

You can change the order of variables definitions from right to left, to left to right.
int a,b,c,d ' d is defined first, then c,b,a  (default)
$option "DimOrder left"
int e,f,g,h ' e will be defined first, then f,g,h
Title: Re: IWBasic v2 progress: compiler
Post by: LarryMc on February 14, 2011, 06:21:08 AM
$option "DimOrder left"
would imply there is a
$option "DimOrder right"to undo it?
I only ask because I don't know why I would use the option in the first place. ???

LarryMc
Title: Re: IWBasic v2 progress: compiler
Post by: sapero on February 14, 2011, 06:33:39 AM
There is push,pop,left,right and default. If you don't care in which order the variables are defined, you don't need to use this option.
If you for example convert some C/C++ code - a structure, the order in C is "left" and IWBasic uses "right":

struct POINT
{
int x,y; // x is first
};

' 1.
type POINT
int y,x ' x is first
endtype

' 2.
type POINT
int x ' x is first
int y
endtype

' 3.
$option "DimOrder left"
type POINT
int x,y ' x is first
endtype
Title: Re: IWBasic v2 progress: compiler
Post by: LarryMc on February 16, 2011, 02:09:25 PM
I've been working on the documentation for several weeks now for Ver 2.0.

The problem is that Sapero can make enhancements/changes faster than I can document them properly in the help file.
This means that I'm loosing ground almost every day and the release date for 2.0 is getting pushed back further and further.

After discussing the problem with LarryS the following has been decided.
Today is the cutoff date for changes that will appear in Ver 2.0.
This topic is going to be locked and not changed further.
As a result I will have a firm endpoint for my documentation effort.
When I'm finished then 2.0 will be released.

Sapero will continue on with his enhancements/changes which will be included at a later date in ver 2.1.
In a private area of the forums, Sapero will document his efforts on 2.1.  When 2.0 is released his postings for 2.1 will be moved to the open forum for all to see.

LarryMc
Title: Re: IWBasic v2.0 progress: compiler
Post by: Rock Ridge Farm (Larry) on February 17, 2011, 01:02:50 PM
We have drawn a line in the sand.
IWBasic2.0  is going to release as soon as Larry Mc can wrap up the help files.
I expect to release no later than Mar 1 (hope, hope)

Larry