All variables must be declared before they are used (however impilcit declaration by assignment is possible).
variable_declaration: type_name variable_names_separated_by_comma
or outer struct_type variable_name
left_value = expression
left_value:
- variable
- parameter_attribute
parameter_attribute:object_paramter_name one or more ( . class_attr_name )
variable:
- simple_variable_name
- object_variable_name
- variable_attribute:object_variable_name one or more ( . class_attr_name )
Not all variables or parameters are allowed at left side of assignment.
At left side we can have variable or parameter of the left_value_type or outer struct_type variable.
left_value_type:
- immediate_type (int, byte)
- str
- int64
- float80
- object_type
The same type at both sides or all type must be used.
i1=3 #simple variable
c1=c2 #object variable
c1.a=1 #object variable c1 class attribute a
c2.c1.s="Ala" #object variable c2 class attribute c1 class attribute s
For types: byte, char, int, str operation simply makes copy, for list, mem, classes objects references are assigned
l1=l2
- dereference previous l1 objects
- write l2 object reference to l1
- increment l2 object reference count
expression:
- constant
- left_value
- parameter
- function_call
- [] empty list
- reminder reminder from divide operation
- unary_operation expression
- expression binary_operation expresion
- expression one or more (add_sub_operation expression)
- expression one or more (multiply_divide_operation expression)
- parenthesized_expression
- new_expression
- type_id_expression
i1=3 #constant
i2=i1 #variable or parameter
i2=cl1.i
i3=f3()
lines=[] #empty list
i4=i3/i2;i5=reminder
i=-i1
i=i1+i2+i3+i4
i=(i1+i2)*(i3+i4)
Base operations for int type:
- - (one argument)
- *, /
- +, -
- >>, >> shift left, right ,i >> 2 shift 2 bits left
- neg (negate all bits)
- & bit and
- xand
- | bit or
- xor
i1 = - i2
i1 = i1 + i2
i1 = (i1 + i2 ) *( i3 + i4)
i1 = i1 >> 2 #shift two bits right
String and list operations
s[i] get i element , indexes start at 0, c1=s[0]
s[i:j] sub, take elements start from i to j , excluding j: s="1234"; s1=s[0:]->s1 is "12"
s[i:] from i to the end
s[:j] from beginning to j, excluding j
+ s1=s1+s2, s="12"+"34" ->"1234"
new operator
new_expression: new object_type_name
The new operator creates new object
class A
a= new list
a1= new A1
Class typeId
type_id_expression: fundamental_type_name .typeId or class_name .typeId
To get object type id we can use typeId function.
class A
a=0
i=int.typeId
i =A.typeId
i=typeId(a)
Int64 assignments
- int64_lv = int_expression
- int64_lv = int_expression * int_expression
- int64_lv = int64_lv + - * / int_expression
- int64_lv = int64_lv + - int64_lv
Matrix element as destination
matrix_name[ row,column]= float_expression
matrixAla[row,col]=2.0
Program layout
Instructions divided by end of line, in one line separated by ;
x=1 #comment to the end of line
y=2
z1=3; z2=4
When we want to continue line in next _ is used.
Instructions divided to blocks according to line indent.
if x=1 block 1
y=2 block 2
z=3 block 2
x=2 block 1
Logical expressions
As logical_expression we have:
- int value true if not 0, false if 0
- str value true if not equal to empty string, false if empty string
- variable in (constant list)
if x in (1,2,3,4)
- comparison operations : =,!=, <>,<,>,<=,>=
if x=2
- logical_operations
Logical_operations
int64 comparisons:
- int64_lv comparison int_expression
i64 <= i
- int64_lv comparison int64_lv
i64_a = i64_b
Program control
To control program flow if elif else, while, for are used.
if logical_expression : instruction_block
elif logical_expression :instruction_block
else:instr_block
if expression
instr_block
elif expression
instr_block
else
instr_block
if x=1 and y=2 : w=2;z=3
elif x=2 :w=3
else:z=4
if x=1 and y=2
w=2
z=3
elif x=2
w=3
else
z=4
while logical_expression
instr_block
for var = expr to expr optional step expr
for i=1 to 12 -> 1,2,.. 11,12
for var_name in list_name
var_name must be unique in program unit.
for e in l
print(e)
Parallel programming
Multicore parallel code
Multicore support must be initialized with initMT()
for loop_variable in list_varaiable parallel
procedure_name(loop_variable)
for loop_variable= start to end parallel
instructions
for loop_variable= start to end step step value parallel
instructions
At the beginning procedure is called for first list element and processed on first processor core,
second list element is processed on next core and so on to last available core.
Now program waits all cores to finish their tasks and everything starts again. When nested parallel code is executed
in win32 environment only first loop is executed in parallel.
SIMD parallel code
for loop_variable= start to end simd
float_matrix[ row , loop_variable]= float_simd_expression
float_matrix_expression:
- float_constant
- float_left_value
- float_matrix [matrix_row, matrix_column ] it is assumed then matrix_column grows in loop
- float_atritmetic_operation x+y, x-y, x*y, x/z
Program structure
Program consists of modules. In modules we have constants, classes, functions, procedures and instructions
For instructions with no indent implicitly module main is assumed.
const Co1 1 #first instruction from main module
class Cl1
p1()
p2()
f1()=
f2()=
When we want define modules in main file:
module m1
const Co1 1
class Cl1
p1()
p2()
f1()=
f2()=
x=0 #first instruction from main module
Each program uses elements from base module for instance:
print(var_name)
Functions and procedures
function_definition: optional return_type_name fun_name ( parameter_list ) =
Pay attention to equal sign = in function definition.
parameter_list: parameter_declaration divided by comma
parameter_declaration:
- type_name parameter_name
- [ list_subtype_name ] parameter_name
- arrayC_base_type [ array_size ]
Last instruction must be return.
return_type:
- immediate_type
- direct_type
- object_type
int f( int x, int y)=
z=x+y; return z
int f1([int] p1) #declares parameter p1 as list of ints
int f2(int[10] p2) #declares parameter p2 as arrayC od ints
As far as arrayC type is concerned then it is possible to use 0 as array size.
In such a case arrayC of any size will be passed as parameter, and it is programmer resposiblity co control index values,
for instnce using another parameter.
procedure_definition: proc proc_name ( parameter_list )
proc p(int x, int y)
print(x); print(y)
auxiliary_assembler_procedure : aux aux_name ()
function_call : left_value = function_name ( actual parameter list ) optionaly con
x=2;y=3
x=f(x,y)
procedure_call : procedure_name ( actual parameter list ) optionaly con
p(x,y)
auxiliary_procedure_call : call aux_name
call printRegs
When con is used function/procedure is passed to second processor core (option mt must be set in ide environment).
External dll procedure call
external_dll_procedure_call: call dll_name.function_name or call dll_name.function_name( actual_parameter_list)
when parameters are used pascal not c parameter passing sequence is used.
hWnd=12
call USER32.UpdateWindow(hWnd)
Late binding
proc p1(int x)=..
proc p1(str s)=.. function name p1 is overloaded
l=[1,Ala] first int than str value
for e in l
p1(e) e type unknown during compile, so parameter is bound during code execution
Internal (built in) procedures
int addr(var_name): return address of variables
int ref(var_name): returns address of object referenced by variable
int typeId(var_name): returns type id of variable
mem getMem(int size) : returns block of memory
Type copy(var_name): new object is created, all attributes are copied
Class C1
C1 c1; c2=copy(c1)
For lists
proc append(list_name,var_name): appends var to list
l=[]; s=Ala
append(l,s)
all pop(list_name)
s=pop(l)
proc replace(list_name,index_var,new_item)
replace(l,0,Ala) : list element 0 i replaced by Ala
proc replace(list_name,for_loop_variable_name,new_item)
for e in l
replace(l,e,123)
Classes
class C1 # class with 3 attributes: int_attr, str_attr, list_attr
int_attr=0 # initial value
str_attr=Ala
list_attr=[]
class C2
id=0
C1 attr_c1 #type_name:C1, attribute_name:attr_c1
C1 c #variable c is declared as object of the class C1
Attributes are referenced by full stop(.)
c.int_attr=12
c.str_attr=1234
append(c.list_attr,12)
text=c.str_attr
C2 c2
c2.c1.int_attr=13
Gui
gui_class_names:
- Window
- Button
- TextBox
- ListBox
- Static
- ComboBox
- TreeList
- Control
- CheckBox
- RadioButton
gui_var_definition: gui_var_name = gui_class_name(parameter_list)
window1=Window(....)
binding:
- bind gui_var_name , event_id , handler_call
- bind1 gui_var_name , event_id , subevent_id , handler_call
handler_call:
- proc_name ( var_name )
- proc_name ( var_name , systemEvent )
If we have more than one bind instruction for a gui_var then in handlers the same variable must be used.
p1(Class1 c1)=..
p2(Class2 c2, Event event)=..
Class1 c1;Class2 c2
bind window1,WM_SIZE, p1(c1)
bind window1,WM_MOVE, p2(c1) #second bind instruction for window1 so as argument in p2, c1 must be used !!!!!!!
bind window2, WM_SIZE, p2(c2,systemEvent)
Where class Event
msg=0
wParam=0
lParam=0
Mov instruction
mov destination , source
mov_instruction:
- mov register_name or byte_register_name , immediate_type_left_value
- mov register_name or byte_register_name , object_type_type_left_value
- mov register_name addr left_value
- mov register_name addr function_name
- mov immediate_type_left_value , register_name or byte_register_name
register_name: eax or ebx or ecx or edx or edi or esi
byte_register_name:ah or al or bh or bl or ch or cl or dh or dl
i=0
mov eax, i
mov ebx, addr f1
Inline assembling
asm assembler_instruction or $asm directive to switch on/off assembler codind
$asm is valid to the end of program unit (function or procedure).
x=1
asm mov eax,1
$asm start of assembler lines
mov eax, 2
mov ebx, 3
$asm end of assembler lines
x=2
Global variables
global global_variable_name
proc1:
global main_window_hwnd; main_window_hwnd=12
proc2:
global main_window_hwnd; int main_window_hwnd
hwnd=main_window_hwnd
Modules
module module_name
module m1
const C 1
class Ala
a=1
proc p()
x=1
f()=
return 1
$import module_name from file_name
file1.fsp:
module m1
const C1 1
int f()=
return 1
int f1()=
return 2
x=1 # here is first instruction of main module and program startup in file1.exe
x=f() # compile first tries to match function name and parameters in current module
# then in current file modules so f from m1 is found
file2.fsp:
$import m1 from file1.fsp
x=2 #program start in file2.exe
x=f() #first current module searched, then current file, then imported modules
print(x) #print found in base.fsp that is searched at the end
Virtual functions
type_name virtual_fun_name ( type_name object_var , parameters_list ) = virtual
virtual virtual_fun_name ( object_var_name, type_names_list) =
actual_fun_name ( type_names_list, additional_variables_list )
Additional_variables_list max length=3
str getField(DataDrid dataGrid, int row, int col)= virtual
dataGrid is an object_var, parameter_list:int row, int col (1)
str newGrodField(int row,int col, Form form)
DataGrid dataGrid; Form form1
virtual getField(dataGrid, int,int)=newGridField(int,int,form1)
getField : virtual_fun_name
newGridField actual_fun_name
int, int : type names list fiting to (1): int row, int col
form1 : one element additional_variables_list, here one variable that we can pass to newGridField