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
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)
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