diff --git a/.github/workflow/ci_i386.yml b/.github/workflow/ci_i386.yml
new file mode 100644
index 0000000000..6202cf3805
--- /dev/null
+++ b/.github/workflow/ci_i386.yml
@@ -0,0 +1,17 @@
+name: CI
+
+on:
+ push:
+ branches: [ main ]
+ pull_request:
+ branches: [ main ]
+ workflow_dispatch:
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+
+ - name: Build
+ run: make all_i386
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8db1d0fbdb..dcf79f5374 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,6 @@
## ELENA 6.0.2b
+*31.03.2023*
+
- ELENA
- fixing a critical error with long number comparision operations
- (re)implementing Script Engine (elenasm60 dll)
diff --git a/asm/aarch64/core60.asm b/asm/aarch64/core60.asm
index 849a9188dc..7d2424655c 100644
--- a/asm/aarch64/core60.asm
+++ b/asm/aarch64/core60.asm
@@ -720,6 +720,22 @@ inline % 1Ch
end
+// ; xload
+inline %1Dh
+
+ add x12, x10, __arg12_1
+ ldrsw x9, [x12]
+
+end
+
+// ; xlload
+inline %1Eh
+
+ add x12, x10, __arg12_1
+ ldr x9, [x12]
+
+end
+
// ; coalesce
inline % 20h
@@ -800,6 +816,50 @@ inline %02Fh
end
+// ; fabsdp
+inline %78h
+
+ add x19, x29, __arg12_1
+ ldr d18, [x0]
+ fabs d18, d18
+ str d18, [x19]
+
+end
+
+// ; fsqrtdp
+inline %79h
+
+ add x19, x29, __arg12_1
+ ldr d18, [x0]
+ fsqrt d18, d18
+ str d18, [x19]
+
+end
+
+// ; fexp
+inline %07Ah
+end
+
+// ; fln
+inline %07Bh
+end
+
+// ; fsin
+inline %07Ch
+end
+
+// ; fcos
+inline %07Dh
+end
+
+// ; farchtan
+inline %07Eh
+end
+
+// ; fpi
+inline %07Fh
+end
+
// ; setr
inline %80h
@@ -1007,7 +1067,7 @@ inline %8Dh
end
-// ; peekfi
+// ; setfi
// ; NOTE : it is presumed that arg1 < 0 (it is inverted in jitcompiler)
inline %08Eh
@@ -1015,7 +1075,7 @@ inline %08Eh
end
-// ; peekfi
+// ; setfi
// ; NOTE : it is presumed that arg1 > 0 (it is inverted in jitcompiler)
inline %58Eh
@@ -1263,6 +1323,44 @@ inline %9Ch
end
+// ; xadddp
+inline %9Dh
+
+ add x11, x29, __arg12_1
+ ldrsw x12, [x11]
+ add x9, x9, x12
+
+end
+
+// ; xsetfi
+// ; NOTE : it is presumed that arg1 < 0 (it is inverted in jitcompiler)
+inline %09Eh
+
+ lsl x14, x9, #3
+ sub x10, x29, -__arg12_1
+ sub x10, x10, x14
+
+end
+
+// ; xsetfi
+// ; NOTE : it is presumed that arg1 > 0 (it is inverted in jitcompiler)
+inline %59Eh
+
+ lsl x14, x9, #3
+ add x10, x29, __arg12_1
+ add x10, x10, x14
+
+end
+// ; frounddp
+inline %9Fh
+
+ add x19, x29, __arg12_1
+ ldr d18, [x0]
+ frintn d18, d18
+ str d18, [x19]
+
+end
+
// ; saveddp
inline %0A0h
@@ -1492,6 +1590,47 @@ inline %0ACh
end
+// ; xfillr
+inline % 0ADh
+
+ ldr w11, [x0]
+ lsl x11, x11, #3
+
+ movz x12, __ptr32lo_1
+ movk x12, __ptr32hi_1, lsl #16
+ mov x13, x10
+
+labLoop:
+ cmp x11, 0
+ beq labEnd
+ sub x11, x11, 8
+ str x12, [x13], #8
+ b labLoop
+
+labEnd:
+
+end
+
+// ; xfillr 0
+inline % 1ADh
+
+ ldr w11, [x0]
+ lsl x11, x11, #3
+
+ movz x12, #0
+ mov x13, x10
+
+labLoop:
+ cmp x11, 0
+ beq labEnd
+ sub x11, x11, 8
+ str x12, [x13], #8
+ b labLoop
+
+labEnd:
+
+end
+
// ; callr
inline %0B0h
@@ -1879,6 +2018,20 @@ inline %0D3h
end
+// ; udivndp
+inline %0D4h
+
+ add x19, x29, __arg12_1
+
+ ldr w17, [x0]
+ ldr w18, [x19]
+
+ udiv x18, x18, x17 // ; sp[0] / temp
+
+ str w18, [x19]
+
+end
+
// ; ianddpn
inline %0D8h
@@ -2211,6 +2364,22 @@ inline %4DDh
end
+// ; selultrr
+inline %0DFh
+
+ ldrsw x17, [x0]
+ ldrsw x18, [x10]
+ cmp x17, x18
+
+ movz x11, __ptr32lo_1
+ movz x12, __ptr32lo_2
+ movk x11, __ptr32hi_1, lsl #16
+ movk x12, __ptr32hi_2, lsl #16
+
+ csel x10, x11, x12, cc
+
+end
+
// ; copydpn
inline %0E0h
@@ -3099,6 +3268,44 @@ inline %0F7h
end
+// ; fillir
+inline %0F8h
+
+ movz x12, __ptr32lo_2
+ movk x12, __ptr32hi_2, lsl #16
+
+ mov x11, __arg12_1
+ mov x13, x10
+
+labLoop:
+ cmp x11, 0
+ beq labEnd
+ sub x11, x11, 1
+ str x12, [x13], #8
+ b labLoop
+
+labEnd:
+
+end
+
+// ; fill i,0
+inline %1F8h
+
+ mov x11, __arg12_1
+ mov x12, 0
+ mov x13, x10
+
+labLoop:
+ cmp x11, 0
+ beq labEnd
+ sub x11, x11, 1
+ str x12, [x13], #8
+ b labLoop
+
+labEnd:
+
+end
+
// ; xstorefir
inline %0F9h
diff --git a/asm/amd64/core60.asm b/asm/amd64/core60.asm
index 2d760ce62a..e7f0f72421 100644
--- a/asm/amd64/core60.asm
+++ b/asm/amd64/core60.asm
@@ -590,6 +590,22 @@ inline % 1Ch
end
+// ; xload
+inline %1Dh
+
+ lea rax, [rbx+rdx]
+ mov edx, dword ptr [rax]
+
+end
+
+// ; xlload
+inline %1Eh
+
+ lea rax, [rbx+rdx]
+ mov rdx, qword ptr [rax]
+
+end
+
// ; coalesce
inline % 20h
@@ -670,6 +686,149 @@ inline %02Fh
end
+// ; fabsdp
+inline %078h
+
+ lea rdi, [rbp + __arg32_1]
+ fld qword ptr [rsi]
+ fabs
+ fstp qword ptr [rdi] // ; store result
+
+end
+
+// ; fsqrtdp
+inline %079h
+
+ lea rdi, [rbp + __arg32_1]
+ fld qword ptr [rsi]
+ fsqrt
+ fstp qword ptr [rdi] // ; store result
+
+end
+
+// ; fexpdp
+inline %07Ah
+
+ lea rdi, [rbp + __arg32_1]
+ fld qword ptr [rsi]
+ xor edx, edx
+
+ fldl2e // ; ->log2(e)
+ fmulp // ; ->log2(e)*Src
+
+ // ; the FPU can compute the antilog only with the mantissa
+ // ; the characteristic of the logarithm must thus be removed
+
+ fld st(0) // ; copy the logarithm
+ frndint // ; keep only the characteristic
+ fsub st(1),st(0) // ; keeps only the mantissa
+ fxch // ; get the mantissa on top
+
+ f2xm1 // ; ->2^(mantissa)-1
+ fld1
+ faddp // ; add 1 back
+
+ //; the number must now be readjusted for the characteristic of the logarithm
+
+ fscale // ;, scale it with the characteristic
+
+ fstsw ax // ; retrieve exception flags from FPU
+ shr al,1 // ; test for invalid operation
+ jc short lErr // ; clean-up and return if error
+
+ // ; the characteristic is still on the FPU and must be removed
+
+ fstp st(1) // ; get rid of the characteristic
+
+ fstp qword ptr [rdi] // ; store result
+ mov edx, 1
+ jmp short labEnd
+
+lErr:
+ ffree st(1)
+
+labEnd:
+
+end
+
+// ; flndp
+inline %07Bh
+
+ lea rdi, [rbp + __arg32_1]
+ fld qword ptr [rsi]
+
+ fldln2
+ fxch
+ fyl2x // ->[log2(Src)]*ln(2) = ln(Src)
+
+ fstsw ax // retrieve exception flags from FPU
+ shr al,1 // test for invalid operation
+ jc short lErr // clean-up and return error
+
+ fstp qword ptr [rdi] // store result
+ mov edx, 1
+ jmp short labEnd
+
+lErr:
+ ffree st(0)
+
+labEnd:
+
+end
+
+// ; fsindp
+inline %07Ch
+
+ lea rdi, [rbp + __arg32_1]
+ fld qword ptr [rsi]
+ fldpi
+ fadd st(0),st(0) // ; ->2pi
+ fxch
+
+lReduce:
+ fprem // ; reduce the angle
+ fsin
+ fstsw ax // ; retrieve exception flags from FPU
+ shr al,1 // ; test for invalid operation
+ // ; jc short lErr // ; clean-up and return error
+ sahf // ; transfer to the CPU flags
+ jpe short lReduce // ; reduce angle again if necessary
+ fstp st(1) // ; get rid of the 2pi
+
+ fstp qword ptr [rdi] // ; store result
+
+end
+
+// ; fcosdp
+inline %07Dh
+
+ lea rdi, [rbp + __arg32_1]
+ fld qword ptr [rsi]
+ fcos
+ fstp qword ptr [rdi] // ; store result
+
+end
+
+// ; farctandp
+inline %07Eh
+
+ lea rdi, [rbp + __arg32_1]
+ fld qword ptr [rsi]
+ fld1
+ fpatan // i.e. arctan(Src/1)
+ fstp qword ptr [rdi] // ; store result
+
+end
+
+// ; fpidp
+inline %07Fh
+
+ lea rdi, [rbp + __arg32_1]
+ fldpi
+ fstp qword ptr [rdi] // ; store result
+
+end
+
// ; setr
inline %80h
@@ -1087,6 +1246,58 @@ inline %9Ch
end
+// ; xadddpn
+inline %09Dh
+
+ mov eax, dword ptr [rbp+__arg32_1]
+ add edx, eax
+
+end
+
+// ; xsetfp
+inline %09Eh
+
+ lea rax, [rdx*4]
+ lea rbx, [rbp + rax + __arg32_1]
+
+end
+
+// ; frounddp
+inline %09Fh
+
+ lea rdi, [rbp + __arg32_1]
+
+ mov ecx, 0
+ fld qword ptr [rsi]
+
+ push rcx // reserve space on stack
+ fstcw word ptr [rsp] // get current control word
+
+ mov rdx, [rsp]
+ and dx,0F3FFh // code it for code it for rounding
+ push rdx
+ fldcw word ptr [rsp] // change rounding code of FPU to truncate
+
+ frndint // round the number
+ pop rdx // remove modified CW from CPU stack
+ fldcw word ptr [rsp] // load back the former control word
+ pop rdx // clean CPU stack
+
+ fstsw ax // retrieve exception flags from FPU
+ shr al,1 // test for invalid operation
+ jc short labErr // clean-up and return error
+
+labSave:
+ fstp qword ptr [rdi] // store result
+ jmp short labEnd
+
+labErr:
+ ffree st(1)
+
+labEnd:
+
+end
+
// ; savedp
inline %0A0h
@@ -1267,6 +1478,24 @@ inline %0ACh
end
+// ; xfillr
+inline % 0ADh
+ mov rax, __ptr64_1
+ mov rdi, rbx
+ mov rcx, [r10]
+ rep stos
+
+end
+
+// ; xfillr i,0
+inline % 1ADh
+ xor rax, rax
+ mov rdi, rbx
+ mov rcx, [r10]
+ rep stos
+
+end
+
// ; callr
inline %0B0h
@@ -1601,6 +1830,17 @@ inline %0D3h
end
+// ; udivndp
+inline %0D4h
+
+ mov rcx, [r10]
+ xor edx, edx
+ mov rax, [rbp+__arg32_1]
+ div ecx
+ mov dword ptr [rbp+__arg32_1], eax
+
+end
+
// ; ianddpn
inline %0D8h
@@ -1837,6 +2077,17 @@ inline %4DDh
end
+// ; selultrr
+inline %0DFh
+
+ mov rax, [r10]
+ cmp eax, dword ptr[rbx]
+ mov rcx, __ptr64_1
+ mov rbx, __ptr64_2
+ cmovb rbx, rcx
+
+end
+
// ; copydpn
inline %0E0h
@@ -2467,6 +2718,26 @@ inline %0F7h
end
+// ; fillir
+inline % 0F8h
+
+ mov rax, __ptr64_2
+ mov rdi, rbx
+ mov ecx, __arg32_1
+ rep stos
+
+end
+
+// ; fill i,0
+inline % 1F8h
+
+ xor rax, rax
+ mov rdi, rbx
+ mov ecx, __arg32_1
+ rep stos
+
+end
+
// ; xstorefir
inline %0F9h
diff --git a/asm/ppc64le/core60.asm b/asm/ppc64le/core60.asm
index 5a9d8d4eb7..ff75c302aa 100644
--- a/asm/ppc64le/core60.asm
+++ b/asm/ppc64le/core60.asm
@@ -777,6 +777,22 @@ inline % 1Ch
end
+// ; xload
+inline %1Dh
+
+ add r18, r18, r15
+ lwz r14, 0(r18)
+
+end
+
+// ; xlload
+inline %1Eh
+
+ add r18, r18, r15
+ ld r14, 0(r18)
+
+end
+
// ; coalesce
inline % 20h
@@ -860,6 +876,52 @@ inline %02Fh
end
+// ; fabsdp
+inline %078h
+
+ addi r19, r31, __arg16_1
+
+ lfd f17, 0(r3)
+ fabs f17, f17
+ stfd f17, 0(r19)
+
+end
+
+// ; fsqrtdp
+inline %079h
+
+ addi r19, r31, __arg16_1
+
+ lfd f17, 0(r3)
+ fsqrt f17, f17
+ stfd f17, 0(r19)
+
+end
+
+// ; fexp
+inline %07Ah
+end
+
+// ; fln
+inline %07Bh
+end
+
+// ; fsin
+inline %07Ch
+end
+
+// ; fcos
+inline %07Dh
+end
+
+// ; farchtan
+inline %07Eh
+end
+
+// ; fpi
+inline %07Fh
+end
+
// ; setr
inline %80h
@@ -1356,6 +1418,36 @@ inline %9Ch
end
+// ; xadddp
+inline %9Dh
+
+ addi r16, r31, __arg16_1
+ lwz r16, 0(r16)
+ add r14, r14, r16
+
+end
+
+// ; xsetfp
+inline %09Eh
+
+ li r16, __arg16_1
+ add r15, r31, r16
+ sldi r18, r14, 3
+ add r15, r15, r18
+
+end
+
+// ; frounddp
+inline %09Fh
+
+ addi r19, r31, __arg16_1
+
+ lfd f17, 0(r3)
+ frin f17, f17
+ stfd f17, 0(r19)
+
+end
+
// ; savedp
inline %0A0h
@@ -1543,6 +1635,51 @@ inline %0ACh
end
+// ; xfillr
+inline % 0ADh
+
+ ld r16, 0(r3)
+ sldi r16, r16, 3
+
+ ld r17, toc_code(r2)
+ addis r17, r17, __xdisp32hi_1
+ addi r17, r17, __xdisp32lo_1
+
+ mr r18, r15
+
+labLoop:
+ cmpwi r16,0
+ beq labEnd
+ addi r16, r16, -8
+ std r17, 0(r18)
+ addi r18, r18, 8
+ b labLoop
+
+labEnd:
+
+end
+
+// ; xfillr
+inline % 1ADh
+
+ ld r16, 0(r3)
+ sldi r16, r16, 3
+ li r17, 0
+ mr r18, r15
+
+labLoop:
+ cmpwi r16,0
+ beq labEnd
+ addi r16, r16, -8
+ std r17, 0(r18)
+ addi r18, r18, 8
+ b labLoop
+
+labEnd:
+
+end
+
+
// ; callr
inline %0B0h
@@ -1910,6 +2047,20 @@ inline %0D3h
end
+// ; udivndp
+inline %0D4h
+
+ addi r19, r31, __arg16_1
+
+ lwz r17, 0(r3)
+ lwz r18, 0(r19)
+
+ divwu r18, r18, r17
+
+ stw r18, 0(r19)
+
+end
+
// ; ianddpn
inline %0D8h
@@ -2242,6 +2393,24 @@ inline %4DDh
end
+// ; selultrr
+inline %0DFh
+
+ lwz r17, 0(r3)
+ lwz r18, 0(r15)
+
+ cmpl r17, r18
+
+ ld r16, toc_code(r2)
+ addis r17, r16, __xdisp32hi_1
+ addis r18, r16, __xdisp32hi_2
+ addi r17, r17, __xdisp32lo_1
+ addi r18, r18, __xdisp32lo_2
+
+ isellt r15, r17, r18
+
+end
+
// ; copydpn
inline %0E0h
@@ -3180,6 +3349,48 @@ inline %0F7h
end
+// ; fillir
+inline %0F8h
+
+ li r16, __arg16_1
+
+ ld r17, toc_rdata(r2)
+ addis r17, r17, __disp32hi_2
+ addi r17, r17, __disp32lo_2
+
+ mr r18, r15
+
+labLoop:
+ cmpwi r16,0
+ beq labEnd
+ addi r16, r16, -1
+ std r17, 0(r18)
+ addi r18, r18, 8
+ b labLoop
+
+labEnd:
+
+end
+
+// ; fillir
+inline %1F8h
+
+ li r16, __arg16_1
+ li r17, 0
+ mr r18, r15
+
+labLoop:
+ cmpwi r16,0
+ beq labEnd
+ addi r16, r16, -1
+ std r17, 0(r18)
+ addi r18, r18, 8
+ b labLoop
+
+labEnd:
+
+end
+
// ; xstorefir
inline %0F9h
diff --git a/asm/x32/core60.asm b/asm/x32/core60.asm
index 0c44bec44d..9e4d48aa11 100644
--- a/asm/x32/core60.asm
+++ b/asm/x32/core60.asm
@@ -588,6 +588,23 @@ inline % 1Ch
end
+// ; xload
+inline %1Dh
+
+ lea eax, [ebx+edx]
+ mov edx, dword ptr [eax]
+
+end
+
+// ; xlload
+inline %1Eh
+
+ lea eax, [ebx+edx]
+ mov edx, dword ptr [eax+4]
+ mov eax, dword ptr [eax]
+
+end
+
// ; coalesce
inline % 20h
@@ -667,6 +684,149 @@ inline %02Fh
end
+// ; fabsdp
+inline %078h
+
+ lea edi, [ebp + __arg32_1]
+ fld qword ptr [esi]
+ fabs
+ fstp qword ptr [edi] // ; store result
+
+end
+
+// ; fsqrtdp
+inline %079h
+
+ lea edi, [ebp + __arg32_1]
+ fld qword ptr [esi]
+ fsqrt
+ fstp qword ptr [edi] // ; store result
+
+end
+
+// ; fexpdp
+inline %07Ah
+
+ lea edi, [ebp + __arg32_1]
+ fld qword ptr [esi]
+ xor edx, edx
+
+ fldl2e // ; ->log2(e)
+ fmulp // ; ->log2(e)*Src
+
+ // ; the FPU can compute the antilog only with the mantissa
+ // ; the characteristic of the logarithm must thus be removed
+
+ fld st(0) // ; copy the logarithm
+ frndint // ; keep only the characteristic
+ fsub st(1),st(0) // ; keeps only the mantissa
+ fxch // ; get the mantissa on top
+
+ f2xm1 // ; ->2^(mantissa)-1
+ fld1
+ faddp // ; add 1 back
+
+ //; the number must now be readjusted for the characteristic of the logarithm
+
+ fscale // ;, scale it with the characteristic
+
+ fstsw ax // ; retrieve exception flags from FPU
+ shr al,1 // ; test for invalid operation
+ jc short lErr // ; clean-up and return if error
+
+ // ; the characteristic is still on the FPU and must be removed
+
+ fstp st(1) // ; get rid of the characteristic
+
+ fstp qword ptr [edi] // ; store result
+ mov edx, 1
+ jmp short labEnd
+
+lErr:
+ ffree st(1)
+
+labEnd:
+
+end
+
+// ; flndp
+inline %07Bh
+
+ lea edi, [ebp + __arg32_1]
+ fld qword ptr [esi]
+
+ fldln2
+ fxch
+ fyl2x // ->[log2(Src)]*ln(2) = ln(Src)
+
+ fstsw ax // retrieve exception flags from FPU
+ shr al,1 // test for invalid operation
+ jc short lErr // clean-up and return error
+
+ fstp qword ptr [edi] // store result
+ mov edx, 1
+ jmp short labEnd
+
+lErr:
+ ffree st(0)
+
+labEnd:
+
+end
+
+// ; fsindp
+inline %07Ch
+
+ lea edi, [ebp + __arg32_1]
+ fld qword ptr [esi]
+ fldpi
+ fadd st(0),st(0) // ; ->2pi
+ fxch
+
+lReduce:
+ fprem // ; reduce the angle
+ fsin
+ fstsw ax // ; retrieve exception flags from FPU
+ shr al,1 // ; test for invalid operation
+ // ; jc short lErr // ; clean-up and return error
+ sahf // ; transfer to the CPU flags
+ jpe short lReduce // ; reduce angle again if necessary
+ fstp st(1) // ; get rid of the 2pi
+
+ fstp qword ptr [edi] // ; store result
+
+end
+
+// ; fcosdp
+inline %07Dh
+
+ lea edi, [ebp + __arg32_1]
+ fld qword ptr [esi]
+ fcos
+ fstp qword ptr [edi] // ; store result
+
+end
+
+// ; farctandp
+inline %07Eh
+
+ lea edi, [ebp + __arg32_1]
+ fld qword ptr [esi]
+ fld1
+ fpatan // i.e. arctan(Src/1)
+ fstp qword ptr [edi] // ; store result
+
+end
+
+// ; fpidp
+inline %07Fh
+
+ lea edi, [ebp + __arg32_1]
+ fldpi
+ fstp qword ptr [edi] // ; store result
+
+end
+
// ; setr
inline %80h
@@ -1069,6 +1229,58 @@ inline %9Ch
end
+// ; xadddpn
+inline %09Dh
+
+ mov eax, [ebp+__arg32_1]
+ add edx, eax
+
+end
+
+// ; xsetfp
+inline %09Eh
+
+ lea eax, [edx*4]
+ lea ebx, [ebp + eax + __arg32_1]
+
+end
+
+// ; frounddp
+inline %09Fh
+
+ lea edi, [ebp + __arg32_1]
+
+ mov ecx, 0
+ fld qword ptr [esi]
+
+ push ecx // reserve space on stack
+ fstcw word ptr [esp] // get current control word
+
+ mov edx, [esp]
+ and dx,0F3FFh // code it for code it for rounding
+ push edx
+ fldcw word ptr [esp] // change rounding code of FPU to truncate
+
+ frndint // round the number
+ pop edx // remove modified CW from CPU stack
+ fldcw word ptr [esp] // load back the former control word
+ pop edx // clean CPU stack
+
+ fstsw ax // retrieve exception flags from FPU
+ shr al,1 // test for invalid operation
+ jc short labErr // clean-up and return error
+
+labSave:
+ fstp qword ptr [edi] // store result
+ jmp short labEnd
+
+labErr:
+ ffree st(1)
+
+labEnd:
+
+end
+
// ; savedp
inline %0A0h
@@ -1151,7 +1363,7 @@ end
// ; xrefreshsi 0
inline %1A7h
- mov esi, [esp+4]
+ mov esi, [esp+__arg32_1]
end
@@ -1203,6 +1415,24 @@ inline %0ACh
end
+// ; xfillr
+inline % 0ADh
+ mov eax, __ptr32_1
+ mov edi, ebx
+ mov ecx, [esi]
+ rep stos
+
+end
+
+// ; xfillr i,0
+inline % 1ADh
+ xor eax, eax
+ mov edi, ebx
+ mov ecx, [esi]
+ rep stos
+
+end
+
// ; callr
inline %0B0h
@@ -1500,6 +1730,16 @@ inline %0D3h
end
+// ; udivndp
+inline %0D4h
+
+ xor edx, edx
+ mov eax, [ebp+__arg32_1]
+ div dword ptr [esi]
+ mov [ebp+__arg32_1], eax
+
+end
+
// ; ianddpn
inline %0D8h
@@ -1800,6 +2040,17 @@ lEnd2:
end
+// ; selultrr
+inline %0DFh
+
+ mov eax, [esi]
+ cmp eax, [ebx]
+ mov ecx, __ptr32_1
+ mov ebx, __ptr32_2
+ cmovb ebx, ecx
+
+end
+
// ; copydpn
inline %0E0h
@@ -2523,6 +2774,26 @@ inline %0F7h
end
+// ; fillir
+inline % 0F8h
+
+ mov eax, __ptr32_2
+ mov edi, ebx
+ mov ecx, __arg32_1
+ rep stos
+
+end
+
+// ; fill i,0
+inline % 1F8h
+
+ xor eax, eax
+ mov edi, ebx
+ mov ecx, __arg32_1
+ rep stos
+
+end
+
// ; xstorefir
inline %0F9h
@@ -2595,11 +2866,11 @@ end
// ; NOTE : __arg32_1 - variadic message; __n_1 - arg count; __ptr32_2 - list, __n_2 - argument list offset
inline % 5FAh
+ mov [esp+4], esi // ; saving arg0
lea eax, [esp + __n_2]
xor ecx, ecx
push ecx
push ecx
- mov [esp+4], esi // ; saving arg0
push ebx
mov ebx, eax
@@ -2738,11 +3009,11 @@ end
// ; NOTE : __arg32_1 - message; __n_1 - arg count; __ptr32_2 - list, __n_2 - argument list offset
inline % 5FBh
+ mov [esp+4], esi // ; saving arg0
xor ecx, ecx
lea eax, [esp + __n_2]
push ecx
push ecx
- mov [esp+4], esi // ; saving arg0
push ebx
mov ebx, eax
diff --git a/bin/templates/lib.cfg b/bin/templates/lib.cfg
deleted file mode 100644
index da8597a25b..0000000000
--- a/bin/templates/lib.cfg
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
- 0
-
-
- ..\..\lib50
-
-
- system'Object
- system'Message
- system'IntNumber
- system'LongNumber
- system'RealNumber
- system'CharValue
- system'String
- system'WideString
- system'MessageName
- system'Func
- system'BoolValue
- system'BoolValue#true
- system'BoolValue#false
- system'ref#1
- system'Array#1
- system'VariadicArray#1
- system'ExtensionMessage
- system'BaseLazyExpression
- system'Wrap
-
-
diff --git a/bin/templates/lib.config b/bin/templates/lib.config
deleted file mode 100644
index 9e74589a34..0000000000
--- a/bin/templates/lib.config
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
- 0
-
-
- /usr/lib/elena/lib50
-
-
- system'Object
- system'Message
- system'IntNumber
- system'LongNumber
- system'RealNumber
- system'CharValue
- system'String
- system'WideString
- system'MessageName
- system'Func
- system'BoolValue
- system'BoolValue#true
- system'BoolValue#false
- system'ref#1
- system'Array#1
- system'VariadicArray#1
- system'ExtensionMessage
- system'BaseLazyExpression
- system'Wrap
-
-
diff --git a/bin/templates/lib60.cfg b/bin/templates/lib60.cfg
index a337eb7bdc..d2e06dc4e8 100644
--- a/bin/templates/lib60.cfg
+++ b/bin/templates/lib60.cfg
@@ -23,9 +23,9 @@
system'predefined'meta$attributesSymbols
system'meta$aliasTypes
system'operations'meta$statementTemplates
- system'meta$startUpSymbols
system'Object
system'IntNumber
+ system'UIntNumber
system'LongNumber
system'RealNumber
system'ByteNumber
@@ -40,9 +40,13 @@
system'Array#1
system'VariadicArray#1
system'Message
+ system'MessageName
system'ExtensionMessage
system'Func
+ system'collections'Tuple
system'BaseLazyExpression
system'UnsafePointer
+ meta$preloadedSymbols
+ meta$preloadedSymbols
\ No newline at end of file
diff --git a/bin/templates/lib60.config b/bin/templates/lib60.config
index 3d3cb9fe66..866a6162da 100644
--- a/bin/templates/lib60.config
+++ b/bin/templates/lib60.config
@@ -30,6 +30,7 @@
system'meta$startUpSymbols
system'Object
system'IntNumber
+ system'UIntNumber
system'LongNumber
system'RealNumber
system'ByteNumber
@@ -44,8 +45,10 @@
system'Array#1
system'VariadicArray#1
system'Message
+ system'MessageName
system'ExtensionMessage
system'Func
+ system'collections'Tuple
system'BaseLazyExpression
system'UnsafePointer
diff --git a/bin/templates/lib_64.cfg b/bin/templates/lib_64.cfg
deleted file mode 100644
index ecb0c8addc..0000000000
--- a/bin/templates/lib_64.cfg
+++ /dev/null
@@ -1,32 +0,0 @@
-
-
- 0
-
-
- 8
-
-
- ..\..\lib50_64
-
-
- system'Object
- system'Message
- system'IntNumber
- system'LongNumber
- system'RealNumber
- system'CharValue
- system'String
- system'WideString
- system'MessageName
- system'Func
- system'BoolValue
- system'BoolValue#true
- system'BoolValue#false
- system'ref#1
- system'Array#1
- system'VariadicArray#1
- system'ExtensionMessage
- system'BaseLazyExpression
- system'Wrap
-
-
diff --git a/bin/templates/lnx32_console.config b/bin/templates/lnx32_console.config
deleted file mode 100644
index 2c90eb3085..0000000000
--- a/bin/templates/lnx32_console.config
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
- 2
-
-
- lib
-
-
- 54000
- 15000
- 10000
-
-
- system'startUp
- system'core_routines'sta_start
- $elena'@rootnamespace'program
- extensions'program_arguments
- system'console
- system'newLine
- system'onConsoleStart
-
-
- /usr/lib/elena/core/x32/core.bin
- /usr/lib/elena/core/x32/core_lnx.bin
- /usr/lib/elena/core/x32/coreapi.bin
- /usr/lib/elena/libelenart.so
-
-
diff --git a/bin/templates/lnx_console60.config b/bin/templates/lnx_console60.config
index 1c7cc37e33..7d708677e1 100644
--- a/bin/templates/lnx_console60.config
+++ b/bin/templates/lnx_console60.config
@@ -28,6 +28,7 @@
system'core_routines'sta_start
+ system'$private'entrySymbol
$rootnamespace'program
\ No newline at end of file
diff --git a/bin/templates/vm_lnx32_console.config b/bin/templates/vm_lnx32_console.config
deleted file mode 100644
index 6cc3546157..0000000000
--- a/bin/templates/vm_lnx32_console.config
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
- 258
-
-
- lib
-
-
- 54000
- 15000
- 10000
-
-
- system'startUp
- system'core_routines'vm_sta_start
- $elena'@rootnamespace'program
- system'newLine
- extensions'program_arguments
- system'onConsoleStart
-
-
- /usr/lib/elena/core/x32/core.bin
- /usr/lib/elena/core/x32/core_lnx.bin
- /usr/lib/elena/core/x32/coreapi.bin
- /usr/lib/elena/libelenavm.so
-
-
-
-
diff --git a/bin/templates/vm_win32_console.cfg b/bin/templates/vm_win32_console.cfg
deleted file mode 100644
index 4f85f7750f..0000000000
--- a/bin/templates/vm_win32_console.cfg
+++ /dev/null
@@ -1,27 +0,0 @@
-
-
- 257
-
-
- lib
-
-
- 54000
- 15000
- 10000
-
-
- system'startUp
- system'core_routines'vm_sta_start
- $elena'@rootnamespace'program
- system'newLine
- extensions'program_arguments
- system'onConsoleStart
-
-
- ..\x32\core.bin
- ..\x32\core_win.bin
- ..\x32\coreapi.bin
- ~elenavm
-
-
\ No newline at end of file
diff --git a/bin/templates/vm_win32_gui_xforms.cfg b/bin/templates/vm_win32_gui_xforms.cfg
deleted file mode 100644
index dc56134cef..0000000000
--- a/bin/templates/vm_win32_gui_xforms.cfg
+++ /dev/null
@@ -1,23 +0,0 @@
-[linker]
-mgsize=54000
-ygsize=15000
-
-[project]
-template=lib
-
-[primitives]
-core=..\x32\core.bin
-core=..\x32\core_win.bin
-coreapi=..\x32\coreapi.bin
-core_vm=..\x32\core_vm.bin
-$rt=~elenavm
-
-[forwards]
-'program=system'winforms'xprogram
-'newLine=system'text'newLine
-'startUp=system'winforms'startUp
-'MainWindow=$elena'@rootnamespace'MainWindow
-
-[system]
-platform=4353
-
diff --git a/bin/templates/vm_win64_console.cfg b/bin/templates/vm_win64_console.cfg
deleted file mode 100644
index 643bd37a15..0000000000
--- a/bin/templates/vm_win64_console.cfg
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
- 385
-
-
- lib_64
-
-
- A8000
- 32000
- 20000
-
-
- system'startUp
- system'core_routines'vm_sta_start
- $elena'@rootnamespace'program
- extensions'program_arguments
- system'console
- system'newLine
- system'onConsoleStart
-
-
- ..\amd64\core.bin
- ..\amd64\core_win.bin
- ..\amd64\coreapi.bin
- ~elenavm64
-
-
diff --git a/bin/templates/vm_win_console60.cfg b/bin/templates/vm_win_console60.cfg
index e3c3e8f7af..e8fb7a0616 100644
--- a/bin/templates/vm_win_console60.cfg
+++ b/bin/templates/vm_win_console60.cfg
@@ -26,6 +26,6 @@
system'core_routines'vm_sta_start
$rootnamespace'program
- system'core_routines'startUpSymbols
+ system'$private'entrySymbol
\ No newline at end of file
diff --git a/bin/templates/win32_console.cfg b/bin/templates/win32_console.cfg
deleted file mode 100644
index d66744eec2..0000000000
--- a/bin/templates/win32_console.cfg
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
- 1
-
-
- lib
-
-
- 54000
- 15000
- 10000
-
-
- system'startUp
- system'core_routines'sta_start
- $elena'@rootnamespace'program
- extensions'program_arguments
- system'console
- system'newLine
- system'onConsoleStart
-
-
- ..\x32\core.bin
- ..\x32\core_win.bin
- ..\x32\coreapi.bin
- ~elenart
-
-
diff --git a/bin/templates/win32_consolex.cfg b/bin/templates/win32_consolex.cfg
deleted file mode 100644
index 50680c4a1d..0000000000
--- a/bin/templates/win32_consolex.cfg
+++ /dev/null
@@ -1,30 +0,0 @@
-
-
- 65537
- 10
-
-
- lib
-
-
- 54000
- 15000
- 10000
-
-
- system'startUp
- system'core_routines'mta_start
- $elena'@rootnamespace'program
- extensions'program_arguments
- system'console
- system'newLine
- system'onConsoleStart
-
-
- ..\x32\core.bin
- ..\x32\corex.bin
- ..\x32\core_win.bin
- ..\x32\coreapi.bin
- ~elenart
-
-
diff --git a/bin/templates/win32_gui.cfg b/bin/templates/win32_gui.cfg
deleted file mode 100644
index 3bcb1ab6f1..0000000000
--- a/bin/templates/win32_gui.cfg
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
- 4097
- 1
-
-
- lib
-
-
- 54000
- 15000
- 10000
-
-
- ..\x32\core.bin
- ..\x32\core_win.bin
- ..\x32\coreapi.bin
- ~elenart
-
-
- system'startUp
- system'core_routines'sta_start
- system'winforms'program
- system'newLine
- $elena'@rootnamespace'MainWindow
- system'winforms'onGUIStart
-
-
diff --git a/bin/templates/win32_gui_xforms.cfg b/bin/templates/win32_gui_xforms.cfg
deleted file mode 100644
index bbd212dbd5..0000000000
--- a/bin/templates/win32_gui_xforms.cfg
+++ /dev/null
@@ -1,22 +0,0 @@
-[linker]
-mgsize=54000
-ygsize=15000
-
-[project]
-template=lib
-
-[primitives]
-core=..\x32\core.bin
-core=..\x32\core_win.bin
-coreapi=..\x32\coreapi.bin
-$rt=~elenart
-
-[forwards]
-'program=system'winforms'xprogram
-'newLine=system'text'newLine
-'startUp=system'winforms'startUp
-'MainWindow=$elena'@rootnamespace'MainWindow
-
-[system]
-platform=4097
-
diff --git a/bin/templates/win32_guix.cfg b/bin/templates/win32_guix.cfg
deleted file mode 100644
index ee06af85f2..0000000000
--- a/bin/templates/win32_guix.cfg
+++ /dev/null
@@ -1,22 +0,0 @@
-[project]
-template=lib
-
-[primitives]
-core=..\x32\corex.bin
-core=..\x32\core_win.bin
-coreapi=..\x32\coreapi.bin
-$rt=~elenart
-
-[forwards]
-'program=system'winforms'program
-'newLine=system'text'newLine
-'startUp=system'winforms'startUp
-
-[linker]
-mgsize=54000
-ygsize=15000
-
-[system]
-maxthread=20
-platform=69633
-
diff --git a/bin/templates/win64_console.cfg b/bin/templates/win64_console.cfg
deleted file mode 100644
index 0fb64befac..0000000000
--- a/bin/templates/win64_console.cfg
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
- 129
-
-
- lib_64
-
-
- A8000
- 32000
- 20000
-
-
- system'startUp
- system'core_routines'sta_start
- $elena'@rootnamespace'program
- extensions'program_arguments
- system'console
- system'newLine
- system'onConsoleStart
-
-
- ..\amd64\core.bin
- ..\amd64\core_win.bin
- ..\amd64\coreapi.bin
- ~elenart64
-
-
diff --git a/bin/templates/win_console60.cfg b/bin/templates/win_console60.cfg
index 79ea1079b4..0ea0eff27d 100644
--- a/bin/templates/win_console60.cfg
+++ b/bin/templates/win_console60.cfg
@@ -17,6 +17,7 @@
system'core_routines'sta_start
+ system'$private'entrySymbol
$rootnamespace'program
\ No newline at end of file
diff --git a/dat/sg/syntax60.txt b/dat/sg/syntax60.txt
index 9e11d69b86..b107a4c8ac 100644
--- a/dat/sg/syntax60.txt
+++ b/dat/sg/syntax60.txt
@@ -27,6 +27,8 @@ __define ARRAY_TYPE 4147;
__define NESTED 4224;
__define CLOSURE 4225;
__define MESSAGE 4288;
+__define OPERATOR 4310;
+__define SUB_VARIABLE 4311;
__define RET_EXPRESSION 7220;
__define GET_EXPRESSION 7222;
__define INIT_EXPRESSION 7223;
@@ -47,16 +49,16 @@ __define LOOP_OPERATION 6221;
__define ELSE_OPERATION 6222;
__define IF_ELSE_OPERATION 6223;
__define MUL_OPERATION 6224;
-__define DIV_OPERATION 6225;
-__define NOTLESS_OPERATION 6226;
-__define GREATER_OPERATION 6227;
-__define NOTGREATER_OPERATION 6228;
-__define EXTERN_OPERATION 6229;
-__define NEGATE_OPERATION 6230;
-__define VALUE_OPERATION 6231;
-__define BAND_OPERATION 6232;
-__define BOR_OPERATION 6233;
-__define BXOR_OPERATION 6234;
+__define DIV_OPERATION 6225;
+__define NOTLESS_OPERATION 6226;
+__define GREATER_OPERATION 6227;
+__define NOTGREATER_OPERATION 6228;
+__define EXTERN_OPERATION 6229;
+__define NEGATE_OPERATION 6230;
+__define VALUE_OPERATION 6231;
+__define BAND_OPERATION 6232;
+__define BOR_OPERATION 6233;
+__define BXOR_OPERATION 6234;
__define BNOT_OPERATION 6235;
__define SHL_OPERATION 6236;
__define SHR_OPERATION 6237;
@@ -68,6 +70,7 @@ __define OR_OPERATION 6242;
__define XOR_OPERATION 6243;
__define BREAK_OPERATION 6244;
__define LAZY_OPERATION 6245;
+__define TUPLE_ASSIGNING 6246;
__define MESSAGE_OPERATION 6337;
__define PROPERTY_OPERATION 6340;
__define EXPRESSION 6288;
@@ -82,10 +85,13 @@ __define NT_EXPRESSION 6296;
__define L7_EXPRESSION 6297;
__define L3_SINGLE_EXPRESSION 6298;
__define NESTED_ROOT_EXPRESSION 6299;
+__define OPERATION_TEMPLATE 6300;
+__define LT_EXPRESSION 6301;
__define SWITCH_OPTION 6353;
__define SWITCH_LAST_OPTION 6354;
__define SWITCH_CODE 6355;
__define COLLECTION_EXPRESSION 6356;
+__define TUPLE_COLLECTION 6357;
__define POSTFIX 4200;
__define TEMPLATE_POSTFIX 4201;
__define TEMPLATE_ARG 4208;
@@ -93,12 +99,16 @@ __define DIMENSION 5233;
__define RESEND 7366;
__define CATCH_OPERATION 7367;
__define CATCH 7368;
+__define FINAL_OPERATION 7386;
__define REDIRECT 7371;
__define ALT_OPERATION 7372;
__define ISNIL_OPERATION 7373;
__define SWITCH_OPERATION 7376;
__define COMPLEX_NAME 4302;
__define INLINE 4303;
+__define SUB_DECLARATION 4312;
+__define FINALLY 7385;
+__define PARAMETER_BLOCK 4336;
START ::=
{ DECLARATION | META_DECLARATION }+ eof
@@ -115,10 +125,14 @@ DECLARATION ::=
IR_DECLARATION ::=
{ TEMPLATE_BRACKETS identifier? | { DYNAMIC_DIMENSION ^ARRAY_TYPE }+ identifier } { POSTFIXES NESTED_SCOPE | SCOPE }
- | "::" COMPLEX_NAME TEMPLATE_BRACKETS? METHOD_SCOPE
+ | { "," SUB_DECLARATION }+ { POSTFIXES NESTED_SCOPE | SCOPE }
+ | { "::" COMPLEX_NAME }+ TEMPLATE_BRACKETS? METHOD_SCOPE
| POSTFIXES NESTED_SCOPE
| SCOPE;
+SUB_DECLARATION ::=
+ { identifier | reference }+ { TEMPLATE_BRACKETS identifier? | { DYNAMIC_DIMENSION ^ARRAY_TYPE }+ identifier | eps };
+
DICTIONARY ::=
identifier+;
@@ -200,15 +214,23 @@ GET_EXPRESSION ::=
T_EXPRESSION ::=
"{" BLOCK;
+T_EXPRESSION_F ::=
+ identifier { NT_EXPRESSION T_EXPRESSION_F | LT_EXPRESSION }
+ | eps;
+
NT_EXPRESSION ::=
"{" BLOCK
- | NESTED_ROOT_EXPRESSION
- | "(" SUB_EXPRESSION;
+ | "::" NESTED_EXPRESSION ^NESTED
+ | "(" T_SUB_EXPRESSION;
+
+LT_EXPRESSION ::=
+ NESTED_ROOT_EXPRESSION ^ BLOCK;
ROOT_EXPRESSION ::=
identifier {
{ identifier }+ {
- L0 ^OBJECT L0_R L1_OP?
+ "," ^OBJECT SUB_VARIABLE { "," SUB_VARIABLE }* ASSIGN EXPRESSION ^TUPLE_ASSIGNING
+ | L0 ^OBJECT L0_R L1_OP?
| { DYNAMIC_DIMENSION ^ARRAY_TYPE }+ {
identifier ^OBJECT ASSIGN ASSIGN_R
| "{" ^OBJECT COLLECTION "}" ^ COLLECTION_EXPRESSION L3_OP*
@@ -220,6 +242,7 @@ ROOT_EXPRESSION ::=
| ASSIGN EXPRESSION ^PROPERTY_OPERATION
| eps ^PROPERTY_OPERATION }
| eps ^OBJECT }
+ | "," ^OBJECT SUB_VARIABLE { "," SUB_VARIABLE }* ASSIGN EXPRESSION ^TUPLE_ASSIGNING
| reference {
L3 ^OBJECT MESSAGE L3_R
| eps ^OBJECT }
@@ -234,19 +257,23 @@ ROOT_EXPRESSION ::=
| ASSIGN ^OBJECT ASSIGN_R
| L1a_O_OP
| L2 ^OBJECT MESSAGE_PARAMETERS? ")" {
- T_EXPRESSION { identifier NT_EXPRESSION }? ^ TEMPLATE_BLOCK
+ T_EXPRESSION T_EXPRESSION_F ^ TEMPLATE_BLOCK
| ISNIL ^MESSAGE_OPERATION SINGLE_EXPRESSION ^ISNIL_OPERATION
+ | LT_EXPRESSION ^ TEMPLATE_BLOCK
| eps ^MESSAGE_OPERATION }
- | L3 ^OBJECT MESSAGE {
- L3_R {
- L3 L3_F
- | L4_OP
- | L6_OP
- | L9_OP
- | eps }
- | ASSIGN EXPRESSION ^PROPERTY_OPERATION
- | L3 ^PROPERTY_OPERATION L3_F
- | eps ^PROPERTY_OPERATION }
+ | L3 ^OBJECT {
+ OPERATOR MESSAGE L3_R ^OPERATION_TEMPLATE
+ | MESSAGE {
+ L3_R {
+ L3 L3_F
+ | L4_OP
+ | L6_OP
+ | L9_OP
+ | eps }
+ | ASSIGN EXPRESSION ^PROPERTY_OPERATION
+ | L3 ^PROPERTY_OPERATION L3_F
+ | eps ^PROPERTY_OPERATION }
+ }
| L4_O_OP L4_OP*
| L5_O_OP
| LESS ^OBJECT TEMPLATE_ARG { "," TEMPLATE_ARG }* ">" ^TEMPLATE_TYPE
@@ -255,13 +282,15 @@ ROOT_EXPRESSION ::=
| identifier ^OBJECT }
| L7_O_OP
| TRY ^OBJECT TRY_R
- | T_EXPRESSION { identifier NT_EXPRESSION }? ^ TEMPLATE_BLOCK
+ | FNL ^OBJECT FNL_R
+ | ALT ^OBJECT ALT_R
+ | T_EXPRESSION T_EXPRESSION_F ^ TEMPLATE_BLOCK
| "=>" ^OBJECT { SWITCH_OPTION+ SWITCH_LAST_OPTION? } ^SWITCH_OPERATION
| eps ^OBJECT }
| reference {
L3 ^OBJECT MESSAGE MESSAGE_R
| eps ^OBJECT }
- | { string | integer | hexinteger | long | real | character | wide } ^OBJECT L4_OP* L5_OP* L6_OP?
+ | { string | integer | hexinteger | long | real | constant | character | wide } ^OBJECT L3_OP* L4_OP* L5_OP* L6_OP?
| "!" EXPRESSION ^NOT_OPERATION
| "*" SINGLE_EXPRESSION ^VALUE_OPERATION
| "~" SINGLE_EXPRESSION ^BNOT_OPERATION
@@ -313,7 +342,7 @@ NESTED_ROOT_EXPRESSION ::=
| reference {
L3 ^OBJECT MESSAGE MESSAGE_R
| eps ^OBJECT }
- | { string | integer | hexinteger | long | real | character | wide } ^OBJECT L4_OP* L5_OP* L6_OP?
+ | { string | integer | hexinteger | long | real | constant | character | wide } ^OBJECT L4_OP* L5_OP* L6_OP?
| "!" EXPRESSION ^NOT_OPERATION
| "*" SINGLE_EXPRESSION ^VALUE_OPERATION
| "~" SINGLE_EXPRESSION ^BNOT_OPERATION
@@ -351,19 +380,20 @@ EXPRESSION ::=
| eps }
| ASSIGN ^OBJECT ASSIGN_R
| L1a_O_OP
- | L2 ^OBJECT L2_R L9_OP?
+ | L2 ^OBJECT L2_R L3_OP* L4_OP* L5_OP* L6_OP? L7_OP* L9_OP?
| L3 ^OBJECT MESSAGE MESSAGE_R L3_OP* L4_OP* L5_OP* L6_OP? L7_OP* { L8_OP | L9_OP }?
| L4_O_OP L4_OP* L5_OP* L6_OP?
| L5_O_OP L5_OP* L6_OP?
| L6_O_OP L7_OP* L8_OP?
| L7_O_OP
+ | L8_O_OP
| TRY ^OBJECT TRY_R
| NESTED_EXPRESSION ^NESTED L3_OP*
| eps ^OBJECT }
| reference {
L3 ^OBJECT MESSAGE MESSAGE_R
| eps ^OBJECT }
- | { string | integer | hexinteger | long | real | character | wide } ^OBJECT L3_OP* L4_OP* L5_OP* L6_OP?
+ | { string | integer | hexinteger | long | real | constant | character | wide } ^OBJECT L3_OP* L4_OP* L5_OP* L6_OP?
| "(" SUB_EXPRESSION L2_OP? L3_OP* L4_OP* L5_OP* L7_OP* L8_OP?
| "{" BLOCK ^CLOSURE
| "*" EXPRESSION ^VALUE_OPERATION
@@ -384,23 +414,26 @@ NESTED_SUB_EXPRESSION ::=
| eps ^OBJECT }
| L0 ^OBJECT L0_R
| ASSIGN ^OBJECT ASSIGN_R
- | L2 ^OBJECT L2_R L9_OP? ")"
+ | L2 ^OBJECT L2_R L9_OP?
| L3 ^OBJECT MESSAGE MESSAGE_R L3_OP* L4_OP* L5_OP* L6_OP? L9_OP?
| L4_O_OP
| L5_O_OP
| eps ^OBJECT }
| reference ^OBJECT
- | { string | integer | hexinteger | long | real | character | wide } ^OBJECT L4_OP* L5_OP* L6_OP?;
+ | { string | integer | hexinteger | long | real | constant | character | wide } ^OBJECT L4_OP* L5_OP* L6_OP?;
SUB_EXPRESSION ::=
identifier {
identifier+ {
L2 ^OBJECT L2_R L3_OP* L5_OP* { L8_OP | L9_OP }? ")"
+ | "," ^ PARAMETER PARAMETER { "," PARAMETER }* {
+ "=>" RET_EXPRESSION ^CLOSURE ")" ^EXPRESSION
+ | ")" "{" BLOCK ^CLOSURE ^EXPRESSION }
| ")" {
"{" ^ PARAMETER BLOCK ^CLOSURE ^EXPRESSION
| eps ^OBJECT ^EXPRESSION }
}
- | L0 ^OBJECT L0_R L3_OP* L5_OP* ")"
+ | L0 ^OBJECT L0_R L3_OP* L5_OP* L6_OP? ")"
| L2 ^OBJECT L2_R L9_OP? ")"
| L3 ^OBJECT MESSAGE MESSAGE_R L3_OP* L4_OP* L5_OP* L6_OP? L7_OP* L9_OP? ")"
| L4_O_OP L4_OP* L5_OP* ")"
@@ -408,8 +441,9 @@ SUB_EXPRESSION ::=
| L6_O_OP L7_OP* ")"
| L7_O_OP ")"
| "=>" ^ PARAMETER RET_EXPRESSION ^CLOSURE ")" ^EXPRESSION
- | "," ^ PARAMETER PARAMETER { "," PARAMETER }*
- "=>" RET_EXPRESSION ^CLOSURE ")" ^EXPRESSION
+ | "," ^ OBJECT ^ EXPRESSION EXPRESSION { "," EXPRESSION }*
+ { "=>" ^ PARAMETER_BLOCK RET_EXPRESSION ^CLOSURE ")" ^EXPRESSION
+ | ")" ^ PARAMETER_BLOCK "{" BLOCK ^CLOSURE ^EXPRESSION }
| ")" {
"{" ^ PARAMETER BLOCK ^CLOSURE ^EXPRESSION
| eps ^OBJECT ^EXPRESSION }
@@ -417,7 +451,11 @@ SUB_EXPRESSION ::=
| reference {
L3 ^OBJECT MESSAGE MESSAGE_R ")"
| ")" ^OBJECT }
- | { string | integer | hexinteger | long | character | wide } ^OBJECT L4_OP* L5_OP* L6_OP? ")" ^EXPRESSION
+ | { string | integer | hexinteger | long | constant | character | wide } ^OBJECT L4_OP* L5_OP* L6_OP? {
+ "," ^EXPRESSION EXPRESSION { "," EXPRESSION }* ^ TUPLE_COLLECTION
+ | eps
+ } ")" ^EXPRESSION
+
| "*" SINGLE_EXPRESSION ^VALUE_OPERATION ")" ^EXPRESSION
| "!" EXPRESSION ^NOT_OPERATION ")" ^EXPRESSION
| "~" SINGLE_EXPRESSION ^BNOT_OPERATION
@@ -425,6 +463,16 @@ SUB_EXPRESSION ::=
| "$name" SINGLE_EXPRESSION ^NAME_OPERATION ^EXPRESSION
| "$len" SINGLE_EXPRESSION ^LEN_OPERATION;
+T_SUB_EXPRESSION ::=
+ identifier+ {
+ "," ^ PARAMETER PARAMETER { "," PARAMETER }* {
+ ")" "{" BLOCK ^CLOSURE ^EXPRESSION }
+ | ")" {
+ "{" ^ PARAMETER BLOCK ^CLOSURE ^EXPRESSION
+ | eps ^OBJECT ^EXPRESSION
+ }
+ };
+
SUB_SINGLE_EXPRESSION ::=
identifier {
{ identifier }+ {
@@ -441,7 +489,7 @@ SUB_SINGLE_EXPRESSION ::=
| L5_O_OP ")"
| ")" ^OBJECT }
| reference ^OBJECT ")"
- | { string | integer | hexinteger | long | real | character | wide } ^OBJECT L4_OP* L5_OP* L6_OP? ")";
+ | { string | integer | hexinteger | long | real | constant | character | wide } ^OBJECT L4_OP* L5_OP* L6_OP? ")";
SUB_L3_SINGLE_EXPRESSION ::=
identifier {
@@ -460,14 +508,15 @@ SUB_L3_SINGLE_EXPRESSION ::=
| L4_O_OP L4_OP* ")"
| L5_O_OP ")"
| "=>" ^ PARAMETER RET_EXPRESSION ^CLOSURE ")" ^EXPRESSION
- | "," ^ PARAMETER PARAMETER { "," PARAMETER }*
- "=>" RET_EXPRESSION ^CLOSURE ")" ^EXPRESSION
+ | "," ^ PARAMETER PARAMETER { "," PARAMETER }* {
+ "=>" RET_EXPRESSION ^CLOSURE ")" ^EXPRESSION
+ | ")" "{" BLOCK ^CLOSURE ^EXPRESSION }
| ")" {
"{" ^ PARAMETER BLOCK ^CLOSURE
| eps ^OBJECT }
}
| reference ^OBJECT ")"
- | { string | integer | hexinteger | long | real | character | wide } ^OBJECT ")"
+ | { string | integer | hexinteger | long | real | constant | character | wide } ^OBJECT ")"
| "*" SINGLE_EXPRESSION ^VALUE_OPERATION ")"
| "!" EXPRESSION ^NOT_OPERATION ")"
| "~" SINGLE_EXPRESSION ^BNOT_OPERATION ")"
@@ -492,7 +541,7 @@ L4_EXPRESSION ::=
| L3 ^OBJECT MESSAGE MESSAGE_R L3_OP*
| eps ^OBJECT }
| reference ^OBJECT
- | { string | integer | hexinteger | long | real | character | wide } ^OBJECT
+ | { string | integer | hexinteger | long | real | constant | character | wide } ^OBJECT
| "(" SUB_EXPRESSION
| "*" SINGLE_EXPRESSION ^VALUE_OPERATION
| "!" L4_EXPRESSION ^NOT_OPERATION
@@ -514,8 +563,8 @@ L5_EXPRESSION ::=
| L4_O_OP L4_OP*
| eps ^OBJECT }
| reference ^OBJECT
- | { string | integer | hexinteger | long | real | character | wide } ^OBJECT L4_OP*
- | "(" SUB_EXPRESSION
+ | { string | integer | hexinteger | long | real | constant | character | wide } ^OBJECT L4_OP*
+ | "(" SUB_EXPRESSION L3_OP* L4_OP*
| "*" SINGLE_EXPRESSION ^VALUE_OPERATION
| "!" L5_EXPRESSION ^NOT_OPERATION
| "~" SINGLE_EXPRESSION ^BNOT_OPERATION
@@ -536,7 +585,7 @@ L3_F ::=
L3_SINGLE_EXPRESSION ::=
identifier ^OBJECT
| reference ^OBJECT
- | { string | integer | hexinteger | character } ^OBJECT
+ | { string | integer | hexinteger | character | constant | long | real } ^OBJECT
| "(" SUB_L3_SINGLE_EXPRESSION;
L6_EXPRESSION ::=
@@ -553,7 +602,7 @@ L6_EXPRESSION ::=
| L5_O_OP
| eps ^OBJECT }
| reference ^OBJECT
- | { string | integer | hexinteger | long | real | character | wide } ^OBJECT L4_OP* L5_OP*
+ | { string | integer | hexinteger | long | real | constant | character | wide } ^OBJECT L4_OP* L5_OP*
| "(" SUB_EXPRESSION
| "*" SINGLE_EXPRESSION ^VALUE_OPERATION
| "!" L6_EXPRESSION ^NOT_OPERATION
@@ -577,7 +626,7 @@ L7_EXPRESSION ::=
| L6_O_OP
| eps ^OBJECT }
| reference ^OBJECT
- | { string | integer | hexinteger | long | real | character | wide } ^OBJECT L4_OP* L5_OP* L6_OP?
+ | { string | integer | hexinteger | long | real | constant | character | wide } ^OBJECT L4_OP* L5_OP* L6_OP?
| "(" SUB_EXPRESSION L6_OP?
| "*" SINGLE_EXPRESSION ^VALUE_OPERATION
| "!" L7_EXPRESSION ^NOT_OPERATION
@@ -618,11 +667,13 @@ NOTGREATER ::= "<=";
GREATER ::= ">";
AND ::= "&&";
OR ::= "||";
+XOR ::= "^^";
IF ::= "?";
ELSE ::= "!";
TRY ::= "\\";
ALT ::= "\";
ISNIL ::= "??";
+FNL ::= "$fnl";
L0_R ::=
EXPRESSION "]" ^INDEXER_OPERATION;
@@ -667,6 +718,7 @@ L3_OP ::=
L4_OP ::=
BAND L4_EXPRESSION ^BAND_OPERATION
| BOR L4_EXPRESSION ^BOR_OPERATION
+ | BXOR L4_EXPRESSION ^BXOR_OPERATION
| STAR L4_EXPRESSION ^MUL_OPERATION
| DIV L4_EXPRESSION ^DIV_OPERATION
| SHL L4_EXPRESSION ^SHL_OPERATION
@@ -714,11 +766,13 @@ L6_O_OP_WM ::=
L7_OP ::=
AND L7_EXPRESSION ^AND_OPERATION
- | OR L7_EXPRESSION ^OR_OPERATION;
+ | OR L7_EXPRESSION ^OR_OPERATION
+ | XOR L7_EXPRESSION ^OR_OPERATION;
L7_O_OP ::=
AND ^OBJECT L7_EXPRESSION ^AND_OPERATION
- | OR ^OBJECT L7_EXPRESSION ^OR_OPERATION;
+ | OR ^OBJECT L7_EXPRESSION ^OR_OPERATION
+ | XOR ^OBJECT L7_EXPRESSION ^OR_OPERATION;
IF_R ::=
L8_EXPRESSION { eps ^IF_OPERATION | ":" L8_EXPRESSION ^IF_ELSE_OPERATION };
@@ -730,8 +784,15 @@ L8_OP ::=
IF IF_R
| ELSE ELSE_R;
+L8_O_OP ::=
+ IF ^OBJECT IF_R
+ | ELSE ^OBJECT ELSE_R;
+
TRY_R ::=
- CATCH ^CATCH_OPERATION;
+ CATCH { "$fnl" FINALLY }? ^CATCH_OPERATION;
+
+FNL_R ::=
+ FINALLY ^FINAL_OPERATION;
ALT_R ::=
CATCH ^ALT_OPERATION;
@@ -739,6 +800,9 @@ ALT_R ::=
CATCH ::=
MESSAGE MESSAGE_R;
+FINALLY ::=
+ L7_EXPRESSION;
+
L9_OP ::=
TRY TRY_R
| ALT ALT_R
@@ -763,9 +827,18 @@ PARAMETER ::=
| TEMPLATE_BRACKETS identifier
| eps };
+SUB_VARIABLE ::=
+ identifier+ {
+ DYNAMIC_DIMENSION ^ARRAY_TYPE identifier
+ | TEMPLATE_BRACKETS identifier
+ | eps };
+
MESSAGE ::=
identifier;
+OPERATOR ::=
+ "\" ^ ALT_OPERATION | "?" ^ IF_OPERATION | "!" ^ ELSE_OPERATION;
+
SWITCH_OPTION ::=
identifier ^ OBJECT SWITCH_CODE
| { integer | character | string } ^ OBJECT SWITCH_CODE;
@@ -777,7 +850,7 @@ SWITCH_CODE ::=
"{" BLOCK;
COLLECTION ::=
- EXPRESSION { "," EXPRESSION }+ ;
+ EXPRESSION { "," EXPRESSION }* ;
POSTFIX ::=
identifier {
diff --git a/doc/api/extensions-math-summary.html b/doc/api/extensions-math-summary.html
index 91d7cb5c9d..01f6ee723c 100644
--- a/doc/api/extensions-math-summary.html
+++ b/doc/api/extensions-math-summary.html
@@ -2,7 +2,7 @@
-ELENA Standard Library 5.8: Module extensions'math
+ELENA Standard Library 6.0: Module extensions'math
@@ -19,7 +19,7 @@
-ELENA Standard Library
5.8
+ELENA Standard Library
6.0
@@ -48,7 +48,7 @@
-sealed Singleton abs
+public class abs
|
@@ -57,7 +57,7 @@
-sealed Singleton arccos
+public class arccos
|
@@ -66,7 +66,7 @@
-sealed Singleton arcsin
+public class arcsin
|
@@ -75,7 +75,7 @@
-sealed Singleton arctan
+public class arctan
|
@@ -84,7 +84,7 @@
-sealed Singleton ceil
+public class ceil
|
@@ -93,7 +93,7 @@
-sealed Singleton cos
+public class cos
|
@@ -102,7 +102,7 @@
-sealed Singleton exp
+public class exp
|
@@ -111,7 +111,7 @@
-sealed Singleton floor
+public class floor
|
@@ -120,144 +120,88 @@
-sealed Singleton frac
+public class frac
|
-intg
- |
-
-
-sealed Singleton intg
- |
-
-
-
-ln
- |
-
-
-sealed Singleton ln
- |
-
-
-
-log10
+modulo
|
-sealed Singleton log10
+public class modulo
|
-log2
+truncate
|
-sealed Singleton log2
+public class truncate
|
-max
+sqr
|
-sealed Singleton max
+public class sqr
|
-min
+sqrt
|
-sealed Singleton min
+public class sqrt
|
-modulo
+ln
|
-sealed Singleton modulo
+public class ln
|
-power
- |
-
-
-sealed Singleton power
- |
-
-
-
sin
|
-sealed Singleton sin
- |
-
-
-
-sqr
- |
-
-
-sealed Singleton sqr
+public class sin
|
-sqrt
+tan
|
-sealed Singleton sqrt
+public class tan
|
-tan
+log2
|
-sealed Singleton tan
+public class log2
|
-truncate
- |
-
-
-sealed Singleton truncate
- |
-
-
-
-
-
-
-Extended Class Summary
-
-
-Extended class name |
-Description |
-
-
-
-RealMatrix
+log10
|
-RealMatrix
+public class log10
|
@@ -275,7 +219,7 @@
diff --git a/doc/api/extensions.html b/doc/api/extensions.html
index eb78dcf10b..325a6e559b 100644
--- a/doc/api/extensions.html
+++ b/doc/api/extensions.html
@@ -724,13 +724,40 @@ Extension Summary
+ByteNumber |
+
+toByte()
+
+ |
+
+
+
+
+ShortNumber |
+
+toShort()
+
+ |
+
+
+
+
+LongNumber |
+
+toLong()
+
+ |
+
+
+
+
RealNumber |
toReal()
|
-
+
Enumerable |
@@ -739,7 +766,7 @@ Extension Summary
-
+
Array |
@@ -748,7 +775,7 @@ Extension Summary
-
+
|
@@ -757,7 +784,7 @@ Extension Summary
-
+
|
@@ -766,7 +793,7 @@ Extension Summary
-
+
|
@@ -775,7 +802,7 @@ Extension Summary
-
+
|
@@ -784,7 +811,7 @@ Extension Summary
-
+
|
@@ -793,7 +820,7 @@ Extension Summary
-
+
|
@@ -802,7 +829,7 @@ Extension Summary
-
+
|
diff --git a/doc/api/index.html b/doc/api/index.html
index cafb0c6fc2..2a925a3928 100644
--- a/doc/api/index.html
+++ b/doc/api/index.html
@@ -89,7 +89,7 @@
-system'math(not yet migrated)
+system'math
|
@@ -158,7 +158,7 @@
|
-system'dynamic(not yet migrated)
+system'dynamic
|
@@ -287,7 +287,7 @@
|
-extensions'math(not yet migrated)
+extensions'math
|
diff --git a/doc/api/system-calendar.html b/doc/api/system-calendar.html
index b2ce28a479..ca92dfa731 100644
--- a/doc/api/system-calendar.html
+++ b/doc/api/system-calendar.html
@@ -1339,7 +1339,7 @@ Symbol Summary
|
-public |
+public Date
now
|
@@ -1376,7 +1376,7 @@ Symbol Summary
-public |
+public Date
utcNow
|
diff --git a/doc/api/system-collections-summary.html b/doc/api/system-collections-summary.html
index 78c0308b73..841665c827 100644
--- a/doc/api/system-collections-summary.html
+++ b/doc/api/system-collections-summary.html
@@ -107,6 +107,15 @@
+Tuple<T1,T2>
+ |
+
+
+public template Tuple<T1,T2>
+ |
+
+
+
Tuple<T1,T2,T3>
|
@@ -114,7 +123,7 @@
public template Tuple<T1,T2,T3>
|
-
+
Tuple<T1,T2,T3,T4>
|
@@ -123,7 +132,7 @@
public template Tuple<T1,T2,T3,T4>
-
+
Tuple<T1,T2,T3,T4,T5>
|
@@ -132,7 +141,7 @@
public template Tuple<T1,T2,T3,T4,T5>
-
+
Tuple<T1,T2,T3,T4,T5,T6>
|
diff --git a/doc/api/system-collections.html b/doc/api/system-collections.html
index a9dc8338d8..3f172ad144 100644
--- a/doc/api/system-collections.html
+++ b/doc/api/system-collections.html
@@ -1719,15 +1719,170 @@ Property Summary
Item1()
+
+
+
+
+
+-
+
Conversion Summary
+
+
+Modifier and Type |
+Conversion Method |
+
+
+
+
+Tuple<T1> |
+
+cast()
+ |
+
+
+
+
+
+
+-
+
Method Summary
+
+
+Modifier and Type |
+Method |
+
+
+
+
+ |
+
+at(IntNumber index)
+
+ |
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-public class ShortNumber
-a signed 16 bit integer
-
-
-
-
-
--
-
Field Summary
-
-
-Modifier and Type |
-Field |
-
- |
+RealNumber
-theValue
+sqrt()
+
|
-
-
-
-
-
--
-
Constructor / Static Method Summary
-
-
-
-
-
--
-
Static Property Summary
-
-
-Modifier and Type |
-Static Property |
-
-get ShortNumber |
+RealNumber
-MinValue()
-
-Returns the minimal value (-32768)
+arctan()
+
|
-get ShortNumber |
+RealNumber
-MaxValue()
-
-Returns the maxial value (32767)
+arcsin()
+
|
-
-
-
-
-
--
-
Property Summary
-
-
-Modifier and Type |
-Property |
-
-get ShortNumber |
+RealNumber
-BInverted()
-
-bitwise inversion
+arccos()
+
|
-
-
-
-
-
--
-
Conversion Summary
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+public class ShortNumber
+a signed 16 bit integer
+
+
+
+
+
+-
+
Field Summary
+
+
+Modifier and Type |
+Field |
+
+
|
-bxor(n)
-
+theValue
|
+
+
+
+
+
+-
+
Constructor / Static Method Summary
+
+
+Modifier and Type |
+Constructor / Static Method |
+
ShortNumber |
-add(ShortNumber n)
+constructor()
-returns the sum
+creates the object with a default value (0)
|
@@ -11481,10 +11734,10 @@ Method Summary
ShortNumber
-subtract(ShortNumber n)
+constructor(ShortNumber s)
-returns the difference
+creates the object with specified value
|
@@ -11492,10 +11745,10 @@ Method Summary
ShortNumber
-multiply(ShortNumber n)
+constructor(ByteNumber b)
-returns the product
+creates the object with specified value
|
@@ -11503,54 +11756,322 @@ Method Summary
ShortNumber
-divide(ShortNumber n)
+constructor(IntNumber n)
-
-returns the result of integer division
|
+
+
+
+
+
+-
+
Static Property Summary
+
+
+
+
+
+-
+
Property Summary
+
+
+
+
+
+-
+
Conversion Summary
+
+
+Modifier and Type |
+Conversion Method |
+
+
-ShortNumber |
+ByteNumber
-divide(ByteNumber n)
-
+cast()
-returns the result of integer division
+Returns the byte value
+ |
+
+
+
+
+IntNumber |
+
+cast()
+
+Returns the integer value
+ |
+
+
+
+
+UIntNumber |
+
+cast()
+
+Returns the unsigned integer value
+ |
+
+
+
+
+LongNumber |
+
+cast()
+
+Returns the long integer value
+ |
+
+
+
+
+RealNumber |
+
+cast()
+
+Returns the real number value
+ |
+
+
+
+
+ShortNumber |
+
+cast()
+ |
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-public class String
-A UTF-8 literal value
-
+
+
+-
+
Extension Summary
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+public class String
+A UTF-8 literal value
+
-
@@ -13002,20 +13632,21 @@
Method Summary
-
+
-public class UnsafePointer
+public class
UIntNumber
+
A unsigned 32 bit integer
@@ -13024,7 +13655,25 @@ UnsafePointer
-
+-
+
+
@@ -13042,125 +13691,114 @@
Field Summary
-pointer
+_value
|
-
+
-
-
Conversion Summary
+Constructor / Static Method Summary
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-abstract public class IntBaseNumber
-a base integer value
-
-
-
-
+
-
-
Property Summary
+Static Property Summary
Modifier and Type |
-Property |
+Static Property |
-get abstract |
+get UIntNumber
-BInverted()
+MinValue()
+
+Creates the object with the minimal value
+ |
+
+
+
+
+get UIntNumber |
+
+MaxValue()
+
+Creates the object with the maximal value
|
@@ -13169,101 +13807,109 @@ Property Summary
-
-
Conversion Summary
+Property Summary
Modifier and Type |
-Conversion Method |
+Property |
-IntBaseNumber |
+get UIntNumber
-cast()
+BInverted()
+
+Bitwise inversion
|
-
+
-
-
Method Summary
+Conversion Summary
Modifier and Type |
-Method |
+Conversion Method |
-abstract |
+ShortNumber
-band(o)
-
+cast()
-Executes bitwise AND operation; should be overridden
+Returns the value as a short integer
|
-abstract |
+ByteNumber
-bor(o)
-
+cast()
-Executes bitwise OR operation; should be overridden
+Returns the byte value
|
-abstract |
+IntNumber
-bxor(o)
-
-
-Executes bitwise XOR operation; should be overridden
+cast()
|
- |
+LongNumber
-band(BaseVariable var)
-
+cast()
+
+Returns the long integer
|
- |
+RealNumber
-bor(BaseVariable var)
-
+cast()
+
+Returns the real number
|
- |
+UIntNumber
-bxor(BaseVariable var)
-
+cast()
|
+
+
+
+
+
+-
+
Method Summary
+
+
+Modifier and Type |
+Method |
+
BoolValue |
-allMask(operand)
+less(n)
-
-Returns true if all the mask bits are set
|
@@ -13271,115 +13917,54 @@ Method Summary
BoolValue
-anyMask(operand)
+equal(o)
-
-Returns true if any of the mask bits are set
|
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-public class UIntNumber
-A unsigned 32 bit integer
-
-
-
-
-
--
-
Field Summary
-
-
-Modifier and Type |
-Field |
-
-__int[4] |
+String
-theValue
+toPrintable()
+
+
+Returns the literal presentation
|
-
-
-
-
-
--
-
Constructor / Static Method Summary
-
-
-
-
-
--
-
Static Property Summary
-
-
-Modifier and Type |
-Static Property |
+
+
+
+ |
+
+band(n)
+
+ |
-get UIntNumber |
+
-MinValue()
-
-Creates the object with the minimal value
+bor(n)
+
|
-get UIntNumber |
+
-MaxValue()
-
-Creates the object with the maximal value
+bxor(n)
+
|
-
-
-
-
-
--
-
Property Summary
-
-
-
-
-
--
-
Conversion Summary
-
-
-Modifier and Type |
-Conversion Method |
-
-
-
-
-ShortNumber |
-
-cast()
-
-Returns the value as a short integer
- |
-
-
-
-
-ByteNumber |
-
-cast()
-
-Returns the byte value
- |
-
-
-
-
-IntNumber |
-
-cast()
- |
-
-
-
-
-LongNumber |
-
-cast()
-
-Returns the long integer
- |
-
-
-
-
-RealNumber |
-
-cast()
-
-Returns the real number
- |
-
-
-
-
-UIntNumber |
-
-cast()
- |
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-public class nilValue
-A nil value
-
-
-
--
-'Object
--
-
--
-system'nilValue
+
+
+-
+
Extension Summary
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+public class UnsafePointer
+
+
+
+-
+'Object
+-
+
+-
+system'UnsafePointer
+
+
+
+
+
+-
+
Field Summary
+
+
+Modifier and Type |
+Field |
+
+
+
+
+ |
+
+pointer
+ |
+
+
+
+
+
+
+-
+
Conversion Summary
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+public class nilValue
+A nil value
+
+
+
+
+
+-
+
Method Summary
+
+
+Modifier and Type |
+Method |
+
+
+
+
+BoolValue |
+
+equal(object)
+
+
+Returns true if the specified object is nil.
+ |
+
+
+
+
+ |
+
+dispatch()
+
+ |
+
+
+
+
+ |
+
+typecast:#generic()
+
+
+Returns nil Any typecasting message will be handled and nil value returned
+ |
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+public class KeyValue
+A key - object pair
Extends the object with a key property
+
+
+
+
+
+-
+
Field Summary
+
+
+Modifier and Type |
+Field |
+
+
+
+
+Object |
+
+key
+ |
+
+
+
+
+Object |
+
+value
+ |
+
+
+
+
+
+
+-
+
Constructor / Static Method Summary
+
+
+Modifier and Type |
+Constructor / Static Method |
+
+
+
+
+KeyValue |
+
+new(key, value)
+
+
+Creates a new object
+ |
+
+
+
+
+
+
+-
+
Property Summary
+
+
+Modifier and Type |
+Property |
+
+
+
+
+get |
+
+Key()
+
+Returns the key
+ |
+
+
+
+
+get |
+
+Value()
+
+Returns the value
+ |
+
+
+
+
+set |
+
+Value(value)
+
+ |
+
+
+
+
+
+-
+
Conversion Summary
+
+
+Modifier and Type |
+Conversion Method |
+
+
+
+
+KeyValue |
+
+cast()
+ |
+
+
@@ -14288,18 +15082,16 @@
Method Summary
BoolValue
-equal(object)
+equal(o)
-
-Returns true if the specified object is nil.
|
- |
+String
-dispatch()
+toPrintable()
|
@@ -14308,10 +15100,10 @@
Method Summary
-typecast:#generic()
+dispatch()
-Returns nil Any typecasting message will be handled and nil value returned
+Redirects the incoming messages to the object
|
@@ -15686,40 +16478,13 @@
Method Summary
- |
-
-convert(IntNumber n, ShortNumber retVal)
-
- |
-
-
-
-
- |
-
-convert(UIntNumber n, ShortNumber retVal)
-
- |
-
-
-
-
- |
-
-convert(ByteNumber b, ShortNumber retVal)
-
- |
-
-
-
-
ShortNumber |
convert(BaseVariable v)
|
-
+
ShortNumber |
@@ -15728,7 +16493,7 @@ Method Summary
-
+
ShortNumber |
@@ -15737,7 +16502,7 @@ Method Summary
-
+
ShortNumber |
@@ -15746,7 +16511,7 @@ Method Summary
-
+
ShortNumber |
@@ -15755,7 +16520,7 @@ Method Summary
-
+
ShortNumber |
@@ -15764,7 +16529,7 @@ Method Summary
-
+
ShortNumber |
@@ -15773,7 +16538,7 @@ Method Summary
-
+
ShortNumber |
@@ -15782,7 +16547,7 @@ Method Summary
-
+
ShortNumber |
@@ -15872,7 +16637,7 @@ Method Summary
IntNumber
-convert(CharValue ch)
+convert(UIntNumber n)
|
@@ -15881,7 +16646,7 @@
Method Summary
IntNumber
-convert(LongNumber l)
+convert(CharValue ch)
|
@@ -15890,7 +16655,7 @@
Method Summary
IntNumber
-convert(RealNumber r)
+convert(LongNumber l)
|
@@ -15899,7 +16664,7 @@
Method Summary
IntNumber
-convert(String s, IntNumber radix)
+convert(RealNumber r)
|
@@ -15908,7 +16673,7 @@
Method Summary
IntNumber
-convert(String s)
+convert(String s, IntNumber radix)
|
@@ -15917,7 +16682,7 @@
Method Summary
IntNumber
-convert(WideString s, IntNumber radix)
+convert(String s)
|
@@ -15926,7 +16691,7 @@
Method Summary
IntNumber
-convert(WideString s)
+convert(WideString s, IntNumber radix)
|
@@ -15935,7 +16700,7 @@
Method Summary
IntNumber
-convert(UIntNumber n)
+convert(WideString s)
|
@@ -16011,7 +16776,7 @@
Method Summary
UIntNumber
-convert(LongNumber l)
+convert(ShortNumber s)
|
@@ -16020,7 +16785,7 @@
Method Summary
UIntNumber
-convert(String s, IntNumber radix)
+convert(LongNumber l)
|
@@ -16029,6 +16794,15 @@
Method Summary
UIntNumber
+convert(String s, IntNumber radix)
+
+ |
+
+
+
+
+UIntNumber |
+
convert(WideString s, IntNumber radix)
|
@@ -16972,7 +17746,158 @@ Conversion Summary
-OutOfMemoryException |
+OutOfMemoryException
+
+cast()
+ |
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+public class MethodNotFoundException
+
+
+
+
+
+-
+
Field Summary
+
+
+Modifier and Type |
+Field |
+
+
+
+
+String |
+
+message
+ |
+
+
+
+
+CallStack |
+
+callStack
+ |
+
+
+
+
+
+
+-
+
Constructor / Static Method Summary
+
+
+
+
+
+-
+
Conversion Summary
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+public class SymbolLoaderException
+
+
+
+-
+'Object
+-
+
+-
+system'SymbolLoaderException
+
+
+
+
+
+-
+
Conversion Summary
+
+
+Modifier and Type |
+Conversion Method |
+
+
+
+
+SymbolLoaderException |
cast()
|
@@ -16982,20 +17907,20 @@ Conversion Summary
-
+
-public class MethodNotFoundException
+public class
OutOfRangeException
@@ -17008,7 +17933,7 @@ MethodNotFoundException
-
-
-system'MethodNotFoundException
+system'OutOfRangeException
@@ -17054,63 +17979,24 @@
Constructor / Static Method Summary
-MethodNotFoundException |
+OutOfRangeException
-new(Object target, Message mssg)
+new()
|
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-public class SymbolLoaderException
-
-
-
--
-'Object
--
-
--
-system'SymbolLoaderException
-
-
-
-
@@ -17123,7 +18009,7 @@
Conversion Summary
-SymbolLoaderException |
+OutOfRangeException
cast()
|
@@ -17133,20 +18019,20 @@ Conversion Summary
-
+
-public class OutOfRangeException
+public class
TypeLoaderException
@@ -17159,7 +18045,7 @@ OutOfRangeException
-
-
-system'OutOfRangeException
+system'TypeLoaderException
@@ -17205,18 +18091,9 @@
Constructor / Static Method Summary
-OutOfRangeException |
-
-new()
-
- |
-
-
-
-
-OutOfRangeException |
+TypeLoaderException
-new(String message)
+new(String className)
|
@@ -17235,7 +18112,7 @@
Conversion Summary
-OutOfRangeException |
+TypeLoaderException
cast()
|
@@ -17529,167 +18406,6 @@ Method Summary
-
-
-
-
-
-
-
-
-
-public template Tuple<T1,T2>
-
-
-
-
-
--
-
Field Summary
-
-
-Modifier and Type |
-Field |
-
-
-
-
-T1 |
-
-Item1
- |
-
-
-
-
-T2 |
-
-Item2
- |
-
-
-
-
-
-
--
-
Constructor / Static Method Summary
-
-
-Modifier and Type |
-Constructor / Static Method |
-
-
-
-
-Tuple<T1,T2> |
-
-constructor()
-
- |
-
-
-
-
-Tuple<T1,T2> |
-
-constructor(T1 o1, T2 o2)
-
- |
-
-
-
-
-Tuple<T1,T2> |
-
-constructor(T1 o1)
-
- |
-
-
-
-
-
-
--
-
Property Summary
-
-
-Modifier and Type |
-Property |
-
-
-
-
-get T1 |
-
-Item1()
- |
-
-
-
-
-set |
-
-Item1(T1 value)
-
- |
-
-
-
-
-get T2 |
-
-Item2()
- |
-
-
-
-
-set |
-
-Item2(T2 value)
-
- |
-
-
-
-
-
-
--
-
Conversion Summary
-
-
-Modifier and Type |
-Conversion Method |
-
-
-
-
-Tuple<T1,T2> |
-
-cast()
- |
-
-
-
-
-
-
@@ -18576,6 +19292,43 @@ Method Summary
+
+
+
+
+
+
+
+
+-
+
Symbol Summary
+
+
+Modifier and Type |
+Name |
+
+
+
+public RealNumber |
+
+Pi_value
+ |
+
+
+
+
+
+
diff --git a/doc/tech/bytecode60.txt b/doc/tech/bytecode60.txt
index dbabe137d4..120a99d727 100644
--- a/doc/tech/bytecode60.txt
+++ b/doc/tech/bytecode60.txt
@@ -96,6 +96,11 @@ ELENA byte codes (or ecodes)
sellt r1, r2 - acc <= COMP.LE ? r1 : r2
+ selult r1, r2 - temp1 : 4 << acc;
+ temp2 : 4 << sp[0];
+ temp2 < temp1 ? r1 : r2;
+ used to compar the unsigned numbers
+
set {prefix}:r - r => acc
set dp:i - dp[i] => acc
@@ -112,9 +117,15 @@ ELENA byte codes (or ecodes)
xassign i - acc[i] := sp[0];
direct operation
+ xassignsp - sp => acc
+
xget - acc[index] => acc
- xassignsp - sp => acc
+ xload - index := acc[index]
+
+ xlload - long:index := long:acc[index]
+
+ xset fp:i - fp[index + i] => acc
Call operations:
@@ -193,6 +204,8 @@ ELENA byte codes (or ecodes)
swap sp:i - acc <=> sp[i]
+ xadd dp:disp - index += [dp[disp]];
+
xrefresh sp:i - cached_sp[i] := sp[i];
xflush sp:i - sp[i] := cached_sp[i];
@@ -241,6 +254,8 @@ ELENA byte codes (or ecodes)
dtrans - sp[0] >> acc, index ptrs
+ fill i, r - fills acc with r i-times
+
len - index := acc.length;
returns the object length
@@ -281,6 +296,8 @@ ELENA byte codes (or ecodes)
sp[0] >> temp;
out: acc contains the class instance, index - undefined
+ xfill r - fills acc with r int(sp[0])-times
+
xredirect m - search acc::VMT for the {m.action + index.argCount} in index;
if found jumps to it; binary search is used ; index, acc presaved;
index is set the original valuze
@@ -299,7 +316,13 @@ ELENA byte codes (or ecodes)
jlt label - jump if COMP.LT == 1
- jge label - jump if COMP.LT == 0
+ jult label - jump if COMP.BL == 1
+
+ jle label - jump if COMP.LT == 1 && COMP.EQ == 1
+
+ jge label - jump if COMP.LT == 0 && COMP.EQ == 1
+
+ jgr label - jump if COMP.LT == 0
Arithmeric operations:
@@ -308,6 +331,9 @@ ELENA byte codes (or ecodes)
andn n - index := index & n
+ fabs dp:disp - double:tmp << sp[0];
+ double:dp[disp] := abs(tmp)
+
fadd dp:disp, n - temp : n << sp[0];
[dp[disp]] += temp;
n = 8
@@ -316,10 +342,19 @@ ELENA byte codes (or ecodes)
[dp[disp]] /= temp;
n = 8
+ fexp dp:disp - double:tmp << sp[0];
+ double:dp[disp] := exp(tmp)
+
fmul dp:disp, n - temp : n << sp[0];
[dp[disp]] *= temp;
n = 8
+ fround dp:disp - double:tmp << sp[0];
+ double:dp[disp] := trunc(tmp)
+
+ fsqrt dp:disp - double:tmp << sp[0];
+ double:dp[disp] := sqrt(tmp)
+
fsub dp:disp, n - temp : n << sp[0];
[dp[disp]] -= temp;
n = 8
@@ -339,6 +374,10 @@ ELENA byte codes (or ecodes)
[dp[disp]] /= temp;
n = 1,2,4,8
+ udiv dp:disp, n - temp : n << sp[0];
+ [dp[disp]] /= temp; as unsigned
+ n = 1,2,4,8
+
imul dp:disp, n - temp : n << sp[0];
[dp[disp]] *= temp;
n = 1,2,4,8
diff --git a/doc/todo.txt b/doc/todo.txt
index ec2c1e2fce..fee03739dd 100644
--- a/doc/todo.txt
+++ b/doc/todo.txt
@@ -4,10 +4,19 @@ In development:
[development]
### EPOCH: elena 6.0 - redux ###
- === Iteration 14 ===
- * release
-
=== Iteration 15 ===
+
+ * test x86, x86-64, i386, amd64, ppc64le, arm64
+
+ === Iteration 16 ===
+ * vm console : ParsingExpression : https://github.com/ELENA-LANG/tutorials/tree/master/ParsingExpression1
+ * vm console : ParsingExpression : https://github.com/ELENA-LANG/tutorials/tree/master/ParsingExpression2
+
+ * ide : create a new project, save it, change it and save it
+ * ide : refreshing auto watch - with the same name, unused
+ * ide : set / remove breakpoints
+ * ide : menu - clear all breakpoints
+
! migrate rest of elena 5.0 functionality (script engine, infinite enumeration, ...)
! script and db samples
! x86 : gui
@@ -17,23 +26,37 @@ In development:
! ide : vm console
* ParsingExpression : https://github.com/ELENA-LANG/tutorials/tree/master/ParsingExpression2
! sm : generate some basic templates from vm console - hello world sample
- ! elena sm : linux
- ! elena vm : ppc64
! script samples : win x86, win x86-64, linix i386, linux amd64
! migrate all script engine tutorials : win x86, win x86-64, linix i386, linux amd64
! regression tests : github issues
- ! i386 : multi-threading
- ! x86-64 : multi-threading
- ! x86-64 : gui
! elc : using custom grammar for parsing a source
! elenavm : test all rosetta code samples for vm
! elenavm : critical exception handlers
+ * Class Constants : review doc and implement if requiered
+ * fix an issue with : Enumerable - probably we do not need them (make the internal)?
+ * optimization : copy a sub array to another array - starting
+ * x86 : gui - starting - new project type
+ * ide : before compiling, make sure the source file is saved
+
+ * switch expression
+ * optimization : copy a sub array to another array
* redesign switch statement : it should be possible to use as an expression as well
(so we cannot use => anymore : e.g. console.printLine(x => 1 { "first" } 2 { "second" } 3 { "third" }) )
console.printLine(x $sel 1 => "first", 2 => "second", 3 => "third");
+ * ide : closing unsaved file - closing unsaved
+ * ide : selecting an error line - try to get rid of blicking
+ * ide : show hex number
+ * ide : show project name as a app title (new / existing projects / single file project)
+
+ * elenavm : preloaded symbol, support preloaded symbols : dynamic
+ * elenavm : loading preloaded symbols for newly loaded modules
+
+ * #508 : support strong-typed variables for tuple unboxing
+ * multi-value return - #508
+
+ * ide debugger : stepping in the loop (for)
- * operator .\
* optimization : copy a sub array to another array
* int32 : implement direct neg, not operations; use it directly for IntNumber
@@ -56,32 +79,44 @@ In development:
* ldoc : symbol should return the type and it should be possible to see its api (e.g. system'console)
* rosetta samples : 20
* examples : datetime
- * ide : change status to ready when writing / selecting files
- * ide : selecting with a mouse
* examples : replace, trans
- * ide : new source
* examples : textdb, textfile
* ide : on start : set focus inside the edit frame if available
* ldoc : get rid of BaseEnumerator and so on
* strong typed forward constant
* arrange action for i386 / amd64 linux release
+ * ide : debug vm client app
+ * ide : editor context menu
+ * ide : tool bar
+ * x86 : gui
+ * system module - it should be possible to use type aliases (replace all cases of using direct types
+ for symbols in system (int,string,wide))
+ * elenavm : protect rdata memory sections
+ * console & files samples
+ * new opcode : fexp, fln - ppc64le, arm64
+ * new opcode : fsin, fcos, farctan, fpi - ppc64le, arm64
- === Iteration 16 ===
+ === Iteration 17 ===
! x86 : multi-threading : sync, thread-safe gc, snop
! x86-64 : multi-threading : open another thread
! sm : generate advances templates from vm console
! elena vm : helloworld sample Windows x86-64, Linux x86 / x86-64 / ppc64le / aarch64
! elena sm : script samples Windows x86-64, Linux x86 / x86-64 / ppc64le / aarch64
- ! elena vm : aarch64, ppc64
! migrate all script engine tutorials : linix aarch64, linux ppc64le
- ! ppc64le : multi-threading
- ! ppc64le : gui
+ ! elena sm : linux
+ ! i386 : multi-threading
+ ! x86-64 : multi-threading
+ ! x86-64 : gui
+ ! x86-64 : script samples
* templates with parameters: template can have attribute values in the brackets after the main body
e.g : info("My class"), MyTemplateWithArg(-2). This feature could be used for the field template
* migrate: amb, anagram
- * multi-value return - #508
+ * review documentation - https://github.com/ELENA-LANG/elena-lang/wiki/ELENA-in-a-nutshell
- === Iteration 17 ===
+ === Iteration 18 ===
+ ! elena vm : aarch64, ppc64
+ ! elena vm : ppc64
+ ! ppc64le : multi-threading
------
Backlog:
@@ -93,6 +128,7 @@ Backlog:
--- x86, x86-64, i386, amd64, ppc64le, arm64 ---
--- elena tutorials ---
+ * review Producing a code in run-time
* raise an error if the constructor does not handle the argument (if the multimethod is auto generated)
* read an article about meta programming in Ruby, try to do similar
* Func / Func1 should use semi-direct call for the function invoke
@@ -100,12 +136,22 @@ Backlog:
* lazy expressions, put it in the first page as a feature
--- elena redux ---
+ * resolve variadic operation directly if possible
+ * fillir - optimization for 1,2,3,4
+ * gc fune-tuning, promote the part of YG to MG if it survive several collecting cycles
+ * debugger info : save the path relative to the src60 path?
+ * ide : brackets highlight
+ * ide : auto indent
+ * ide : highlight syntax
+ * ide : rest of menu options
+ * ide : context menu
+ * internal / auto-generated classes must not be included in run-time attributes
+ * optimization : tuple / array unboxing
* native conversion from short to int / byte to int
* extension template should contain all its arguments in the signature
* support strong extension template arrayOp : strong, weak
* support autoloaded classes : should be automatically resolved when the module is loaded
(flag elAutoLoaded)
- * support preloaded symbols : both static and dynamic
* module extension dispatcher should be preloaded
* elena : nullable
* system'collections'Map - migrating rest of methods
@@ -132,8 +178,6 @@ Backlog:
* allocate constant array directly if possible
* byrefHandler : if it is not contain the explicit return, assign self to byref retVal
* dispatch optimization : for 1,2,3 args
- * debugger : step over symbol
- * debugger : stepping in the loop (for)
* system'String.Substring<'IntNumber,'IntNumber>[3] - why the parameters are boxed?
* system'io'read[3] : uncomment code
* system'console : reader and writer should be strongly-typed : IConsoleReader, IConsoleWriter
@@ -143,7 +187,6 @@ Backlog:
* ldoc : all symbols should be in alphabetic order
* ldoc : consoleOp extension should be visible
* debugger watch: variadic argument list
- * callstack : fix the call stack list, it looks some points are not included
* call semidirect method
* external inline template should be private / internal. Currently it is not possible because
it cannot be resolved by template generation
@@ -162,7 +205,6 @@ Backlog:
* do:while : both statement are matched : do{ a } while(b) and do{ a } while{ b } which is not correct?
* ide : error messages if the debug process failed
* ide : set focus on activate / after opening a file
- * ide : output is not properly refreshed
* ide : toolbar
* ide : fix blicking on tab selecting (especially on opening a new project)
* ide : find
@@ -170,6 +212,8 @@ Backlog:
* ide : replace all
* ide : open the last opened file on the ide start
* ide : remember last open project
+ * ide : project settings
+ * ide : editor settings
* api : migrate VariadicArray, Matrix, BitArray, BitArray32, IntMatrix, RealMatrix
* elena : allow to initialize class in-place
* ide - disable close if no files are open
@@ -183,8 +227,6 @@ Backlog:
* api : provide field descriptions
- * ide : debugger - step into / over / stop / run / compile
- * ide : debugger - on debugging / debugger stopped
* ide - tab
* ide - close project
* ide - close single file project
@@ -195,19 +237,15 @@ Backlog:
* ide - fix errors
* ide - compile the project / file
- * ide debugger
-
* conversion : byte / short / int / long => real
* toPrintable should return both wide and string
- * unit tests : arithmetic operations
* uncomment hello world
* uncomment lnx_console.l code
* unit tests : boolean operations
* int to short -> negative
* short to int -> negative
- * uint : test comparision (e.g 0 < 3000000u)
* comparision operations : short / byte / long operation
* boolean operators : &&, ||, ^^ - weak implementation
@@ -221,7 +259,6 @@ Backlog:
* api60 : Indexer2D?
* native support for long to real
* native support for real to long
- * migrate realOpController : math operations
* pi & e constants
* intRefOp & realRefOp ?
* string to real : support e notation
@@ -235,7 +272,6 @@ Backlog:
* prop template : weak
* generate default constructor if there is an initializer
* do not box when stack-allocated self is returned from the stack-safe method
- * new opcode - creater
* tests : mg->yg collecting - x86, x86-64, i386, amd64, ppc64le, arm64
* unit tests : branching
* unit tests : looping
@@ -243,8 +279,6 @@ Backlog:
* review code { int n := 3; } : extra assigning
* repeate-until statements
* aarch64 : setting mask for size (createn, ...)
- * try-finally-catch
- * try-finally
* optimization : fields should be aligned to 4 / 8 and the copy operation should take this into account,
except for special type of structs - packed one
* ide : fix errors with font size / switching to error list / clear high light on click
@@ -279,7 +313,7 @@ Backlog:
* exclude embeddable return for auto field
* generate abstract ebleddable
* primitive operations : support all comparision operations (not only <, == and !=)
- * uint, ushort, int8
+ * ushort, int8
* numberic constant should be implicitly converted to byte / short / long / real
* closure should be sealed
* jumping - aligning the target to 4 / 8
@@ -314,7 +348,6 @@ Backlog:
* verifyMultimethods implements
* explicit multimethod
* call interface method
- * compiler - constructor - fill newly created object with zerros
* compiler - if the method has no call operarion, no need to set arg length
* bcwriter : openFrame - should flush only used arguments (e.g. for test[1] - only one xflush)
* dispatch opcode : optimize for 1,2,3,4 arguments
@@ -365,13 +398,10 @@ Backlog:
* for linux amd64 allocate shadow memory
* ide : editor
- * ide : project view
- * ide : compiling
* ide : save last open file / project
* ide : project settings
* ide : styling source code
* call a message / closure; debugger
- * support preloaded symbols
* redux : add output convertion for the method without the explicit return statement
* optimization : openheader / open - there should be an optimized version for n < 4 - with reserved raw stack
@@ -575,7 +605,6 @@ Backlog:
* refactoring : classROp.setField should be either internal or not available at all (because
it is not possible to enforce types)
- * multi-return
* docs
* api doc : static method descriptions;
diff --git a/elenasrc3/common/config.cpp b/elenasrc3/common/config.cpp
index c0157dbe2f..df5b602fff 100644
--- a/elenasrc3/common/config.cpp
+++ b/elenasrc3/common/config.cpp
@@ -53,8 +53,10 @@ ConfigFile::Node ConfigFile :: selectNode(Node& node, ustr_t xpath)
void ConfigFile :: appendSetting(ustr_t xpath, ustr_t value)
{
XmlNode node = _tree.insertNode(xpath);
-
- node.setContent(value);
+ if (node.isNotFound()) {
+ assert(false);
+ }
+ else node.setContent(value);
}
bool ConfigFile :: load(path_t path, FileEncoding encoding)
diff --git a/elenasrc3/common/dump.h b/elenasrc3/common/dump.h
index a564f3d6b9..e58f9dcd3a 100644
--- a/elenasrc3/common/dump.h
+++ b/elenasrc3/common/dump.h
@@ -104,7 +104,11 @@ namespace elena_lang
MemoryDump(const MemoryDump& copy);
virtual ~MemoryDump()
{
- freestr((char*)_buffer);
+ if (_buffer) {
+ freestr((char*)_buffer);
+ _buffer = nullptr;
+ }
+ else _buffer = nullptr;
}
};
diff --git a/elenasrc3/common/lists.h b/elenasrc3/common/lists.h
index a455370366..b5d4f2e17b 100644
--- a/elenasrc3/common/lists.h
+++ b/elenasrc3/common/lists.h
@@ -288,6 +288,14 @@ namespace elena_lang
bool eof() const { return _current == nullptr; }
+ bool last()
+ {
+ MemoryIteratorBase tmp = *this;
+ ++tmp;
+
+ return tmp.eof();
+ }
+
MemoryIteratorBase(MemoryDump* buffer, Item* item)
{
_buffer = buffer;
diff --git a/elenasrc3/common/paths.cpp b/elenasrc3/common/paths.cpp
index 1b879686bb..cd63c1827f 100644
--- a/elenasrc3/common/paths.cpp
+++ b/elenasrc3/common/paths.cpp
@@ -3,7 +3,7 @@
//
// This file contains ELENA Engine File class implementations.
//
-// (C)2021-2022, by Aleksey Rakov
+// (C)2021-2023, by Aleksey Rakov
//---------------------------------------------------------------------------
#include "common.h"
@@ -149,6 +149,11 @@ bool PathUtil :: removeFile(path_t path)
#endif
+bool PathUtil :: ifExist(path_t path)
+{
+ return checkDir(path, 0) == 0;
+}
+
bool PathUtil :: checkExtension(path_t path, path_t extension)
{
size_t namepos = path.findLast(PATH_SEPARATOR) + 1;
diff --git a/elenasrc3/common/paths.h b/elenasrc3/common/paths.h
index 20930678dc..d7823d650d 100644
--- a/elenasrc3/common/paths.h
+++ b/elenasrc3/common/paths.h
@@ -3,7 +3,7 @@
//
// This file contains ELENA Engine Path class declarations.
//
-// (C)2021-2022, by Aleksey Rakov
+// (C)2021-2023, by Aleksey Rakov
//---------------------------------------------------------------------------
#ifndef PATHS_H
@@ -27,6 +27,8 @@ namespace elena_lang
class PathUtil
{
public:
+ static bool ifExist(path_t path);
+
static bool compare(path_t path1, path_t path);
static bool compare(path_t s1, path_t s2, size_t length);
diff --git a/elenasrc3/common/ustring.h b/elenasrc3/common/ustring.h
index df94f0e5d3..3fc0037aab 100644
--- a/elenasrc3/common/ustring.h
+++ b/elenasrc3/common/ustring.h
@@ -361,11 +361,16 @@ namespace elena_lang
return true;
}
- static bool longToStr(unsigned long long n, T* s, int radix, size_t maxLength)
+ static bool longToStr(long long n, T* s, int radix, size_t maxLength)
{
long long rem = 0;
size_t pos = 0;
size_t start = 0;
+ if (n < 0) {
+ start++;
+ n = -n;
+ s[pos++] = '-';
+ }
do
{
@@ -646,11 +651,12 @@ namespace elena_lang
void insert(const T* s, size_t index)
{
pos_t length = getlength_pos(s);
- if (_size <= length) {
- create(length + 1);
- }
+ size_t newLength = getlength(_string) + length;
+ if (_size <= newLength)
+ create(newLength + 1);
StrUtil::insert(_string, index, length, s);
+ _string[newLength] = 0;
}
void cut(size_t index, size_t length)
@@ -674,6 +680,14 @@ namespace elena_lang
_size = 0;
_string = nullptr;
}
+ DynamicString(const T* value, size_t index, size_t length)
+ {
+ _size = 0;
+ _string = nullptr;
+
+ copy(value + index, length);
+ }
+
};
}
diff --git a/elenasrc3/elc/clicommon.h b/elenasrc3/elc/clicommon.h
index 98a74ad4f1..1b7c3365d9 100644
--- a/elenasrc3/elc/clicommon.h
+++ b/elenasrc3/elc/clicommon.h
@@ -174,14 +174,14 @@ struct BuiltinReferences
ref_t superReference;
ref_t intReference, shortReference, byteReference;
ref_t longReference, realReference;
- ref_t dwordReference;
+ ref_t uintReference;
ref_t literalReference;
ref_t wideReference;
ref_t messageReference, extMessageReference;
ref_t wrapperTemplateReference;
ref_t arrayTemplateReference;
ref_t argArrayTemplateReference;
- ref_t closureTemplateReference;
+ ref_t closureTemplateReference, tupleTemplateReference;
ref_t lazyExpressionReference;
ref_t pointerReference;
@@ -204,13 +204,13 @@ struct BuiltinReferences
{
superReference = intReference = 0;
shortReference = byteReference = 0;
- dwordReference = 0;
+ uintReference = 0;
longReference = realReference = 0;
literalReference = wideReference = 0;
messageReference = extMessageReference = 0;
wrapperTemplateReference = 0;
arrayTemplateReference = argArrayTemplateReference = 0;
- closureTemplateReference = lazyExpressionReference = 0;
+ closureTemplateReference = lazyExpressionReference = tupleTemplateReference = 0;
pointerReference = 0;
dispatch_message = constructor_message = 0;
@@ -263,6 +263,7 @@ class ModuleScopeBase : public SectionScopeBase
IdentifierString selfVar;
IdentifierString declVar;
IdentifierString superVar;
+ IdentifierString receivedVar;
pos_t stackAlingment, rawStackAlingment;
pos_t ehTableEntrySize;
@@ -383,6 +384,8 @@ enum class ExpressionAttribute : pos64_t
InitializerScope = 0x00000800000,
NestedDecl = 0x00001000000,
ConstantExpr = 0x00002000000,
+ Variadic = 0x00004000000,
+ WithVariadicArg = 0x00008000000,
Superior = 0x10000000000,
Lookahead = 0x20000000000,
NoDebugInfo = 0x40000000000,
@@ -444,6 +447,7 @@ struct FieldAttributes
bool isConstant;
bool isStatic;
bool isEmbeddable;
+ bool isReadonly;
bool inlineArray;
bool fieldArray;
};
@@ -460,8 +464,8 @@ class CompilerBase
virtual void injectVirtualReturningMethod(ModuleScopeBase* scope, SyntaxNode classNode,
mssg_t message, ustr_t retVar, ref_t classRef) = 0;
- virtual ref_t resolvePrimitiveType(ModuleScopeBase& scope, TypeInfo typeInfo)
- = 0;
+ virtual ref_t resolvePrimitiveType(ModuleScopeBase& moduleScope, ustr_t ns,
+ TypeInfo typeInfo, bool declarationMode = false) = 0;
virtual ref_t generateExtensionTemplate(ModuleScopeBase& scope, ref_t templateRef, size_t argumentLen,
ref_t* arguments, ustr_t ns, ExtensionMap* outerExtensionList) = 0;
diff --git a/elenasrc3/elc/cliconst.h b/elenasrc3/elc/cliconst.h
index 51c63c0308..83ea349ed7 100644
--- a/elenasrc3/elc/cliconst.h
+++ b/elenasrc3/elc/cliconst.h
@@ -13,7 +13,19 @@
namespace elena_lang
{
- #define ELC_REVISION_NUMBER 0x0167
+ #define ELC_REVISION_NUMBER 0x0186
+
+#if defined _M_IX86 || _M_X64
+
+ #define ERROR_RET_CODE -2
+ #define WARNING_RET_CODE -1
+
+#elif defined __i386__ || __x86_64__ || __PPC64__ || __aarch64__
+
+ #define ERROR_RET_CODE 2
+ #define WARNING_RET_CODE 1
+
+#endif
// --- Information messages ---
constexpr auto ELC_GREETING = "ELENA Command-line compiler %d.%d.%d (C)2005-2023 by Aleksey Rakov\n";
diff --git a/elenasrc3/elc/codeimage.cpp b/elenasrc3/elc/codeimage.cpp
index f29e3326eb..23beb249af 100644
--- a/elenasrc3/elc/codeimage.cpp
+++ b/elenasrc3/elc/codeimage.cpp
@@ -2,13 +2,16 @@
// E L E N A P r o j e c t: ELENA Compiler
//
// This file contains ELENA Image class implementations
-// (C)2021-2022, by Aleksey Rakov
+// (C)2021-2023, by Aleksey Rakov
//---------------------------------------------------------------------------
#include "elena.h"
// --------------------------------------------------------------------------
#include "codeimage.h"
+
+#include "bytecode.h"
#include "jitlinker.h"
+#include "module.h"
using namespace elena_lang;
@@ -52,27 +55,46 @@ TargetImage :: TargetImage(PlatformType systemTarget, ForwardResolverBase* resol
_tlsVariable = linker.resolveTLSSection(compiler);
}
+ // resolve the debug entry
+ _debugEntryPoint = INVALID_ADDR;
+
if (_systemTarget == PlatformType::VMClient) {
MemoryDump tape;
createVMTape(&tape, loader->Namespace(), loader->OutputPath(), resolver);
linker.resolveTape(VM_TAPE, &tape);
+
+ // resolve the system entry
+ ustr_t entryName = resolver->resolveForward(SYSTEM_FORWARD);
+ _entryPoint = entryName.empty() ? INVALID_POS : (pos_t)linker.resolve(entryName, mskSymbolRef, true);
+ if (_entryPoint == INVALID_POS)
+ throw JITUnresolvedException(ReferenceInfo(SYSTEM_FORWARD));
}
+ else {
+ // resolving program entry
+ _debugEntryPoint = (pos_t)linker.resolve(PROGRAM_ENTRY, mskSymbolRef, true);
- // resolve the program entry
- ustr_t entryName = resolver->resolveForward(SYSTEM_FORWARD);
- _entryPoint = entryName.empty() ? INVALID_POS : (pos_t)linker.resolve(entryName, mskSymbolRef, true);
- if (_entryPoint == INVALID_POS)
- throw JITUnresolvedException(ReferenceInfo(SYSTEM_FORWARD));
+ // creating start up symbol
+ Module* dummyModule = new Module();
+ linker.loadPreloaded(PRELOADED_FORWARD);
+ addLazyReference({ mskAutoSymbolRef, INVALID_POS,
+ dummyModule, dummyModule->mapReference(resolver->resolveForward(START_FORWARD)), 0});
- // resolvethe debug entry
- _debugEntryPoint = INVALID_ADDR;
+ MemoryDump tapeSymbol;
+ generateAutoSymbol(dummyModule, tapeSymbol);
+ addr_t vaddress = linker.resolveTemporalByteCode(tapeSymbol, dummyModule);
+ mapReference(STARTUP_ENTRY, vaddress, mskSymbolRef);
- if (_systemTarget != PlatformType::VMClient) {
- _debugEntryPoint = (pos_t)linker.resolve(PROGRAM_ENTRY, mskSymbolRef, true);
+ // resolve the system entry
+ ustr_t entryName = resolver->resolveForward(SYSTEM_FORWARD);
+ _entryPoint = entryName.empty() ? INVALID_POS : (pos_t)linker.resolve(entryName, mskSymbolRef, true);
+ if (_entryPoint == INVALID_POS)
+ throw JITUnresolvedException(ReferenceInfo(SYSTEM_FORWARD));
ustr_t superClass = resolver->resolveForward(SUPER_FORWARD);
linker.complete(compiler, superClass);
+
+ freeobj(dummyModule);
}
if (_debugEntryPoint == INVALID_ADDR) {
@@ -129,9 +151,10 @@ void TargetImage :: createVMTape(MemoryBase* tape, ustr_t ns, path_t nsPath, For
IdentifierString nsPathStr(nsPath);
addVMTapeEntry(tapeWriter, VM_PACKAGE_CMD, ns, *nsPathStr);
+ addVMTapeEntry(tapeWriter, VM_PRELOADED_CMD, PRELOADED_FORWARD);
addVMTapeEntry(tapeWriter, VM_INIT_CMD);
- addVMTapeEntry(tapeWriter, VM_CALLSYMBOL_CMD, STARTUP_ENTRY);
+ addVMTapeEntry(tapeWriter, VM_CALLSYMBOL_CMD, resolver->resolveForward(START_FORWARD));
addVMTapeEntry(tapeWriter, VM_ENDOFTAPE_CMD);
}
@@ -168,3 +191,17 @@ void TargetImage :: prepareImage(ustr_t ns)
MemoryWriter debugWriter(getTargetDebugSection());
debugWriter.writeString(ns);
}
+
+void TargetImage :: generateAutoSymbol(ModuleBase* module, MemoryDump& tapeSymbol)
+{
+ // fill the list of virtual references
+ ModuleInfoList symbolList({});
+ forEachLazyReference(&symbolList, [](ModuleInfoList* symbolList, LazyReferenceInfo info)
+ {
+ if (info.mask == mskAutoSymbolRef) {
+ symbolList->add({ info.module, info.reference });
+ }
+ });
+
+ ByteCodeUtil::generateAutoSymbol(symbolList, module, tapeSymbol);
+}
diff --git a/elenasrc3/elc/codeimage.h b/elenasrc3/elc/codeimage.h
index 99a27a8c4e..aa9dcf1106 100644
--- a/elenasrc3/elc/codeimage.h
+++ b/elenasrc3/elc/codeimage.h
@@ -64,6 +64,8 @@ namespace elena_lang
return _debugEntryPoint & ~mskAnyRef;
}
+ void generateAutoSymbol(ModuleBase* module, MemoryDump& tapeSymbol);
+
TargetImage(PlatformType systemTarget, ForwardResolverBase* resolver, LibraryLoaderBase* loader,
JITCompilerBase* (*jitCompilerFactory)(LibraryLoaderBase*, PlatformType),
TargetImageInfo imageInfo, AddressMapperBase* addressMapper);
diff --git a/elenasrc3/elc/compiler.cpp b/elenasrc3/elc/compiler.cpp
index e8d28bcfde..4af429b247 100644
--- a/elenasrc3/elc/compiler.cpp
+++ b/elenasrc3/elc/compiler.cpp
@@ -58,7 +58,7 @@ inline bool isSelfCall(ObjectInfo target)
case ObjectKind::SelfLocal:
case ObjectKind::SelfBoxableLocal:
//case okOuterSelf:
- //case okClassSelf:
+ case ObjectKind::ClassSelf:
//case okInternalSelf:
return true;
default:
@@ -116,6 +116,41 @@ void declareTemplateParameters(ModuleBase* module, TemplateTypeList& typeList,
dummyWriter.closeNode();
}
+inline ref_t mapIntConstant(Compiler::Scope& scope, int integer)
+{
+ String s;
+
+ // convert back to string as a decimal integer
+ s.appendInt(integer, 16);
+
+ return scope.moduleScope->module->mapConstant(s.str());
+}
+
+inline bool isConstant(ObjectKind kind)
+{
+ switch (kind) {
+ case ObjectKind::IntLiteral:
+ case ObjectKind::Float64Literal:
+ case ObjectKind::LongLiteral:
+ case ObjectKind::StringLiteral:
+ case ObjectKind::WideStringLiteral:
+ case ObjectKind::Singleton:
+ return true;
+ default:
+ return false;
+ }
+}
+
+inline bool areConstants(ArgumentsInfo& args)
+{
+ for (size_t i = 0; i < args.count(); i++) {
+ if (!isConstant(args[i].kind))
+ return false;
+ }
+
+ return true;
+}
+
// --- Interpreter ---
Interpreter :: Interpreter(ModuleScopeBase* scope, CompilerLogic* logic)
@@ -134,13 +169,13 @@ ObjectInfo Interpreter :: mapWideStringConstant(ustr_t s)
return ObjectInfo(ObjectKind::WideStringLiteral, { V_WIDESTRING }, _scope->module->mapConstant(s));
}
-void Interpreter :: addTypeListItem(ref_t dictionaryRef, ref_t symbolRef)
+void Interpreter :: addTypeListItem(ref_t dictionaryRef, ref_t symbolRef, ref_t mask)
{
MemoryBase* dictionary = _scope->module->mapSection(dictionaryRef | mskTypeListRef, true);
if (!dictionary)
throw InternalError(errFatalError);
- _logic->writeArrayEntry(dictionary, symbolRef | mskSymbolRef);
+ _logic->writeArrayEntry(dictionary, symbolRef | mask);
}
void Interpreter :: addConstArrayItem(ref_t dictionaryRef, ref_t item, ref_t mask)
@@ -244,6 +279,9 @@ ObjectInfo Interpreter :: createConstCollection(ref_t arrayRef, ref_t typeRef, A
case ObjectKind::StringLiteral:
addConstArrayItem(arrayRef, arg.reference, mskLiteralRef);
break;
+ case ObjectKind::Singleton:
+ addConstArrayItem(arrayRef, arg.reference, mskVMTRef);
+ break;
default:
assert(false);
break;
@@ -261,7 +299,9 @@ bool Interpreter :: evalObjArrayOp(ref_t operator_id, ArgumentsInfo& args)
ObjectInfo roperand = args[1];
if (loperand.kind == ObjectKind::TypeList && roperand.kind == ObjectKind::Symbol) {
if (operator_id == ADD_ASSIGN_OPERATOR_ID) {
- addTypeListItem(loperand.reference, roperand.reference | mskSymbolRef);
+ ref_t mask = mskSymbolRef;
+
+ addTypeListItem(loperand.reference, roperand.reference, mask);
return true;
}
@@ -284,6 +324,7 @@ bool Interpreter :: evalDeclOp(ref_t operator_id, ArgumentsInfo& args, ObjectInf
return true;
}
case ObjectKind::Class:
+ case ObjectKind::ClassSelf:
retVal = { ObjectKind::SelfName };
return true;
case ObjectKind::Method:
@@ -633,6 +674,11 @@ ObjectInfo Compiler::MetaScope :: mapDecl()
return { ObjectKind::Class, { V_DECLARATION }, classScope->reference };
}
+ SymbolScope* symbolScope = Scope::getScope(*this, ScopeLevel::Symbol);
+ if (symbolScope != nullptr) {
+ return { ObjectKind::Symbol, { V_DECLARATION }, symbolScope->reference };
+ }
+
return {};
}
@@ -712,11 +758,11 @@ Compiler::ClassScope :: ClassScope(Scope* ns, ref_t reference, Visibility visibi
inline ObjectInfo mapClassInfoField(ClassInfo& info, ustr_t identifier, ExpressionAttribute attr, bool ignoreFields)
{
- bool readOnly = test(info.header.flags, elReadOnlyRole)
- && !EAttrs::test(attr, EAttr::InitializerScope);
-
auto fieldInfo = info.fields.get(identifier);
if (!ignoreFields && fieldInfo.offset >= 0) {
+ bool readOnly = (test(info.header.flags, elReadOnlyRole) || fieldInfo.readOnly)
+ && !EAttrs::test(attr, EAttr::InitializerScope);
+
if (test(info.header.flags, elStructureRole)) {
return { readOnly ? ObjectKind::ReadOnlyFieldAddress : ObjectKind::FieldAddress,
fieldInfo.typeInfo, fieldInfo.offset };
@@ -725,6 +771,9 @@ inline ObjectInfo mapClassInfoField(ClassInfo& info, ustr_t identifier, Expressi
fieldInfo.typeInfo, fieldInfo.offset };
}
else if (!ignoreFields && fieldInfo.offset == -2) {
+ bool readOnly = (test(info.header.flags, elReadOnlyRole) || fieldInfo.readOnly)
+ && !EAttrs::test(attr, EAttr::InitializerScope);
+
return { readOnly ? ObjectKind::ReadOnlySelfLocal : ObjectKind::SelfLocal, fieldInfo.typeInfo, 1u, TargetMode::ArrayContent };
}
else {
@@ -861,7 +910,11 @@ ObjectInfo Compiler::MethodScope :: mapParameter(ustr_t identifier, ExpressionAt
else return { ObjectKind::ParamAddress, local.typeInfo, prefix - local.offset };
}
else if (local.typeInfo.typeRef == V_ARGARRAY) {
- return { ObjectKind::VArgParam, local.typeInfo, prefix - local.offset };
+ TargetMode mode = TargetMode::None;
+ if (EAttrs::test(attr, EAttr::Variadic))
+ mode = TargetMode::UnboxingVarArgument;
+
+ return { ObjectKind::VArgParam, local.typeInfo, prefix - local.offset, mode };
}
else {
if (byRef) {
@@ -895,6 +948,9 @@ ObjectInfo Compiler::MethodScope :: mapIdentifier(ustr_t identifier, bool refere
}
else return mapSuper();
}
+ else if (moduleScope->receivedVar.compare(identifier) && messageLocalAddress != 0) {
+ return { ObjectKind::LocalAddress, { V_MESSAGE }, messageLocalAddress };
+ }
}
if (constructorMode)
@@ -1040,7 +1096,7 @@ ObjectInfo Compiler::ExprScope :: mapMember(ustr_t identifier)
ClassScope* classScope = Scope::getScope(*this, ScopeLevel::Class);
if (classScope) {
//if (methodScope)
- return classScope->mapField(identifier, EAttr::None);
+ return classScope->mapField(identifier, (methodScope != nullptr && methodScope->constructorMode) ? EAttr::InitializerScope : EAttr::None);
}
return Scope::mapMember(identifier);
@@ -1349,7 +1405,8 @@ ref_t Compiler :: mapNewTerminal(Scope& scope, ustr_t prefix, SyntaxNode nameNod
}
mssg_t Compiler :: mapMethodName(MethodScope& scope, pos_t paramCount, ustr_t actionName, ref_t actionRef,
- ref_t flags, ref_t* signature, size_t signatureLen)
+ ref_t flags, ref_t* signature, size_t signatureLen,
+ bool withoutWeakMessages, bool noSignature)
{
if ((flags & PREFIX_MESSAGE_MASK) == VARIADIC_MESSAGE) {
paramCount = 1;
@@ -1358,6 +1415,10 @@ mssg_t Compiler :: mapMethodName(MethodScope& scope, pos_t paramCount, ustr_t ac
paramCount++;
}
+ // NOTE : a message target should be included as well for a normal message
+ pos_t argCount = test(flags, FUNCTION_MESSAGE) ? 0 : 1;
+ argCount += paramCount;
+
if (actionRef != 0) {
// HOTFIX : if the action was already resolved - do nothing
}
@@ -1367,13 +1428,17 @@ mssg_t Compiler :: mapMethodName(MethodScope& scope, pos_t paramCount, ustr_t ac
signatureRef = scope.moduleScope->module->mapSignature(signature, signatureLen, false);
actionRef = scope.moduleScope->module->mapAction(actionName, signatureRef, false);
+
+ if (withoutWeakMessages && noSignature && test(scope.getClassFlags(false), elClosed)) {
+ // HOTFIX : for the nested closed class - special handling is requiered
+ ClassScope* classScope = Scope::getScope(scope, Scope::ScopeLevel::Class);
+ if (!classScope->info.methods.exist(encodeMessage(actionRef, argCount, flags))) {
+ actionRef = scope.moduleScope->module->mapAction(actionName, 0, false);
+ }
+ }
}
else return 0;
- // NOTE : a message target should be included as well for a normal message
- pos_t argCount = test(flags, FUNCTION_MESSAGE) ? 0 : 1;
- argCount += paramCount;
-
return encodeMessage(actionRef, argCount, flags);
}
@@ -1547,7 +1612,7 @@ void Compiler :: declareDictionary(Scope& scope, SyntaxNode node, Visibility vis
scope.moduleScope->module->mapSection(reference | mask, false);
}
-Compiler::InheritResult Compiler :: inheritClass(ClassScope& scope, ref_t parentRef)
+Compiler::InheritResult Compiler :: inheritClass(ClassScope& scope, ref_t parentRef, bool ignoreSealed)
{
ref_t flagCopy = scope.info.header.flags;
ref_t classClassCopy = scope.info.header.classRef;
@@ -1587,7 +1652,7 @@ Compiler::InheritResult Compiler :: inheritClass(ClassScope& scope, ref_t parent
}
}
- if (test(scope.info.header.flags, elFinal)) {
+ if (!ignoreSealed && test(scope.info.header.flags, elFinal)) {
// COMPILER MAGIC : if it is a unsealed nested class inheriting its owner
if (!test(scope.info.header.flags, elSealed) && test(flagCopy, elNestedClass)) {
ClassScope* owner = Scope::getScope(scope, Scope::ScopeLevel::OwnerClass);
@@ -1646,6 +1711,7 @@ ref_t Compiler :: generateConstant(Scope& scope, ObjectInfo& retVal, ref_t const
case ObjectKind::StringLiteral:
case ObjectKind::WideStringLiteral:
case ObjectKind::IntLiteral:
+ case ObjectKind::Float64Literal:
break;
default:
return 0;
@@ -1692,11 +1758,24 @@ ref_t Compiler :: generateConstant(Scope& scope, ObjectInfo& retVal, ref_t const
retVal.typeInfo = { scope.moduleScope->buildins.intReference };
break;
}
+ case ObjectKind::Float64Literal:
+ {
+ ustr_t valueStr = module->resolveConstant(retVal.reference);
+ double value = StrConvertor::toDouble(valueStr);
+
+ dataWriter.write(&value, sizeof(double));
+
+ retVal.typeInfo = { scope.moduleScope->buildins.realReference };
+ break;
+ }
default:
break;
}
ref_t typeRef = retrieveStrongType(scope, retVal);
+ if (!typeRef)
+ return 0;
+
dataWriter.Memory()->addReference(typeRef | mskVMTRef, (pos_t)-4);
// save constant meta info
@@ -2012,7 +2091,10 @@ void Compiler :: injectVirtualMethods(SyntaxNode classNode, SyntaxKey methodType
injectVirtualMultimethod(classNode, methodType, scope, info, methodInfo.value1);
break;
case VirtualType::EmbeddableWrapper:
- injectVirtualEmbeddableWrapper(classNode, methodType, scope, targetRef, info, methodInfo.value1);
+ injectVirtualEmbeddableWrapper(classNode, methodType, scope, targetRef, info, methodInfo.value1, false);
+ break;
+ case VirtualType::AbstractEmbeddableWrapper:
+ injectVirtualEmbeddableWrapper(classNode, methodType, scope, targetRef, info, methodInfo.value1, true);
break;
default:
break;
@@ -2094,15 +2176,20 @@ void Compiler :: generateMethodDeclarations(ClassScope& scope, SyntaxNode node,
}
if (methodKey != SyntaxKey::Constructor && !test(hints, (ref_t)MethodHint::Constant)) {
- // HOTFIX : do not generate byref handler for methods returning constant value
- mssg_t byRefMethod = withRetOverload ? 0 : defineByRefMethod(scope, current);
- if (byRefMethod) {
- current.appendChild(SyntaxKey::ByRefRetMethod, byRefMethod);
-
- // HOTFIX : do not need to generate byref stub for the private method, it will be added later in the code
- if (!test(current.arg.reference, STATIC_MESSAGE) && retrieveMethod(implicitMultimethods, byRefMethod) == 0) {
- implicitMultimethods.add({ byRefMethod, VirtualType::EmbeddableWrapper });
- thirdPassRequired = true;
+ // HOTFIX : do not generate byref handler for methods returning constant value & variadic method
+ if ((current.arg.reference & PREFIX_MESSAGE_MASK) != VARIADIC_MESSAGE) {
+ mssg_t byRefMethod = withRetOverload ? 0 : defineByRefMethod(scope, current);
+ if (byRefMethod) {
+ current.appendChild(SyntaxKey::ByRefRetMethod, byRefMethod);
+
+ // HOTFIX : do not need to generate byref stub for the private method, it will be added later in the code
+ if (!test(current.arg.reference, STATIC_MESSAGE) && retrieveMethod(implicitMultimethods, byRefMethod) == 0) {
+ if (SyntaxTree::ifChildExists(current, SyntaxKey::Attribute, V_ABSTRACT)) {
+ implicitMultimethods.add({ byRefMethod, VirtualType::AbstractEmbeddableWrapper });
+ }
+ else implicitMultimethods.add({ byRefMethod, VirtualType::EmbeddableWrapper });
+ thirdPassRequired = true;
+ }
}
}
}
@@ -2187,6 +2274,7 @@ void Compiler :: generateClassField(ClassScope& scope, SyntaxNode node,
TypeInfo typeInfo = attrs.typeInfo;
int sizeHint = attrs.size;
bool embeddable = attrs.isEmbeddable;
+ bool readOnly = attrs.isReadonly;
ref_t flags = scope.info.header.flags;
if (sizeHint == -1) {
@@ -2194,7 +2282,9 @@ void Compiler :: generateClassField(ClassScope& scope, SyntaxNode node,
scope.info.header.flags |= elDynamicRole;
}
else if (!test(scope.info.header.flags, elStructureRole)) {
- typeInfo.typeRef = resolveArrayTemplate(scope, attrs.typeInfo.typeRef, true);
+ NamespaceScope* nsScope = Scope::getScope(scope, Scope::ScopeLevel::Namespace);
+
+ typeInfo.typeRef = resolveArrayTemplate(*scope.moduleScope, *nsScope->nsName, attrs.typeInfo.typeRef, true);
}
else scope.raiseError(errIllegalField, node);
@@ -2259,7 +2349,7 @@ void Compiler :: generateClassField(ClassScope& scope, SyntaxNode node,
typeInfo.typeRef = _logic->definePrimitiveArray(*scope.moduleScope, typeInfo.elementRef,
test(scope.info.header.flags, elStructureRole));
- scope.info.fields.add(name, { -2, typeInfo });
+ scope.info.fields.add(name, { -2, typeInfo, readOnly });
}
else scope.raiseError(errIllegalField, node);
}
@@ -2278,7 +2368,7 @@ void Compiler :: generateClassField(ClassScope& scope, SyntaxNode node,
offset = scope.info.size;
scope.info.size += sizeInfo.size;
- scope.info.fields.add(name, { offset, typeInfo });
+ scope.info.fields.add(name, { offset, typeInfo, readOnly });
if (typeInfo.isPrimitive())
_logic->tweakPrimitiveClassFlags(scope.info, typeInfo.typeRef);
@@ -2291,7 +2381,7 @@ void Compiler :: generateClassField(ClassScope& scope, SyntaxNode node,
scope.info.header.flags |= elNonStructureRole;
offset = scope.info.fields.count();
- scope.info.fields.add(name, { offset, typeInfo });
+ scope.info.fields.add(name, { offset, typeInfo, readOnly });
}
}
}
@@ -2306,7 +2396,7 @@ void Compiler :: generateClassFields(ClassScope& scope, SyntaxNode node, bool si
FieldAttributes attrs = {};
declareFieldAttributes(scope, current, attrs);
- if (attrs.isConstant || attrs.isStatic) {
+ if ((attrs.isConstant && !isClassClassMode) || attrs.isStatic) {
generateClassStaticField(scope, current, attrs.isConstant, attrs.typeInfo);
}
else if (!isClassClassMode) {
@@ -2323,7 +2413,8 @@ void Compiler :: generateClassDeclaration(ClassScope& scope, SyntaxNode node, re
bool closed = test(scope.info.header.flags, elClosed);
if (scope.isClassClass()) {
-
+ // generate static fields
+ generateClassFields(scope, node, false);
}
else {
// HOTFIX : flags / fields should be compiled only for the class itself
@@ -2362,7 +2453,8 @@ void Compiler :: generateClassDeclaration(ClassScope& scope, SyntaxNode node, re
void Compiler :: declareSymbol(SymbolScope& scope, SyntaxNode node)
{
- declareSymbolAttributes(scope, node);
+ declareSymbolAttributes(scope, node, false);
+ declareSymbolMetaInfo(scope, node);
scope.save();
}
@@ -2372,7 +2464,7 @@ void Compiler :: declareClassParent(ref_t parentRef, ClassScope& scope, SyntaxNo
scope.info.header.parentRef = parentRef;
InheritResult res = InheritResult::irSuccessfull;
if (scope.info.header.parentRef != 0) {
- res = inheritClass(scope, scope.info.header.parentRef/*, ignoreFields, test(scope.info.header.flags, elVirtualVMT)*/);
+ res = inheritClass(scope, scope.info.header.parentRef/*, ignoreFields*/, test(scope.info.header.flags, elVirtualVMT));
}
//if (res == irObsolete) {
@@ -2415,6 +2507,8 @@ void Compiler :: resolveClassPostfixes(ClassScope& scope, SyntaxNode node, bool
scope.raiseError(errUnknownTemplate, current);
}
else if (!parentRef) {
+ parentNode = current;
+
parentRef = resolveStrongTypeAttribute(scope, child, extensionMode, false);
}
else scope.raiseError(errInvalidSyntax, current);
@@ -2539,6 +2633,42 @@ void Compiler :: declareFieldMetaInfo(FieldScope& scope, SyntaxNode node)
}
}
+void Compiler :: declareSymbolMetaInfo(SymbolScope& scope, SyntaxNode node)
+{
+ SyntaxNode current = node.firstChild();
+ while (current != SyntaxKey::None) {
+ switch (current.key) {
+ case SyntaxKey::InlineTemplate:
+ if (!importInlineTemplate(scope, current, INLINE_PREFIX, node))
+ scope.raiseError(errUnknownTemplate, node);
+ break;
+ case SyntaxKey::MetaExpression:
+ {
+ MetaScope metaScope(&scope, Scope::ScopeLevel::Symbol);
+
+ evalStatement(metaScope, current);
+ break;
+ }
+ case SyntaxKey::MetaDictionary:
+ declareDictionary(scope, current, Visibility::Public, Scope::ScopeLevel::Field);
+ break;
+ //case SyntaxKey::Name:
+ //case SyntaxKey::Type:
+ //case SyntaxKey::ArrayType:
+ //case SyntaxKey::TemplateType:
+ //case SyntaxKey::Attribute:
+ //case SyntaxKey::Dimension:
+ //case SyntaxKey::EOP:
+ // break;
+ default:
+ // scope.raiseError(errInvalidSyntax, node);
+ break;
+ }
+
+ current = current.nextNode();
+ }
+}
+
void Compiler :: declareMethodMetaInfo(MethodScope& scope, SyntaxNode node)
{
bool withoutBody = false;
@@ -2583,7 +2713,7 @@ void Compiler :: declareMethodMetaInfo(MethodScope& scope, SyntaxNode node)
}
void Compiler :: declareParameter(MethodScope& scope, SyntaxNode current, bool withoutWeakMessages,
- bool declarationMode, bool& variadicMode, bool& weakSignature,
+ bool declarationMode, bool& variadicMode, bool& weakSignature, bool& noSignature,
pos_t& paramCount, ref_t* signature, size_t& signatureLen)
{
int index = 1 + scope.parameters.count();
@@ -2592,11 +2722,16 @@ void Compiler :: declareParameter(MethodScope& scope, SyntaxNode current, bool w
TypeInfo paramTypeInfo = {};
declareArgumentAttributes(scope, current, paramTypeInfo, declarationMode);
- if (withoutWeakMessages && !paramTypeInfo.typeRef)
+ // NOTE : an extension method must be strong-resolved
+ if (withoutWeakMessages && !paramTypeInfo.typeRef) {
paramTypeInfo.typeRef = scope.moduleScope->buildins.superReference;
+ }
+ else noSignature = false;
- if (paramTypeInfo.typeRef)
- weakSignature = false;
+ if (!paramTypeInfo.typeRef) {
+ paramTypeInfo.typeRef = scope.moduleScope->buildins.superReference;
+ }
+ else weakSignature = false;
ustr_t terminal = current.findChild(SyntaxKey::Name).firstChild(SyntaxKey::TerminalMask).identifier();
if (scope.parameters.exist(terminal))
@@ -2666,13 +2801,13 @@ void Compiler :: declareVMTMessage(MethodScope& scope, SyntaxNode node, bool wit
flags |= FUNCTION_MESSAGE;
}
- //bool noSignature = true; // NOTE : is similar to weakSignature except if withoutWeakMessages=true
+ bool noSignature = true; // NOTE : is similar to weakSignature except if withoutWeakMessages=true
// if method has an argument list
SyntaxNode current = node.findChild(SyntaxKey::Parameter);
while (current != SyntaxKey::None) {
if (current == SyntaxKey::Parameter) {
declareParameter(scope, current, withoutWeakMessages,
- declarationMode, variadicMode, weakSignature,
+ declarationMode, variadicMode, weakSignature, noSignature,
paramCount, signature, signatureLen);
}
else break;
@@ -2778,7 +2913,7 @@ void Compiler :: declareVMTMessage(MethodScope& scope, SyntaxNode node, bool wit
else {
// check if protected method already declared
mssg_t publicMessage = mapMethodName(scope, paramCount, *actionStr, actionRef, flags,
- signature, signatureLen);
+ signature, signatureLen, withoutWeakMessages, noSignature);
mssg_t declaredMssg = scope.getAttribute(publicMessage, ClassAttribute::ProtectedAlias);
if (!declaredMssg) {
@@ -2799,7 +2934,7 @@ void Compiler :: declareVMTMessage(MethodScope& scope, SyntaxNode node, bool wit
if (!scope.message) {
scope.message = mapMethodName(scope, paramCount, *actionStr, actionRef, flags,
- signature, signatureLen);
+ signature, signatureLen, withoutWeakMessages, noSignature);
if (unnamedMessage || !scope.message)
scope.raiseError(errIllegalMethod, node);
}
@@ -2821,13 +2956,14 @@ ref_t Compiler :: declareClosureParameters(MethodScope& methodScope, SyntaxNode
ref_t signRef = 0;
bool weakSingature = true;
+ bool noSignature = true;
bool variadicMode = false;
ref_t flags = FUNCTION_MESSAGE;
ref_t signatures[ARG_COUNT];
size_t signatureLen = 0;
while (argNode == SyntaxKey::Parameter) {
declareParameter(methodScope, argNode, false, false,
- variadicMode, weakSingature,
+ variadicMode, weakSingature, noSignature,
paramCount, signatures, signatureLen);
if (variadicMode)
@@ -2837,7 +2973,7 @@ ref_t Compiler :: declareClosureParameters(MethodScope& methodScope, SyntaxNode
}
messageStr.copy(INVOKE_MESSAGE);
- if (!weakSingature) {
+ if (!weakSingature && !noSignature) {
signRef = methodScope.module->mapSignature(signatures, signatureLen, false);
}
@@ -3188,7 +3324,7 @@ void Compiler :: declareMemberIdentifiers(NamespaceScope& ns, SyntaxNode node)
case SyntaxKey::Symbol:
{
SymbolScope symbolScope(&ns, 0, ns.defaultVisibility);
- declareSymbolAttributes(symbolScope, current);
+ declareSymbolAttributes(symbolScope, current, true);
SyntaxNode name = current.findChild(SyntaxKey::Name);
@@ -3298,7 +3434,7 @@ void Compiler :: declareNamespace(NamespaceScope& ns, SyntaxNode node, bool igno
current.setKey(SyntaxKey::Idle);
}
else {
- ns.raiseWarning(WARNING_LEVEL_1, wrnUnknownModule, current);
+ ns.raiseWarning(WARNING_LEVEL_1, wrnUnknownModule, current.findChild(SyntaxKey::Name));
current.setKey(SyntaxKey::Idle); // remove the node, to prevent duplicate warnings
}
}
@@ -3422,7 +3558,8 @@ ObjectInfo Compiler :: evalCollection(Interpreter& interpreter, Scope& scope, Sy
ref_t collectionTypeRef = retrieveStrongType(scope, typeInfo);
ClassInfo collectionInfo;
- _logic->defineClassInfo(*scope.moduleScope, collectionInfo, collectionTypeRef, false, true);
+ if(!_logic->defineClassInfo(*scope.moduleScope, collectionInfo, collectionTypeRef, false, true))
+ scope.raiseError(errInvalidOperation, node);
if (!test(collectionInfo.header.flags, elDynamicRole))
scope.raiseError(errInvalidOperation, node);
@@ -3434,13 +3571,12 @@ ObjectInfo Compiler :: evalCollection(Interpreter& interpreter, Scope& scope, Sy
auto fieldInfo = *(collectionInfo.fields.start());
ref_t elementTypeRef = retrieveStrongType(scope, { ObjectKind::Object, { fieldInfo.typeInfo.elementRef }, 0 });
- auto sizeInfo = _logic->defineStructSize(collectionInfo);
ArgumentsInfo arguments;
EAttr paramMode = EAttr::Parameter;
while (current != SyntaxKey::None) {
if (current == SyntaxKey::Expression) {
auto argInfo = evalExpression(interpreter, scope, current);
- if (!_logic->isCompatible(*scope.moduleScope, { elementTypeRef }, argInfo.typeInfo, true))
+ if (!isConstant(argInfo.kind) || !_logic->isCompatible(*scope.moduleScope, { elementTypeRef }, argInfo.typeInfo, true))
return {};
arguments.add(argInfo);
@@ -3542,11 +3678,16 @@ inline void createObject(BuildTreeWriter& writer, ClassInfo& info, ref_t referen
if (test(info.header.flags, elStructureRole)) {
writer.newNode(BuildKey::CreatingStruct, info.size);
}
- else writer.newNode(BuildKey::CreatingClass, info.fields.count());
+ else {
+ writer.newNode(BuildKey::CreatingClass, info.fields.count());
+ }
writer.appendNode(BuildKey::Type, reference);
-
writer.closeNode();
+
+ if (!test(info.header.flags, elStructureRole) && info.fields.count() != 0) {
+ writer.appendNode(BuildKey::FillOp, info.fields.count());
+ }
}
inline void copyObjectToAcc(BuildTreeWriter& writer, ClassInfo& info, int offset)
@@ -3800,6 +3941,45 @@ ObjectInfo Compiler :: boxArgumentLocally(BuildTreeWriter& writer, ExprScope& sc
}
}
+ObjectInfo Compiler :: boxVariadicArgument(BuildTreeWriter& writer, ExprScope& scope, ObjectInfo info)
+{
+ NamespaceScope* nsScope = Scope::getScope(scope, Scope::ScopeLevel::Namespace);
+
+ ref_t elementRef = info.typeInfo.elementRef;
+ if (!elementRef)
+ elementRef = scope.moduleScope->buildins.superReference;
+
+ ref_t typeRef = resolveArgArrayTemplate(*scope.moduleScope, *nsScope->nsName, elementRef, false);
+
+ ObjectInfo destLocal = declareTempLocal(scope, typeRef);
+ ObjectInfo lenLocal = declareTempLocal(scope, scope.moduleScope->buildins.intReference, false);
+
+ // get length
+ writeObjectInfo(writer, scope, info);
+ writer.appendNode(BuildKey::SavingInStack);
+ writer.newNode(BuildKey::VArgSOp, LEN_OPERATOR_ID);
+ writer.appendNode(BuildKey::Index, lenLocal.argument);
+ writer.closeNode();
+
+ // create a dynamic array
+ writeObjectInfo(writer, scope, lenLocal);
+ writer.appendNode(BuildKey::SavingInStack);
+ writer.appendNode(BuildKey::NewArrayOp, typeRef);
+ compileAssigningOp(writer, scope, destLocal, { ObjectKind::Object, { typeRef }, 0 });
+
+ // copy the content
+ // index len
+ // src:sp[0]
+ // dst:acc
+ writer.appendNode(BuildKey::LoadingIndex, lenLocal.argument);
+ writeObjectInfo(writer, scope, info);
+ writer.appendNode(BuildKey::SavingInStack);
+ writeObjectInfo(writer, scope, destLocal);
+ writer.appendNode(BuildKey::CopyingArr);
+
+ return destLocal;
+}
+
ObjectInfo Compiler :: boxArgument(BuildTreeWriter& writer, ExprScope& scope, ObjectInfo info,
bool stackSafe, bool boxInPlace, bool allowingRefArg, ref_t targetRef)
{
@@ -3837,7 +4017,9 @@ ObjectInfo Compiler :: boxArgument(BuildTreeWriter& writer, ExprScope& scope, Ob
if (!boxInPlace)
scope.tempLocals.add(key, retVal);
}
-
+ }
+ else if (info.kind == ObjectKind::VArgParam && !stackSafe) {
+ retVal = boxVariadicArgument(writer, scope, info);
}
else retVal = info;
@@ -3870,6 +4052,9 @@ void Compiler :: writeObjectInfo(BuildTreeWriter& writer, ExprScope& scope, Obje
case ObjectKind::MssgLiteral:
writer.appendNode(BuildKey::MssgLiteral, info.reference);
break;
+ case ObjectKind::MssgNameLiteral:
+ writer.appendNode(BuildKey::MssgNameLiteral, info.reference);
+ break;
case ObjectKind::ExtMssgLiteral:
writer.appendNode(BuildKey::ExtMssgLiteral, info.reference);
break;
@@ -3889,6 +4074,7 @@ void Compiler :: writeObjectInfo(BuildTreeWriter& writer, ExprScope& scope, Obje
writer.appendNode(BuildKey::SymbolCall, info.reference);
break;
case ObjectKind::Class:
+ case ObjectKind::ClassSelf:
case ObjectKind::Singleton:
case ObjectKind::ConstantRole:
writer.appendNode(BuildKey::ClassReference, info.reference);
@@ -3925,6 +4111,7 @@ void Compiler :: writeObjectInfo(BuildTreeWriter& writer, ExprScope& scope, Obje
case ObjectKind::TempLocalAddress:
writer.appendNode(BuildKey::LocalAddress, info.reference);
break;
+ case ObjectKind::ReadOnlyField:
case ObjectKind::Field:
case ObjectKind::Outer:
case ObjectKind::OuterSelf:
@@ -3974,71 +4161,81 @@ ref_t Compiler :: retrieveType(Scope& scope, ObjectInfo info)
else return info.typeInfo.typeRef;
}
-ref_t Compiler :: resolvePrimitiveType(ModuleScopeBase& scope, TypeInfo typeInfo)
+ref_t Compiler :: resolvePrimitiveType(Scope& scope, TypeInfo typeInfo, bool declarationMode)
{
- MetaScope metaScope(nullptr, Scope::ScopeLevel::Expr);
- metaScope.moduleScope = &scope;
+ NamespaceScope* nsScope = Scope::getScope(scope, Scope::ScopeLevel::Namespace);
- return resolvePrimitiveType(metaScope, typeInfo, false);
+ return resolvePrimitiveType(*scope.moduleScope, *nsScope->nsName, typeInfo, declarationMode);
}
-ref_t Compiler :: resolvePrimitiveType(Scope& scope, TypeInfo typeInfo, bool declarationMode)
+ref_t Compiler :: resolvePrimitiveType(ModuleScopeBase& moduleScope, ustr_t ns, TypeInfo typeInfo,
+ bool declarationMode)
{
switch (typeInfo.typeRef) {
case V_INT8:
- return scope.moduleScope->buildins.byteReference;
+ return moduleScope.buildins.byteReference;
case V_INT16:
- return scope.moduleScope->buildins.shortReference;
+ return moduleScope.buildins.shortReference;
case V_INT32:
- return scope.moduleScope->buildins.intReference;
+ return moduleScope.buildins.intReference;
case V_INT64:
- return scope.moduleScope->buildins.longReference;
+ return moduleScope.buildins.longReference;
case V_FLOAT64:
- return scope.moduleScope->buildins.realReference;
- case V_WORD32:
- return scope.moduleScope->buildins.dwordReference;
+ return moduleScope.buildins.realReference;
+ case V_UINT32:
+ return moduleScope.buildins.uintReference;
case V_STRING:
- return scope.moduleScope->buildins.literalReference;
+ return moduleScope.buildins.literalReference;
case V_WIDESTRING:
- return scope.moduleScope->buildins.wideReference;
+ return moduleScope.buildins.wideReference;
case V_MESSAGE:
- return scope.moduleScope->buildins.messageReference;
+ return moduleScope.buildins.messageReference;
case V_EXTMESSAGE64:
case V_EXTMESSAGE128:
- return scope.moduleScope->buildins.extMessageReference;
+ return moduleScope.buildins.extMessageReference;
case V_FLAG:
- return scope.moduleScope->branchingInfo.typeRef;
+ return moduleScope.branchingInfo.typeRef;
case V_WRAPPER:
- return resolveWrapperTemplate(scope, typeInfo.elementRef, declarationMode);
+ return resolveWrapperTemplate(moduleScope, ns, typeInfo.elementRef, declarationMode);
case V_INT8ARRAY:
case V_INT16ARRAY:
case V_INT32ARRAY:
case V_BINARYARRAY:
- return resolveArrayTemplate(scope, typeInfo.elementRef, declarationMode);
+ return resolveArrayTemplate(moduleScope, ns, typeInfo.elementRef, declarationMode);
case V_NIL:
- return scope.moduleScope->buildins.superReference;
+ return moduleScope.buildins.superReference;
case V_ARGARRAY:
- return resolveArgArrayTemplate(scope, typeInfo.elementRef, declarationMode);
+ return resolveArgArrayTemplate(moduleScope, ns, typeInfo.elementRef, declarationMode);
case V_OBJARRAY:
- return resolveArrayTemplate(scope, typeInfo.elementRef, declarationMode);
+ return resolveArrayTemplate(moduleScope, ns, typeInfo.elementRef, declarationMode);
case V_PTR32:
case V_PTR64:
- return scope.moduleScope->buildins.pointerReference;
+ return moduleScope.buildins.pointerReference;
default:
- throw InternalError(errFatalError);
+ return 0;
}
}
-void Compiler :: declareSymbolAttributes(SymbolScope& scope, SyntaxNode node)
+void Compiler :: declareSymbolAttributes(SymbolScope& scope, SyntaxNode node, bool identifierDeclarationMode)
{
bool constant = false;
SyntaxNode current = node.firstChild();
while (current != SyntaxKey::None) {
- if (current == SyntaxKey::Attribute) {
- if (!_logic->validateSymbolAttribute(current.arg.value, scope.visibility, constant, scope.isStatic)) {
- current.setArgumentValue(0); // HOTFIX : to prevent duplicate warnings
- scope.raiseWarning(WARNING_LEVEL_1, wrnInvalidHint, current);
- }
+ switch (current.key) {
+ case SyntaxKey::Attribute:
+ if (!_logic->validateSymbolAttribute(current.arg.value, scope.visibility, constant, scope.isStatic)) {
+ current.setArgumentValue(0); // HOTFIX : to prevent duplicate warnings
+ scope.raiseWarning(WARNING_LEVEL_1, wrnInvalidHint, current);
+ }
+ break;
+ case SyntaxKey::Type:
+ case SyntaxKey::ArrayType:
+ case SyntaxKey::TemplateType:
+ if (!identifierDeclarationMode)
+ scope.info.typeRef = resolveStrongTypeAttribute(scope, current, true, false);
+ break;
+ default:
+ break;
}
current = current.nextNode();
@@ -4048,7 +4245,7 @@ void Compiler :: declareSymbolAttributes(SymbolScope& scope, SyntaxNode node)
scope.info.loadableInRuntime = true;
}
- if (constant) {
+ if (constant && !identifierDeclarationMode) {
scope.info.symbolType = SymbolType::Constant;
Interpreter interpreter(scope.moduleScope, _logic);
@@ -4135,6 +4332,24 @@ void Compiler :: declareArgumentAttributes(MethodScope& scope, SyntaxNode node,
scope.raiseError(errInvalidOperation, node);
}
+ref_t Compiler :: declareMultiType(Scope& scope, SyntaxNode& current, ref_t elementRef)
+{
+ bool eol = false;
+ ArgumentsInfo items;
+ items.add({ ObjectKind::Class, { elementRef }, 0 });
+
+ while (current != SyntaxKey::None) {
+ if (current == SyntaxKey::Type) {
+ items.add({ ObjectKind::Class, { resolveStrongTypeAttribute(scope, current, true, false) }, 0 });
+ }
+ else break;
+
+ current = current.nextNode();
+ }
+
+ return resolveTupleClass(scope, current, items);
+}
+
void Compiler :: declareMethodAttributes(MethodScope& scope, SyntaxNode node, bool exensionMode)
{
if (exensionMode)
@@ -4167,7 +4382,12 @@ void Compiler :: declareMethodAttributes(MethodScope& scope, SyntaxNode node, bo
case SyntaxKey::TemplateType:
case SyntaxKey::ArrayType:
// if it is a type attribute
- scope.info.outputRef = resolveStrongTypeAttribute(scope, current, true, false);
+ if (scope.info.outputRef) {
+ scope.info.outputRef = declareMultiType(scope, current, scope.info.outputRef);
+
+ continue;
+ }
+ else scope.info.outputRef = resolveStrongTypeAttribute(scope, current, true, false);
break;
case SyntaxKey::Name:
{
@@ -4419,8 +4639,15 @@ void Compiler :: declareTemplateCode(TemplateScope& scope, SyntaxNode& node)
SyntaxNode name = node.findChild(SyntaxKey::Name);
if (name.nextNode() == SyntaxKey::ComplexName) {
SyntaxNode secondName = name.nextNode();
- postfix.insert(secondName.firstChild().identifier(), 0);
- postfix.insert(":", 0);
+ size_t index = 0;
+ while (secondName == SyntaxKey::ComplexName) {
+ postfix.insert(secondName.firstChild().identifier(), index);
+ postfix.insert(":", index);
+
+ index += secondName.firstChild().identifier().length() + 1;
+
+ secondName = secondName.nextNode();
+ }
}
scope.reference = mapNewTerminal(scope, *prefix, name, *postfix, scope.visibility);
@@ -4629,6 +4856,7 @@ ref_t Compiler :: resolveTypeIdentifier(Scope& scope, ustr_t identifier, SyntaxK
switch (identInfo.kind) {
case ObjectKind::Class:
+ case ObjectKind::ClassSelf:
return identInfo.reference;
case ObjectKind::Symbol:
if (declarationMode)
@@ -4729,10 +4957,11 @@ ref_t Compiler :: resolveTypeTemplate(Scope& scope, SyntaxNode node,
}
}
-ref_t Compiler :: resolveTemplate(Scope& scope, ref_t templateRef, ref_t elementRef, bool declarationMode)
+ref_t Compiler :: resolveTemplate(ModuleScopeBase& moduleScope, ustr_t ns, ref_t templateRef,
+ ref_t elementRef, bool declarationMode)
{
if (isPrimitiveRef(elementRef))
- elementRef = resolvePrimitiveType(*scope.moduleScope, { elementRef });
+ elementRef = resolvePrimitiveType(moduleScope, ns, { elementRef });
TemplateTypeList typeList;
typeList.add(elementRef);
@@ -4740,11 +4969,9 @@ ref_t Compiler :: resolveTemplate(Scope& scope, ref_t templateRef, ref_t element
// HOTFIX : generate a temporal template to pass the type
SyntaxTree dummyTree;
List parameters({});
- declareTemplateParameters(scope.module, typeList, dummyTree, parameters);
+ declareTemplateParameters(moduleScope.module, typeList, dummyTree, parameters);
- NamespaceScope* nsScope = Scope::getScope(scope, Scope::ScopeLevel::Namespace);
-
- return _templateProcessor->generateClassTemplate(*scope.moduleScope, *nsScope->nsName,
+ return _templateProcessor->generateClassTemplate(moduleScope, ns,
templateRef, parameters, declarationMode, nullptr);
}
@@ -4830,22 +5057,22 @@ ref_t Compiler :: resolveClosure(Scope& scope, mssg_t closureMessage, ref_t outp
}
}
-ref_t Compiler :: resolveWrapperTemplate(Scope& scope, ref_t elementRef, bool declarationMode)
+ref_t Compiler :: resolveWrapperTemplate(ModuleScopeBase& moduleScope, ustr_t ns, ref_t elementRef, bool declarationMode)
{
if (!elementRef)
- elementRef = scope.moduleScope->buildins.superReference;
+ elementRef = moduleScope.buildins.superReference;
- return resolveTemplate(scope, scope.moduleScope->buildins.wrapperTemplateReference, elementRef, declarationMode);
+ return resolveTemplate(moduleScope, ns, moduleScope.buildins.wrapperTemplateReference, elementRef, declarationMode);
}
-ref_t Compiler :: resolveArrayTemplate(Scope& scope, ref_t elementRef, bool declarationMode)
+ref_t Compiler :: resolveArrayTemplate(ModuleScopeBase& moduleScope, ustr_t ns, ref_t elementRef, bool declarationMode)
{
- return resolveTemplate(scope, scope.moduleScope->buildins.arrayTemplateReference, elementRef, declarationMode);
+ return resolveTemplate(moduleScope, ns, moduleScope.buildins.arrayTemplateReference, elementRef, declarationMode);
}
-ref_t Compiler :: resolveArgArrayTemplate(Scope& scope, ref_t elementRef, bool declarationMode)
+ref_t Compiler :: resolveArgArrayTemplate(ModuleScopeBase& moduleScope, ustr_t ns, ref_t elementRef, bool declarationMode)
{
- return resolveTemplate(scope, scope.moduleScope->buildins.argArrayTemplateReference, elementRef, declarationMode);
+ return resolveTemplate(moduleScope, ns, moduleScope.buildins.argArrayTemplateReference, elementRef, declarationMode);
}
TypeInfo Compiler :: resolveTypeScope(Scope& scope, SyntaxNode node, TypeAttributes& attributes,
@@ -5021,9 +5248,11 @@ void Compiler :: readFieldAttributes(ClassScope& scope, SyntaxNode node, FieldAt
}
else if (attrs.size == -1) {
// if it is a nested array
+ NamespaceScope* nsScope = Scope::getScope(scope, Scope::ScopeLevel::Namespace);
readFieldAttributes(scope, current, attrs, declarationMode);
- attrs.typeInfo = { resolveArrayTemplate(scope, attrs.typeInfo.typeRef, declarationMode) };
+ attrs.typeInfo = { resolveArrayTemplate(*scope.moduleScope, *nsScope->nsName,
+ attrs.typeInfo.typeRef, declarationMode) };
}
else scope.raiseError(errInvalidHint, current);
break;
@@ -5066,6 +5295,17 @@ void Compiler :: declareFieldAttributes(ClassScope& scope, SyntaxNode node, Fiel
break;
}
break;
+ case V_UINTBINARY:
+ switch (attrs.size) {
+ case 4:
+ attrs.typeInfo.typeRef = V_UINT32;
+ attrs.fieldArray = false;
+ break;
+ default:
+ valid = false;
+ break;
+ }
+ break;
case V_WORDBINARY:
switch (attrs.size) {
case 4:
@@ -5098,7 +5338,6 @@ void Compiler :: declareFieldAttributes(ClassScope& scope, SyntaxNode node, Fiel
break;
}
break;
- case V_SUBJBINARY:
case V_MSSGBINARY:
switch (attrs.size) {
case 4:
@@ -5110,6 +5349,7 @@ void Compiler :: declareFieldAttributes(ClassScope& scope, SyntaxNode node, Fiel
break;
}
break;
+ case V_SUBJBINARY:
switch (attrs.size) {
case 4:
attrs.typeInfo.typeRef = V_MESSAGENAME;
@@ -5339,8 +5579,13 @@ bool Compiler :: evalInitializers(ClassScope& scope, SyntaxNode node)
else scope.raiseError(errInvalidOperation, current);
}
break;
+ case ObjectKind::StaticField:
+ if (!current.arg.reference) {
+ current.setArgumentReference(compileStaticAssigning(scope, current));
+ }
+ break;
default:
- scope.raiseError(errInvalidOperation, current);
+ evalulated = false;
break;
}
}
@@ -5368,6 +5613,11 @@ ObjectInfo Compiler :: mapClassSymbol(Scope& scope, ref_t classRef)
retVal.typeInfo = { classClassRef };
+ ClassScope* classScope = Scope::getScope(scope, Scope::ScopeLevel::Class);
+ if (classScope != nullptr && classScope->reference == retVal.typeInfo.typeRef) {
+ retVal.kind = ObjectKind::ClassSelf;
+ }
+
return retVal;
}
else return {};
@@ -5388,6 +5638,34 @@ ExternalInfo Compiler :: mapExternal(Scope& scope, SyntaxNode node)
return scope.moduleScope->mapExternal(dllAlias, functionName);
}
+ref_t Compiler :: compileStaticAssigning(ClassScope& scope, SyntaxNode node)
+{
+ ref_t actionRef = 0;
+
+ SyntaxNode rootNode = node.parentNode();
+ while (rootNode != SyntaxKey::Class) {
+ rootNode = rootNode.parentNode();
+ }
+
+ SyntaxNode staticInitializer = rootNode.firstChild(SyntaxKey::StaticInitializerMethod);
+ if (staticInitializer == SyntaxKey::None) {
+ IdentifierString sectionName(scope.module->resolveReference(scope.reference));
+ sectionName.append(INITIALIZER_SECTION);
+
+ actionRef = scope.moduleScope->mapAnonymous(*sectionName);
+
+ staticInitializer = rootNode.appendChild(SyntaxKey::StaticInitializerMethod, actionRef);
+
+ scope.addAttribute(ClassAttribute::Initializer, actionRef);
+ }
+ else actionRef = staticInitializer.arg.reference;
+
+ SyntaxTreeWriter writer(staticInitializer);
+ SyntaxTree::copyNode(writer, node, true);
+
+ return actionRef;
+}
+
ObjectInfo Compiler :: compileExternalOp(BuildTreeWriter& writer, ExprScope& scope, ref_t externalRef,
bool stdCall, ArgumentsInfo& arguments, ref_t expectedRef)
{
@@ -5542,14 +5820,19 @@ ObjectInfo Compiler :: compileWeakOperation(BuildTreeWriter& writer, ExprScope&
ObjectInfo retVal = {};
// resolving a message signature (excluding a target)
+ bool weakSignature = false;
for (pos_t i = 1; i < argLen; i++) {
- if (isPrimitiveRef(arguments[i])) {
+ if (!arguments[i]) {
+ weakSignature = true;
+ break;
+ }
+ else if (isPrimitiveRef(arguments[i])) {
arguments[i - 1] = resolvePrimitiveType(scope, { arguments[i] }, false);
}
else arguments[i - 1] = arguments[i];
}
- ref_t signRef = argLen > 1 ? scope.module->mapSignature(arguments, argLen - 1, false) : 0;
+ ref_t signRef = (!weakSignature && argLen > 1) ? scope.module->mapSignature(arguments, argLen - 1, false) : 0;
mssg_t byRefHandler = resolveByRefHandler(scope, retrieveStrongType(scope, loperand), expectedRef, message, signRef);
if (byRefHandler) {
@@ -5664,6 +5947,7 @@ ObjectInfo Compiler :: compileOperation(BuildTreeWriter& writer, ExprScope& scop
break;
case BuildKey::BoolSOp:
case BuildKey::IntCondOp:
+ case BuildKey::UIntCondOp:
case BuildKey::ByteCondOp:
case BuildKey::ShortCondOp:
case BuildKey::LongCondOp:
@@ -5853,7 +6137,7 @@ ref_t Compiler :: compileExtensionDispatcher(BuildTreeWriter& writer, NamespaceS
}
ref_t Compiler :: compileMessageArguments(BuildTreeWriter& writer, ExprScope& scope, SyntaxNode current,
- ArgumentsInfo& arguments, ref_t expectedSignRef, EAttr mode, ArgumentsInfo* updatedOuterArgs)
+ ArgumentsInfo& arguments, ref_t expectedSignRef, EAttr mode, ArgumentsInfo* updatedOuterArgs, bool& variadicArgList)
{
EAttr paramMode = EAttr::Parameter;
if (EAttrs::testAndExclude(mode, EAttr::NoPrimitives))
@@ -5874,15 +6158,27 @@ ref_t Compiler :: compileMessageArguments(BuildTreeWriter& writer, ExprScope& sc
auto argInfo = compileExpression(writer, scope, current, signatures[signatureLen],
paramMode, updatedOuterArgs);
- ref_t argRef = retrieveStrongType(scope, argInfo);
- if (signatureLen >= ARG_COUNT) {
- signatureLen++;
+ if (argInfo.mode == TargetMode::UnboxingVarArgument) {
+ if (argInfo.typeInfo.elementRef) {
+ signatures[signatureLen++] = argInfo.typeInfo.elementRef;
+ }
+ else signatures[signatureLen++] = scope.moduleScope->buildins.superReference;
+
+ if (!variadicArgList) {
+ variadicArgList = true;
+ }
+ else scope.raiseError(errInvalidOperation, current);
}
- else if (argRef) {
- signatures[signatureLen++] = argRef;
+ else {
+ ref_t argRef = retrieveStrongType(scope, argInfo);
+ if (signatureLen >= ARG_COUNT) {
+ signatureLen++;
+ }
+ else if (argRef) {
+ signatures[signatureLen++] = argRef;
+ }
+ else signatures[signatureLen++] = superReference;
}
- else signatures[signatureLen++] = superReference;
-
arguments.add(argInfo);
}
@@ -6170,6 +6466,8 @@ ObjectInfo Compiler :: unboxArguments(BuildTreeWriter& writer, ExprScope& scope,
ObjectInfo Compiler :: compileMessageOperation(BuildTreeWriter& writer, ExprScope& scope, SyntaxNode node, ObjectInfo target,
mssg_t weakMessage, ref_t implicitSignatureRef, ArgumentsInfo& arguments, ExpressionAttributes mode, ArgumentsInfo* updatedOuterArgs)
{
+ bool argUnboxinhgRequired = EAttrs::testAndExclude(mode.attrs, EAttr::WithVariadicArg);
+
ObjectInfo retVal(ObjectKind::Object);
BuildKey operation = BuildKey::CallOp;
@@ -6234,6 +6532,10 @@ ObjectInfo Compiler :: compileMessageOperation(BuildTreeWriter& writer, ExprScop
operation = BuildKey::None;
}
else operation = BuildKey::DirectCallOp;
+ // HOTFIX : do not box the variadic argument target for the direct operation
+ if (arguments[0].kind == ObjectKind::VArgParam)
+ result.stackSafe = true;
+
break;
default:
break;
@@ -6283,6 +6585,7 @@ ObjectInfo Compiler :: compileMessageOperation(BuildTreeWriter& writer, ExprScop
}
if (operation != BuildKey::None) {
+ ObjectInfo lenLocal = {};
bool targetOverridden = (target != arguments[0]);
if (targetOverridden) {
target = boxArgument(writer, scope, target, result.stackSafe, false, false);
@@ -6292,6 +6595,24 @@ ObjectInfo Compiler :: compileMessageOperation(BuildTreeWriter& writer, ExprScop
stackSafeAttr = 0;
pos_t counter = arguments.count_pos();
+ if (argUnboxinhgRequired) {
+ counter--;
+
+ ObjectInfo lenLocal = declareTempLocal(scope, scope.moduleScope->buildins.intReference, false);
+
+ // get length
+ writeObjectInfo(writer, scope, arguments[counter]);
+ writer.appendNode(BuildKey::SavingInStack);
+ writer.newNode(BuildKey::VArgSOp, LEN_OPERATOR_ID);
+ writer.appendNode(BuildKey::Index, lenLocal.argument);
+ writer.closeNode();
+
+ writer.appendNode(BuildKey::LoadingIndex, lenLocal.argument);
+ writer.newNode(BuildKey::UnboxMessage, arguments[counter].argument);
+ writer.appendNode(BuildKey::Index, counter);
+ writer.closeNode();
+ }
+
// box the arguments if required
int argMask = 1;
for (unsigned int i = 0; i < counter; i++) {
@@ -6303,7 +6624,8 @@ ObjectInfo Compiler :: compileMessageOperation(BuildTreeWriter& writer, ExprScop
argMask <<= 1;
}
- if (isOpenArg(message)) {
+ if (isOpenArg(message) && !argUnboxinhgRequired) {
+ // NOTE : in case of unboxing variadic argument, the terminator is already copied
arguments.add({ ObjectKind::Terminator });
counter++;
}
@@ -6328,6 +6650,11 @@ ObjectInfo Compiler :: compileMessageOperation(BuildTreeWriter& writer, ExprScop
writer.closeNode();
retVal = unboxArguments(writer, scope, retVal, updatedOuterArgs);
+
+ if (argUnboxinhgRequired) {
+ writer.appendNode(BuildKey::LoadingIndex, lenLocal.argument);
+ writer.appendNode(BuildKey::FreeVarStack);
+ }
}
scope.reserveArgs(arguments.count_pos());
@@ -6349,7 +6676,8 @@ void Compiler :: addBreakpoint(BuildTreeWriter& writer, SyntaxNode node, BuildKe
}
}
-ObjectInfo Compiler :: compileNewArrayOp(BuildTreeWriter& writer, ExprScope& scope, ObjectInfo source, ref_t targetRef, ArgumentsInfo& arguments)
+ObjectInfo Compiler :: compileNewArrayOp(BuildTreeWriter& writer, ExprScope& scope, SyntaxNode node,
+ ObjectInfo source, ref_t targetRef, ArgumentsInfo& arguments)
{
ref_t sourceRef = retrieveStrongType(scope, source);
@@ -6367,7 +6695,10 @@ ObjectInfo Compiler :: compileNewArrayOp(BuildTreeWriter& writer, ExprScope& sco
auto sizeInfo = _logic->defineStructSize(*scope.moduleScope, sourceRef);
if (targetRef) {
- auto conversionRoutine = _logic->retrieveConversionRoutine(this, *scope.moduleScope, targetRef, source.typeInfo);
+ NamespaceScope* nsScope = Scope::getScope(scope, Scope::ScopeLevel::Namespace);
+
+ auto conversionRoutine = _logic->retrieveConversionRoutine(this, *scope.moduleScope, *nsScope->nsName,
+ targetRef, source.typeInfo);
if (conversionRoutine.result == ConversionResult::BoxingRequired) {
source.typeInfo = { targetRef };
}
@@ -6389,10 +6720,15 @@ ObjectInfo Compiler :: compileNewArrayOp(BuildTreeWriter& writer, ExprScope& sco
writer.closeNode();
+ // fill the array
+ if (!sizeInfo.size) {
+ writer.appendNode(BuildKey::FillOp);
+ }
+
return { ObjectKind::Object, source.typeInfo, 0 };
}
- assert(false);
+ scope.raiseError(errInvalidOperation, node);
return {}; // !! temporal
}
@@ -6501,11 +6837,21 @@ ObjectInfo Compiler :: compilePropertyOperation(BuildTreeWriter& writer, ExprSco
mssg_t resolvedMessage = _logic->resolveSingleDispatch(*scope.moduleScope,
retrieveType(scope, source), messageRef);
+ bool variadicArgList = false;
ref_t expectedSignRef = 0;
if (resolvedMessage)
scope.module->resolveAction(getAction(resolvedMessage), expectedSignRef);
- ref_t implicitSignatureRef = compileMessageArguments(writer, scope, current, arguments, expectedSignRef, EAttr::NoPrimitives, &outerArgsToUpdate);
+ ref_t implicitSignatureRef = compileMessageArguments(writer, scope, current, arguments, expectedSignRef, EAttr::NoPrimitives,
+ &outerArgsToUpdate, variadicArgList);
+ EAttr opMode = EAttr::None;
+ if (variadicArgList) {
+ //// HOTFIX : set variadic flag if required
+ //messageRef |= VARIADIC_MESSAGE;
+
+ //opMode = EAttr::WithVariadicArg;
+ }
+
mssg_t byRefHandler = resolveByRefHandler(scope, retrieveStrongType(scope, source), expectedRef, messageRef, implicitSignatureRef);
if (byRefHandler) {
ObjectInfo tempRetVal = declareTempLocal(scope, expectedRef, false);
@@ -6513,12 +6859,12 @@ ObjectInfo Compiler :: compilePropertyOperation(BuildTreeWriter& writer, ExprSco
addByRefRetVal(arguments, tempRetVal);
compileMessageOperation(writer, scope, node, source, byRefHandler,
- implicitSignatureRef, arguments, EAttr::AlreadyResolved, &outerArgsToUpdate);
+ implicitSignatureRef, arguments, opMode | EAttr::AlreadyResolved, &outerArgsToUpdate);
retVal = tempRetVal;
}
else retVal = compileMessageOperation(writer, scope, node, source, messageRef,
- 0, arguments, EAttr::None, &outerArgsToUpdate);
+ 0, arguments, opMode, &outerArgsToUpdate);
return retVal;
}
@@ -6562,32 +6908,46 @@ ObjectInfo Compiler :: compileMessageOperation(BuildTreeWriter& writer, ExprScop
switch (source.mode) {
case TargetMode::External:
case TargetMode::WinApi:
- compileMessageArguments(writer, scope, current, arguments, 0, EAttr::None, nullptr);
+ {
+ bool dummy = false;
+ compileMessageArguments(writer, scope, current, arguments, 0, EAttr::None, nullptr, dummy);
+ if (dummy)
+ scope.raiseError(errInvalidOperation, current);
retVal = compileExternalOp(writer, scope, source.reference, source.mode == TargetMode::WinApi, arguments, expectedRef);
break;
+ }
case TargetMode::CreatingArray:
{
- compileMessageArguments(writer, scope, current, arguments, 0, EAttr::NoPrimitives, nullptr);
+ bool dummy = false;
+ compileMessageArguments(writer, scope, current, arguments, 0, EAttr::NoPrimitives, nullptr, dummy);
+ if (dummy)
+ scope.raiseError(errInvalidOperation, current);
- retVal = compileNewArrayOp(writer, scope, source, expectedRef, arguments);
+ retVal = compileNewArrayOp(writer, scope, node, source, expectedRef, arguments);
break;
}
case TargetMode::Creating:
{
- ref_t signRef = compileMessageArguments(writer, scope, current, arguments, 0, EAttr::NoPrimitives, nullptr);
+ bool dummy = false;
+ ref_t signRef = compileMessageArguments(writer, scope, current, arguments, 0, EAttr::NoPrimitives, nullptr, dummy);
+ if (dummy)
+ scope.raiseError(errInvalidOperation, current);
retVal = compileNewOp(writer, scope, node, mapClassSymbol(scope,
retrieveStrongType(scope, source)), signRef, arguments);
break;
}
case TargetMode::Casting:
- compileMessageArguments(writer, scope, current, arguments, 0, EAttr::NoPrimitives, nullptr);
- if (arguments.count() == 1) {
+ {
+ bool dummy = false;
+ compileMessageArguments(writer, scope, current, arguments, 0, EAttr::NoPrimitives, nullptr, dummy);
+ if (arguments.count() == 1 && !dummy) {
retVal = convertObject(writer, scope, current, arguments[0], retrieveStrongType(scope, source));
}
else scope.raiseError(errInvalidOperation, node);
break;
+ }
default:
{
// NOTE : the operation target shouldn't be a primtive type
@@ -6607,7 +6967,16 @@ ObjectInfo Compiler :: compileMessageOperation(BuildTreeWriter& writer, ExprScop
if (resolvedMessage)
scope.module->resolveAction(getAction(resolvedMessage), expectedSignRef);
- ref_t implicitSignatureRef = compileMessageArguments(writer, scope, current, arguments, expectedSignRef, EAttr::NoPrimitives, &updatedOuterArgs);
+ bool withVariadicArg = false;
+ ref_t implicitSignatureRef = compileMessageArguments(writer, scope, current, arguments, expectedSignRef, EAttr::NoPrimitives,
+ &updatedOuterArgs, withVariadicArg);
+
+ EAttr opMode = EAttr::None;
+ if (withVariadicArg) {
+ messageRef |= VARIADIC_MESSAGE;
+
+ opMode = EAttr::WithVariadicArg;
+ }
mssg_t byRefHandler = resolveByRefHandler(scope, retrieveStrongType(scope, source), expectedRef, messageRef, implicitSignatureRef);
if (byRefHandler) {
@@ -6616,12 +6985,12 @@ ObjectInfo Compiler :: compileMessageOperation(BuildTreeWriter& writer, ExprScop
addByRefRetVal(arguments, tempRetVal);
compileMessageOperation(writer, scope, node, source, byRefHandler,
- implicitSignatureRef, arguments, EAttr::AlreadyResolved, &updatedOuterArgs);
+ implicitSignatureRef, arguments, opMode | EAttr::AlreadyResolved, &updatedOuterArgs);
retVal = tempRetVal;
}
else retVal = compileMessageOperation(writer, scope, node, source, messageRef,
- implicitSignatureRef, arguments, EAttr::None, &updatedOuterArgs);
+ implicitSignatureRef, arguments, opMode, &updatedOuterArgs);
break;
}
@@ -6769,6 +7138,44 @@ bool Compiler :: compileAssigningOp(BuildTreeWriter& writer, ExprScope& scope, O
return true;
}
+ObjectInfo Compiler :: compileTupleAssigning(BuildTreeWriter& writer, ExprScope& scope, SyntaxNode node)
+{
+ ArgumentsInfo targets;
+ ArgumentsInfo arguments;
+
+ SyntaxNode current = node.firstChild();
+ targets.add(mapObject(scope, current, EAttr::None));
+ current = current.nextNode();
+ while (current == SyntaxKey::SubVariable) {
+ ObjectInfo subVar = mapObject(scope, current, EAttr::NewVariable | EAttr::IgnoreDuplicate);
+ if (subVar.kind == ObjectKind::Unknown)
+ scope.raiseError(errUnknownObject, current);
+
+ targets.add(subVar);
+
+ current = current.nextNode();
+ }
+
+ ObjectInfo exprVal = compileExpression(writer, scope, current, 0, EAttr::Parameter, nullptr);
+ for (pos_t i = 0; i < targets.count_pos(); i++) {
+ arguments.clear();
+ arguments.add(exprVal);
+ arguments.add({ ObjectKind::IntLiteral, { V_INT32 }, ::mapIntConstant(scope, i), i});
+
+ ObjectInfo targetVar = targets[i];
+
+ ref_t actionRef = scope.module->mapAction(REFER_MESSAGE, 0, false);
+ mssg_t getter = encodeMessage(actionRef, 2, 0);
+
+ ObjectInfo sourceVar = compileMessageOperation(writer, scope, node, exprVal, getter,
+ 0, arguments, EAttr::None, nullptr);
+
+ compileAssigningOp(writer, scope, targetVar, sourceVar);
+ }
+
+ return exprVal;
+}
+
ObjectInfo Compiler :: compileAssigning(BuildTreeWriter& writer, ExprScope& scope, SyntaxNode loperand,
SyntaxNode roperand, ExpressionAttribute mode)
{
@@ -7088,12 +7495,15 @@ ObjectInfo Compiler :: compileMessageOperationR(BuildTreeWriter& writer, ExprSco
switch (target.mode) {
case TargetMode::Casting:
- compileMessageArguments(writer, scope, messageNode, arguments, 0, EAttr::NoPrimitives, &updatedOuterArgs);
- if (arguments.count() == 1) {
+ {
+ bool dummy = false;
+ compileMessageArguments(writer, scope, messageNode, arguments, 0, EAttr::NoPrimitives, &updatedOuterArgs, dummy);
+ if (arguments.count() == 1 && !dummy) {
return convertObject(writer, scope, messageNode, arguments[0], retrieveStrongType(scope, target));
}
else scope.raiseError(errInvalidOperation, messageNode);
break;
+ }
default:
{
// NOTE : the operation target shouldn't be a primitive type
@@ -7112,11 +7522,19 @@ ObjectInfo Compiler :: compileMessageOperationR(BuildTreeWriter& writer, ExprSco
arguments.add(source);
}
+ bool withVariadicArg = false;
ref_t implicitSignatureRef = compileMessageArguments(writer, scope, messageNode, arguments, expectedSignRef,
- EAttr::NoPrimitives, &updatedOuterArgs);
+ EAttr::NoPrimitives, &updatedOuterArgs, withVariadicArg);
+
+ EAttr opMode = EAttr::None;
+ if (withVariadicArg) {
+ //messageRef |= VARIADIC_MESSAGE;
+
+ //opMode = EAttr::WithVariadicArg;
+ }
return compileMessageOperation(writer, scope, messageNode, source, messageRef,
- implicitSignatureRef, arguments, EAttr::None, &updatedOuterArgs);
+ implicitSignatureRef, arguments, opMode, &updatedOuterArgs);
break;
}
@@ -7193,11 +7611,42 @@ ObjectInfo Compiler :: compileIsNilOperation(BuildTreeWriter& writer, ExprScope&
}
+ObjectInfo Compiler :: compileFinalOperation(BuildTreeWriter& writer, ExprScope& scope, SyntaxNode node)
+{
+ ObjectInfo ehLocal = declareTempStructure(scope, { (int)scope.moduleScope->ehTableEntrySize, false });
+
+ int index1 = scope.newTempLocal();
+
+ SyntaxNode finallyNode = node.findChild(SyntaxKey::FinallyBlock).firstChild();
+ SyntaxNode opNode = node.firstChild();
+ if (opNode.existChild(SyntaxKey::ClosureBlock))
+ opNode = opNode.findChild(SyntaxKey::ClosureBlock);
+
+ writer.newNode(BuildKey::FinalOp, ehLocal.argument);
+ writer.appendNode(BuildKey::Index, index1);
+
+ writer.newNode(BuildKey::Tape);
+ compileExpression(writer, scope, opNode, 0, EAttr::None, nullptr);
+ writer.closeNode();
+
+ if (finallyNode.existChild(SyntaxKey::ClosureBlock))
+ finallyNode = finallyNode.findChild(SyntaxKey::ClosureBlock);
+
+ writer.newNode(BuildKey::Tape);
+ compileExpression(writer, scope, finallyNode, 0, EAttr::None, nullptr);
+ writer.closeNode();
+
+ writer.closeNode();
+
+ return {};
+}
+
ObjectInfo Compiler :: compileCatchOperation(BuildTreeWriter& writer, ExprScope& scope, SyntaxNode node)
{
ObjectInfo ehLocal = declareTempStructure(scope, { (int)scope.moduleScope->ehTableEntrySize, false });
SyntaxNode catchNode = node.findChild(SyntaxKey::CatchDispatch);
+ SyntaxNode finallyNode = node.findChild(SyntaxKey::FinallyBlock).firstChild();
SyntaxNode opNode = node.firstChild();
if (opNode.existChild(SyntaxKey::ClosureBlock))
opNode = opNode.findChild(SyntaxKey::ClosureBlock);
@@ -7209,10 +7658,18 @@ ObjectInfo Compiler :: compileCatchOperation(BuildTreeWriter& writer, ExprScope&
writer.closeNode();
writer.newNode(BuildKey::Tape);
-
compileMessageOperationR(writer, scope, { ObjectKind::Object }, catchNode.firstChild().firstChild());
writer.closeNode();
+ if (finallyNode != SyntaxKey::None) {
+ if (finallyNode.existChild(SyntaxKey::ClosureBlock))
+ finallyNode = finallyNode.findChild(SyntaxKey::ClosureBlock);
+
+ writer.newNode(BuildKey::Tape);
+ compileExpression(writer, scope, finallyNode, 0, EAttr::None, nullptr);
+ writer.closeNode();
+ }
+
writer.closeNode();
return {};
@@ -7238,16 +7695,6 @@ ObjectInfo Compiler :: mapConstant(Scope& scope, SyntaxNode node)
return { ObjectKind::ConstantLiteral, { V_WORD32 }, scope.module->mapConstant(node.identifier()) };
}
-inline ref_t mapIntConstant(Compiler::Scope& scope, int integer)
-{
- String s;
-
- // convert back to string as a decimal integer
- s.appendInt(integer, 16);
-
- return scope.moduleScope->module->mapConstant(s.str());
-}
-
inline ref_t mapLongConstant(Compiler::Scope& scope, long long integer)
{
String s;
@@ -7364,12 +7811,12 @@ ObjectInfo Compiler :: mapExtMessageConstant(Scope& scope, SyntaxNode node, ref_
Interpreter interpreter(scope.moduleScope, _logic);
ObjectInfo retVal = evalExpression(interpreter, scope, node.findChild(SyntaxKey::Expression));
switch (retVal.kind) {
- case ObjectKind::IntLiteral:
- argCount = retVal.extra;
- break;
- default:
- scope.raiseError(errCannotEval, node);
- break;
+ case ObjectKind::IntLiteral:
+ argCount = retVal.extra;
+ break;
+ default:
+ scope.raiseError(errCannotEval, node);
+ break;
}
mssg_t message = encodeMessage(actionRef, argCount, 0);
@@ -7412,7 +7859,7 @@ ObjectInfo Compiler :: mapTerminal(Scope& scope, SyntaxNode node, TypeInfo decla
bool newOp = EAttrs::testAndExclude(attrs, ExpressionAttribute::NewOp);
bool castOp = EAttrs::testAndExclude(attrs, ExpressionAttribute::CastOp);
bool refOp = EAttrs::testAndExclude(attrs, ExpressionAttribute::RefOp);
- bool mssgOp = EAttrs::testAndExclude(attrs, ExpressionAttribute::MssgLiteral);
+ bool mssgOp = EAttrs::testAndExclude(attrs, ExpressionAttribute::MssgNameLiteral);
bool probeMode = EAttrs::testAndExclude(attrs, ExpressionAttribute::ProbeMode);
bool memberMode = EAttrs::testAndExclude(attrs, ExpressionAttribute::Member);
bool ignoreDuplicates = EAttrs::testAndExclude(attrs, ExpressionAttribute::IgnoreDuplicate);
@@ -7746,8 +8193,10 @@ ObjectInfo Compiler :: convertObject(BuildTreeWriter& writer, ExprScope& scope,
// unbox wrapper for the conversion
source.typeInfo = { source.typeInfo.elementRef };
}
-
- auto conversionRoutine = _logic->retrieveConversionRoutine(this, *scope.moduleScope, targetRef, source.typeInfo);
+ NamespaceScope* nsScope = Scope::getScope(scope, Scope::ScopeLevel::Namespace);
+
+ auto conversionRoutine = _logic->retrieveConversionRoutine(this, *scope.moduleScope, *nsScope->nsName,
+ targetRef, source.typeInfo);
if (conversionRoutine.result == ConversionResult::BoxingRequired) {
// if it is implcitily compatible
switch (source.kind) {
@@ -7803,6 +8252,8 @@ ObjectInfo Compiler :: compileNestedExpression(BuildTreeWriter& writer, InlineCl
{
bool paramMode = EAttrs::test(mode, EAttr::Parameter);
ref_t nestedRef = scope.reference;
+ if (test(scope.info.header.flags, elVirtualVMT))
+ nestedRef = scope.info.header.parentRef;
if (test(scope.info.header.flags, elStateless)) {
ObjectInfo retVal = { ObjectKind::Singleton, { nestedRef }, nestedRef };
@@ -7837,6 +8288,12 @@ ObjectInfo Compiler :: compileNestedExpression(BuildTreeWriter& writer, InlineCl
writer.appendNode(BuildKey::Type, nestedRef);
writer.closeNode();
+ if (scope.outers.count() != scope.info.fields.count()) {
+ if (scope.info.fields.count() != 0) {
+ writer.appendNode(BuildKey::FillOp, scope.info.fields.count());
+ }
+ }
+
// second pass : fill members
int argIndex = 0;
int preservedClosure = 0;
@@ -7942,7 +8399,12 @@ ObjectInfo Compiler :: compileClosure(BuildTreeWriter& writer, ExprScope& ownerS
ref_t nestedRef = mapNested(ownerScope, mode);
InlineClassScope scope(&ownerScope, nestedRef);
- compileClosureClass(writer, scope, node);
+ BuildNode buildNode = writer.CurrentNode();
+ while (buildNode != BuildKey::Root)
+ buildNode = buildNode.parentNode();
+
+ BuildTreeWriter nestedWriter(buildNode);
+ compileClosureClass(nestedWriter, scope, node);
return compileNestedExpression(writer, scope, ownerScope, mode, updatedOuterArgs);
}
@@ -7954,9 +8416,9 @@ ObjectInfo Compiler :: compileNested(BuildTreeWriter& writer, ExprScope& ownerSc
EAttrs nestedMode = { EAttr::NestedDecl };
declareExpressionAttributes(ownerScope, node, parentInfo, nestedMode);
- // allow only new and type attrobutes
- if (nestedMode.attrs != EAttr::None && !EAttrs::test(nestedMode.attrs, EAttr::NewOp) && !EAttrs::test(nestedMode.attrs, EAttr::NewVariable))
- ownerScope.raiseError(errInvalidOperation, node);
+ //// allow only new and type attrobutes
+ //if (nestedMode.attrs != EAttr::None && !EAttrs::test(nestedMode.attrs, EAttr::NewOp) && !EAttrs::test(nestedMode.attrs, EAttr::NewVariable))
+ // ownerScope.raiseError(errInvalidOperation, node);
ref_t nestedRef = mapNested(ownerScope, mode);
InlineClassScope scope(&ownerScope, nestedRef);
@@ -8058,28 +8520,91 @@ void Compiler :: compileSwitchOperation(BuildTreeWriter& writer, ExprScope& scop
writer.closeNode();
}
-inline bool isConstant(ObjectKind kind)
+ref_t Compiler :: resolveTupleClass(Scope& scope, SyntaxNode node, ArgumentsInfo& items)
{
- switch (kind) {
- case ObjectKind::IntLiteral:
- case ObjectKind::Float64Literal:
- case ObjectKind::LongLiteral:
- case ObjectKind::StringLiteral:
- case ObjectKind::WideStringLiteral:
- return true;
- default:
- return false;
+ IdentifierString tupleName(scope.module->resolveReference(scope.moduleScope->buildins.tupleTemplateReference));
+
+ List parameters({});
+
+ // HOTFIX : generate a temporal template to pass the type
+ SyntaxTree dummyTree;
+ SyntaxTreeWriter dummyWriter(dummyTree);
+ dummyWriter.newNode(SyntaxKey::Root);
+
+ for (size_t i = 0; i < items.count(); i++) {
+ ref_t typeRef = retrieveStrongType(scope, items[i]);
+
+ dummyWriter.newNode(SyntaxKey::TemplateArg, typeRef);
+ dummyWriter.newNode(SyntaxKey::Type);
+
+ ustr_t referenceName = scope.moduleScope->module->resolveReference(typeRef);
+ if (isWeakReference(referenceName)) {
+ dummyWriter.appendNode(SyntaxKey::reference, referenceName);
+ }
+ else dummyWriter.appendNode(SyntaxKey::globalreference, referenceName);
+
+ dummyWriter.closeNode();
+ dummyWriter.closeNode();
+ }
+
+ dummyWriter.closeNode();
+
+ SyntaxNode current = dummyTree.readRoot().firstChild();
+ while (current == SyntaxKey::TemplateArg) {
+ parameters.add(current);
+
+ current = current.nextNode();
}
+
+ tupleName.append('#');
+ tupleName.appendInt(items.count());
+
+ ref_t templateReference = 0;
+ if (isWeakReference(*tupleName)) {
+ templateReference = scope.module->mapReference(*tupleName, true);
+ }
+ else templateReference = scope.moduleScope->mapFullReference(*tupleName, true);
+
+ if (!templateReference)
+ scope.raiseError(errInvalidOperation, node);
+
+ NamespaceScope* nsScope = Scope::getScope(scope, Scope::ScopeLevel::Namespace);
+
+ return _templateProcessor->generateClassTemplate(*scope.moduleScope, *nsScope->nsName,
+ templateReference, parameters, false, nullptr);
}
-inline bool areConstants(ArgumentsInfo& args)
+ObjectInfo Compiler :: compileTupleCollectiom(BuildTreeWriter& writer, ExprScope& scope, SyntaxNode node)
{
- for (size_t i = 0; i < args.count(); i++) {
- if (!isConstant(args[i].kind))
- return false;
+ ArgumentsInfo arguments;
+ EAttr paramMode = EAttr::Parameter;
+
+ SyntaxNode current = node.firstChild();
+ while (current != SyntaxKey::None) {
+ if (current == SyntaxKey::Expression) {
+ auto argInfo = compileExpression(writer, scope, current, 0,
+ paramMode, nullptr);
+
+ arguments.add(argInfo);
+ }
+
+ current = current.nextNode();
}
- return true;
+ ref_t tupleRef = resolveTupleClass(scope, node, arguments);
+
+ writer.newNode(BuildKey::CreatingClass, arguments.count());
+ writer.appendNode(BuildKey::Type, tupleRef);
+ writer.closeNode();
+
+ for (size_t i = 0; i < arguments.count(); i++) {
+ writer.appendNode(BuildKey::SavingInStack, 0);
+ writeObjectInfo(writer, scope, arguments[i]);
+ writer.appendNode(BuildKey::AccSwapping);
+ writer.appendNode(BuildKey::FieldAssigning, (pos_t)i);
+ }
+
+ return { ObjectKind::Object, { tupleRef }, 0 };
}
ObjectInfo Compiler :: compileCollection(BuildTreeWriter& writer, ExprScope& scope, SyntaxNode node, ExpressionAttribute mode)
@@ -8238,6 +8763,9 @@ ObjectInfo Compiler :: compileExpression(BuildTreeWriter& writer, ExprScope& sco
case SyntaxKey::CatchOperation:
retVal = compileCatchOperation(writer, scope, current);
break;
+ case SyntaxKey::FinalOperation:
+ retVal = compileFinalOperation(writer, scope, current);
+ break;
case SyntaxKey::AltOperation:
retVal = compileAltOperation(writer, scope, current);
break;
@@ -8283,6 +8811,12 @@ ObjectInfo Compiler :: compileExpression(BuildTreeWriter& writer, ExprScope& sco
return compileExpression(writer, scope, current.nextNode(), targetRef, exprAttr.attrs, updatedOuterArgs);
break;
}
+ case SyntaxKey::TupleCollection:
+ retVal = compileTupleCollectiom(writer, scope, current);
+ break;
+ case SyntaxKey::TupleAssignOperation:
+ retVal = compileTupleAssigning(writer, scope, current);
+ break;
case SyntaxKey::None:
assert(false);
break;
@@ -8358,6 +8892,11 @@ ObjectInfo Compiler :: compileRetExpression(BuildTreeWriter& writer, CodeScope&
if (!hasToBePresaved(retVal)) {
writeObjectInfo(writer, scope, retVal);
}
+ else if (retVal.kind == ObjectKind::Symbol) {
+ writeObjectInfo(writer, scope, retVal);
+
+ retVal = { ObjectKind::Object, retVal.typeInfo, 0 };
+ }
outputRef = retrieveStrongType(scope, retVal);
@@ -8422,6 +8961,7 @@ bool Compiler :: compileSymbolConstant(SymbolScope& scope, ObjectInfo retVal)
break;
case ObjectKind::StringLiteral:
case ObjectKind::IntLiteral:
+ case ObjectKind::Float64Literal:
scope.info.symbolType = SymbolType::Constant;
scope.info.valueRef = constRef;
scope.info.typeRef = retrieveStrongType(scope, retVal);
@@ -8590,10 +9130,18 @@ void Compiler :: injectVariableInfo(BuildNode node, CodeScope& codeScope)
BuildNode varNode = node.appendChild(BuildKey::IntVariableAddress, it.key());
varNode.appendChild(BuildKey::Index, localInfo.offset);
}
+ else if (localInfo.typeInfo.typeRef == codeScope.moduleScope->buildins.uintReference) {
+ BuildNode varNode = node.appendChild(BuildKey::UIntVariableAddress, it.key());
+ varNode.appendChild(BuildKey::Index, localInfo.offset);
+ }
else if (localInfo.typeInfo.typeRef == codeScope.moduleScope->buildins.byteReference) {
BuildNode varNode = node.appendChild(BuildKey::IntVariableAddress, it.key());
varNode.appendChild(BuildKey::Index, localInfo.offset);
}
+ else if (localInfo.typeInfo.typeRef == codeScope.moduleScope->buildins.shortReference) {
+ BuildNode varNode = node.appendChild(BuildKey::IntVariableAddress, it.key());
+ varNode.appendChild(BuildKey::Index, localInfo.offset);
+ }
else if (localInfo.typeInfo.typeRef == codeScope.moduleScope->buildins.longReference) {
BuildNode varNode = node.appendChild(BuildKey::LongVariableAddress, it.key());
varNode.appendChild(BuildKey::Index, localInfo.offset);
@@ -8779,6 +9327,43 @@ void Compiler :: compileInitializerMethod(BuildTreeWriter& writer, MethodScope&
endMethod(writer, scope);
}
+void Compiler :: compileStaticInitializerMethod(BuildTreeWriter& writer, ClassScope& scope, SyntaxNode node)
+{
+ BuildNode buildNode = writer.CurrentNode();
+ while (buildNode != BuildKey::Root)
+ buildNode = buildNode.parentNode();
+
+ BuildTreeWriter nestedWriter(buildNode);
+
+ nestedWriter.newNode(BuildKey::Symbol, node.arg.reference);
+
+ nestedWriter.newNode(BuildKey::Tape);
+ nestedWriter.appendNode(BuildKey::OpenFrame);
+
+ SyntaxNode current = node.firstChild();
+ while (current != SyntaxKey::None) {
+ if (current == SyntaxKey::AssignOperation) {
+ nestedWriter.appendNode(BuildKey::OpenStatement);
+ addBreakpoint(nestedWriter, findObjectNode(current), BuildKey::Breakpoint);
+
+ ExprScope exprScope(&scope);
+ compileExpression(nestedWriter, exprScope,
+ current, 0, EAttr::None, nullptr);
+
+ nestedWriter.appendNode(BuildKey::EndStatement);
+
+ exprScope.syncStack();
+ }
+ current = current.nextNode();
+ }
+
+ nestedWriter.appendNode(BuildKey::CloseFrame);
+ nestedWriter.appendNode(BuildKey::Exit);
+
+ nestedWriter.closeNode();
+ nestedWriter.closeNode();
+}
+
void Compiler :: compileAbstractMethod(BuildTreeWriter& writer, MethodScope& scope, SyntaxNode node, bool abstractMode)
{
SyntaxNode current = node.firstChild(SyntaxKey::MemberMask);
@@ -8909,11 +9494,19 @@ ObjectInfo Compiler :: compileResendCode(BuildTreeWriter& writer, CodeScope& cod
if (!test(messageRef, FUNCTION_MESSAGE))
arguments.add(source);
+ bool withVariadicArg = false;
ref_t implicitSignatureRef = compileMessageArguments(writer, scope, current, arguments, expectedSignRef,
- EAttr::NoPrimitives, &updatedOuterArgs);
+ EAttr::NoPrimitives, &updatedOuterArgs, withVariadicArg);
+
+ EAttr opMode = EAttr::None;
+ if (withVariadicArg) {
+ //messageRef |= VARIADIC_MESSAGE;
+
+ //opMode = EAttr::WithVariadicArg;
+ }
retVal = compileMessageOperation(writer, scope, node, target, messageRef,
- implicitSignatureRef, arguments, EAttr::None, &updatedOuterArgs);
+ implicitSignatureRef, arguments, opMode, &updatedOuterArgs);
scope.syncStack();
}
@@ -9212,10 +9805,17 @@ bool Compiler :: isDefaultOrConversionConstructor(Scope& scope, mssg_t message,
// NOTE : check if init_method is declared in the current class then call it
// returns the parent class reference
-ref_t Compiler :: callInitMethod(BuildTreeWriter& writer, SyntaxNode node, ExprScope& exprScope, ClassInfo& info, ref_t reference)
+void Compiler :: callInitMethod(BuildTreeWriter& writer, SyntaxNode node, ExprScope& exprScope, ClassInfo& info, ref_t reference)
{
if (!info.methods.exist(exprScope.moduleScope->buildins.init_message))
- return 0;
+ return;
+
+ if (info.header.parentRef != 0) {
+ ClassInfo classInfo;
+ _logic->defineClassInfo(*exprScope.moduleScope, classInfo, info.header.parentRef);
+
+ callInitMethod(writer, node, exprScope, classInfo, info.header.parentRef);
+ }
MethodInfo initInfo = info.methods.get(exprScope.moduleScope->buildins.init_message);
if (!initInfo.inherited) {
@@ -9225,24 +9825,13 @@ ref_t Compiler :: callInitMethod(BuildTreeWriter& writer, SyntaxNode node, ExprS
compileMessageOperation(writer, exprScope, node, args[0], exprScope.moduleScope->buildins.init_message,
0, args, EAttr::AlreadyResolved, nullptr);
}
-
- return info.header.parentRef;
}
void Compiler :: compileInlineInitializing(BuildTreeWriter& writer, ClassScope& classScope, SyntaxNode node)
{
ExprScope exprScope(&classScope);
- ref_t reference = classScope.reference;
- while (reference != 0) {
- if (reference != classScope.reference) {
- ClassInfo classInfo;
- _logic->defineClassInfo(*classScope.moduleScope, classInfo, reference);
-
- reference = callInitMethod(writer, node, exprScope, classInfo, reference);
- }
- else reference = callInitMethod(writer, node, exprScope, classScope.info, reference);
- }
+ callInitMethod(writer, node, exprScope, classScope.info, classScope.reference);
}
void Compiler :: compileDefConvConstructorCode(BuildTreeWriter& writer, MethodScope& scope,
@@ -9510,6 +10099,7 @@ void Compiler :: compileDispatcherMethod(BuildTreeWriter& writer, MethodScope& s
scope.messageLocalAddress = allocateLocalAddress(&codeScope, sizeof(mssg_t), false);
writer.appendNode(BuildKey::SavingIndex, scope.messageLocalAddress);
// unbox argument list
+ writer.appendNode(BuildKey::LoadArgCount, 1);
writer.appendNode(BuildKey::UnboxMessage, -1);
// change incoming message to variadic multi-method
writer.newNode(BuildKey::LoadingSubject,
@@ -9584,6 +10174,9 @@ void Compiler :: compileVMT(BuildTreeWriter& writer, ClassScope& scope, SyntaxNo
scope.raiseError(errIllegalStaticMethod, node);
}
break;
+ case SyntaxKey::StaticInitializerMethod:
+ compileStaticInitializerMethod(writer, scope, current);
+ break;
default:
break;
}
@@ -9717,7 +10310,7 @@ void Compiler :: compileClosureClass(BuildTreeWriter& writer, ClassScope& scope,
bool lazyExpression = node == SyntaxKey::LazyOperation;
ref_t parentRef = scope.info.header.parentRef;
- writer.newNode(BuildKey::NestedClass, scope.reference);
+ writer.newNode(BuildKey::Class, scope.reference);
MethodScope methodScope(&scope);
declareClosureMessage(methodScope, node);
@@ -9869,8 +10462,27 @@ void Compiler :: injectInterfaceDispatch(Scope& scope, SyntaxNode node, ref_t pa
void Compiler :: compileNestedClass(BuildTreeWriter& writer, ClassScope& scope, SyntaxNode node, ref_t parentRef)
{
NamespaceScope* ns = Scope::getScope(scope, Scope::ScopeLevel::Namespace);
-
scope.info.header.flags |= elNestedClass;
+
+ bool virtualClass = true;
+ // NOTE : check if it is in-place initialization
+ SyntaxNode current = node.firstChild();
+ while (current != SyntaxKey::None) {
+ switch (current.key) {
+ case SyntaxKey::Field:
+ case SyntaxKey::Method:
+ virtualClass = false;
+ break;
+ default:
+ break;
+ }
+
+ current = current.nextNode();
+ }
+
+ if (virtualClass)
+ scope.info.header.flags |= elVirtualVMT;
+
declareClassParent(parentRef, scope, node);
ref_t dummy = 0;
@@ -9892,20 +10504,26 @@ void Compiler :: compileNestedClass(BuildTreeWriter& writer, ClassScope& scope,
scope.save();
- writer.newNode(BuildKey::NestedClass, scope.reference);
+ BuildNode buildNode = writer.CurrentNode();
+ while (buildNode != BuildKey::Root)
+ buildNode = buildNode.parentNode();
- writer.appendNode(BuildKey::Path, *ns->sourcePath);
+ BuildTreeWriter nestedWriter(buildNode);
+
+ nestedWriter.newNode(BuildKey::Class, scope.reference);
+
+ nestedWriter.appendNode(BuildKey::Path, *ns->sourcePath);
- compileVMT(writer, scope, node, true, true);
+ compileVMT(nestedWriter, scope, node, true, true);
// set flags once again
// NOTE : it should be called after the code compilation to take into consideration outer fields
_logic->tweakClassFlags(*scope.moduleScope, scope.reference, scope.info, scope.isClassClass());
// NOTE : compile once again only auto generated methods
- compileVMT(writer, scope, node, true, false);
+ compileVMT(nestedWriter, scope, node, true, false);
- writer.closeNode();
+ nestedWriter.closeNode();
scope.save();
}
@@ -10120,8 +10738,9 @@ void Compiler :: prepare(ModuleScopeBase* moduleScope, ForwardResolverBase* forw
moduleScope->buildins.argArrayTemplateReference = safeMapReference(moduleScope, forwardResolver, VARIADIC_ARRAY_FORWARD);
moduleScope->buildins.closureTemplateReference = safeMapWeakReference(moduleScope, forwardResolver, CLOSURE_FORWARD);
+ moduleScope->buildins.tupleTemplateReference = safeMapWeakReference(moduleScope, forwardResolver, TUPLE_FORWARD);
moduleScope->buildins.lazyExpressionReference = safeMapWeakReference(moduleScope, forwardResolver, LAZY_FORWARD);
- moduleScope->buildins.dwordReference = safeMapReference(moduleScope, forwardResolver, DWORD_FORWARD);
+ moduleScope->buildins.uintReference = safeMapReference(moduleScope, forwardResolver, UINT_FORWARD);
moduleScope->buildins.pointerReference = safeMapReference(moduleScope, forwardResolver, PTR_FORWARD);
moduleScope->branchingInfo.typeRef = safeMapReference(moduleScope, forwardResolver, BOOL_FORWARD);
@@ -10219,6 +10838,11 @@ void Compiler :: prepare(ModuleScopeBase* moduleScope, ForwardResolverBase* forw
{
return current == reference;
}));
+ moduleScope->receivedVar.copy(moduleScope->predefined.retrieve("@received", V_RECEIVED_VAR,
+ [](ref_t reference, ustr_t key, ref_t current)
+ {
+ return current == reference;
+ }));
if (!moduleScope->tapeOptMode)
moduleScope->tapeOptMode = _tapeOptMode;
@@ -10327,9 +10951,11 @@ inline SyntaxNode newVirtualMultimethod(SyntaxNode classNode, SyntaxKey methodTy
return methodNode;
}
-inline SyntaxNode newVirtualMethod(SyntaxNode classNode, SyntaxKey methodType, mssg_t message, Visibility visibility)
+inline SyntaxNode newVirtualMethod(SyntaxNode classNode, SyntaxKey methodType, mssg_t message, Visibility visibility, bool abstractOne)
{
ref_t hints = methodType == SyntaxKey::StaticMethod ? (ref_t)MethodHint::Sealed : (ref_t)MethodHint::Normal;
+ if (abstractOne)
+ hints |= (ref_t)MethodHint::Abstract;
switch (visibility) {
case Visibility::Protected:
@@ -10349,7 +10975,7 @@ inline SyntaxNode newVirtualMethod(SyntaxNode classNode, SyntaxKey methodType, m
}
void Compiler :: injectVirtualEmbeddableWrapper(SyntaxNode classNode, SyntaxKey methodType, ModuleScopeBase& scope,
- ref_t targetRef, ClassInfo& info, mssg_t message)
+ ref_t targetRef, ClassInfo& info, mssg_t message, bool abstractOne)
{
MethodInfo methodInfo = {};
@@ -10370,13 +10996,16 @@ void Compiler :: injectVirtualEmbeddableWrapper(SyntaxNode classNode, SyntaxKey
visibility = Visibility::Private;
}
- SyntaxNode methodNode = newVirtualMethod(classNode, methodType, message, visibility);
+ SyntaxNode methodNode = newVirtualMethod(classNode, methodType, message, visibility, abstractOne);
methodNode.appendChild(SyntaxKey::Autogenerated, -1); // -1 indicates autogenerated method
- mssg_t resendMessage = message | STATIC_MESSAGE;
+ if (!abstractOne) {
+ mssg_t resendMessage = message | STATIC_MESSAGE;
- SyntaxNode resendOp = methodNode.appendChild(SyntaxKey::DirectResend, resendMessage);
- resendOp.appendChild(SyntaxKey::Target, targetRef);
+ SyntaxNode resendOp = methodNode.appendChild(SyntaxKey::DirectResend, resendMessage);
+ resendOp.appendChild(SyntaxKey::Target, targetRef);
+ }
+ else methodNode.appendChild(SyntaxKey::WithoutBody);
}
}
@@ -10536,7 +11165,7 @@ void Compiler :: injectVirtualMultimethod(SyntaxNode classNode, SyntaxKey method
void Compiler :: injectVirtualTryDispatch(SyntaxNode classNode, SyntaxKey methodType,
mssg_t message, mssg_t dispatchMessage, ref_t originalTarget)
{
- SyntaxNode methodNode = newVirtualMethod(classNode, methodType, message, Visibility::Public);
+ SyntaxNode methodNode = newVirtualMethod(classNode, methodType, message, Visibility::Public, false);
methodNode.appendChild(SyntaxKey::Autogenerated, -1); // -1 indicates autogenerated method
SyntaxNode dispatchOp = methodNode.appendChild(SyntaxKey::RedirectTryDispatch, dispatchMessage);
diff --git a/elenasrc3/elc/compiler.h b/elenasrc3/elc/compiler.h
index e5ade931f8..7442799d66 100644
--- a/elenasrc3/elc/compiler.h
+++ b/elenasrc3/elc/compiler.h
@@ -41,6 +41,7 @@ namespace elena_lang
Terminator,
Symbol,
Class,
+ ClassSelf,
Method,
Object,
Singleton,
@@ -99,7 +100,8 @@ namespace elena_lang
UnboxingRequired,
RefUnboxingRequired,
LocalUnboxingRequired,
- ArrayContent
+ ArrayContent,
+ UnboxingVarArgument
};
struct ObjectInfo
@@ -189,6 +191,14 @@ namespace elena_lang
this->extra = extra;
mode = TargetMode::None;
}
+ ObjectInfo(ObjectKind kind, TypeInfo typeInfo, int argument, TargetMode mode)
+ {
+ this->kind = kind;
+ this->typeInfo = typeInfo;
+ this->argument = argument;
+ this->extra = 0;
+ this->mode = mode;
+ }
ObjectInfo(ObjectKind kind, TypeInfo typeInfo, ref_t reference, TargetMode mode)
{
this->kind = kind;
@@ -256,6 +266,7 @@ namespace elena_lang
};
typedef CachedList ArgumentsInfo;
+ typedef CachedList TypeList;
// --- Interpreter ---
class Interpreter
@@ -267,7 +278,7 @@ namespace elena_lang
void setAttributeMapValue(ref_t dictionaryRef, ustr_t key, ustr_t value);
void setTypeMapValue(ref_t dictionaryRef, ustr_t key, ref_t reference);
- void addTypeListItem(ref_t dictionaryRef, ref_t symbolRef);
+ void addTypeListItem(ref_t dictionaryRef, ref_t symbolRef, ref_t mask);
void addConstArrayItem(ref_t dictionaryRef, ref_t item, ref_t mask);
bool evalDictionaryOp(ref_t operator_id, ArgumentsInfo& args);
@@ -307,7 +318,8 @@ namespace elena_lang
{
None = 0,
Multimethod,
- EmbeddableWrapper
+ EmbeddableWrapper,
+ AbstractEmbeddableWrapper
};
typedef Pair VirtualMethod;
@@ -705,6 +717,13 @@ namespace elena_lang
return scope ? scope->reference : 0;
}
+ ref_t getClassFlags(bool ownerClass = true)
+ {
+ ClassScope* scope = Scope::getScope(*this, ownerClass ? ScopeLevel::OwnerClass : ScopeLevel::Class);
+
+ return scope ? scope->info.header.flags : 0;
+ }
+
Visibility getClassVisibility(bool ownerClass = true)
{
ClassScope* scope = Scope::getScope(*this, ownerClass ? ScopeLevel::OwnerClass : ScopeLevel::Class);
@@ -945,7 +964,7 @@ namespace elena_lang
ref_t mapNewTerminal(Scope& scope, ustr_t prefix, SyntaxNode nameNode, ustr_t postfix, Visibility visibility);
mssg_t mapMethodName(MethodScope& scope, pos_t paramCount, ustr_t actionName, ref_t actionRef,
- ref_t flags, ref_t* signature, size_t signatureLen);
+ ref_t flags, ref_t* signature, size_t signatureLen, bool withoutWeakMessages, bool noSignature);
mssg_t mapMessage(Scope& scope, SyntaxNode node, bool propertyMode, bool extensionMode, bool probeMode);
ExternalInfo mapExternal(Scope& scope, SyntaxNode node);
@@ -977,11 +996,12 @@ namespace elena_lang
ref_t resolveTypeTemplate(Scope& scope, SyntaxNode node,
TypeAttributes& attributes, bool declarationMode, bool objectMode = false);
- ref_t resolveTemplate(Scope& scope, ref_t templateRef, ref_t elementRef, bool declarationMode);
+ ref_t resolveTemplate(ModuleScopeBase& moduleScope, ustr_t ns, ref_t templateRef, ref_t elementRef, bool declarationMode);
ref_t resolveClosure(Scope& scope, mssg_t closureMessage, ref_t outputRef);
- ref_t resolveWrapperTemplate(Scope& scope, ref_t elementRef, bool declarationMode);
- ref_t resolveArrayTemplate(Scope& scope, ref_t elementRef, bool declarationMode);
- ref_t resolveArgArrayTemplate(Scope& scope, ref_t elementRef, bool declarationMode);
+ ref_t resolveWrapperTemplate(ModuleScopeBase& moduleScope, ustr_t ns, ref_t elementRef, bool declarationMode);
+ ref_t resolveArrayTemplate(ModuleScopeBase& moduleScope, ustr_t ns, ref_t elementRef, bool declarationMode);
+ ref_t resolveArgArrayTemplate(ModuleScopeBase& moduleScope, ustr_t ns, ref_t elementRef, bool declarationMode);
+ ref_t resolveTupleClass(Scope& scope, SyntaxNode node, ArgumentsInfo& items);
int resolveSize(Scope& scope, SyntaxNode node);
TypeInfo resolveTypeAttribute(Scope& scope, SyntaxNode node, TypeAttributes& attributes,
@@ -1014,8 +1034,10 @@ namespace elena_lang
ObjectInfo allocateResult(ExprScope& scope, ref_t resultRef);
+ ref_t declareMultiType(Scope& scope, SyntaxNode& node, ref_t elementRef);
+
void declareTemplateAttributes(TemplateScope& scope, SyntaxNode node, IdentifierString& postfix);
- void declareSymbolAttributes(SymbolScope& scope, SyntaxNode node);
+ void declareSymbolAttributes(SymbolScope& scope, SyntaxNode node, bool identifierDeclarationMode);
void declareClassAttributes(ClassScope& scope, SyntaxNode node, ref_t& fldeclaredFlagsags);
void declareFieldAttributes(ClassScope& scope, SyntaxNode node, FieldAttributes& mode);
void declareMethodAttributes(MethodScope& scope, SyntaxNode node, bool exensionMode);
@@ -1037,7 +1059,7 @@ namespace elena_lang
void declareTemplateClass(TemplateScope& scope, SyntaxNode& node);
void declareTemplateCode(TemplateScope& scope, SyntaxNode& node);
- InheritResult inheritClass(ClassScope& scope, ref_t parentRef/*, bool ignoreFields, bool ignoreSealed*/);
+ InheritResult inheritClass(ClassScope& scope, ref_t parentRef/*, bool ignoreFields*/, bool ignoreSealed);
void checkMethodDuplicates(ClassScope& scope, SyntaxNode node, mssg_t message,
mssg_t publicMessage, bool protectedOne, bool internalOne);
@@ -1070,7 +1092,7 @@ namespace elena_lang
int resolveArraySize(Scope& scope, SyntaxNode node);
void declareParameter(MethodScope& scope, SyntaxNode node, bool withoutWeakMessages,
- bool declarationMode, bool& variadicMode, bool& weakSignature,
+ bool declarationMode, bool& variadicMode, bool& weakSignature, bool& noSignature,
pos_t& paramCount, ref_t* signature, size_t& signatureLen);
ref_t declareClosureParameters(MethodScope& methodScope, SyntaxNode argNode);
@@ -1080,6 +1102,8 @@ namespace elena_lang
void initializeMethod(ClassScope& scope, MethodScope& methodScope, SyntaxNode current);
+ void declareSymbolMetaInfo(SymbolScope& scope, SyntaxNode node);
+
void declareMetaInfo(Scope& scope, SyntaxNode node);
void declareMethodMetaInfo(MethodScope& scope, SyntaxNode node);
void declareMethod(MethodScope& scope, SyntaxNode node, bool abstractMode);
@@ -1126,7 +1150,7 @@ namespace elena_lang
ref_t outputRef);
ref_t compileMessageArguments(BuildTreeWriter& writer, ExprScope& scope, SyntaxNode current,
- ArgumentsInfo& arguments, ref_t expectedSignRef, ExpressionAttribute mode, ArgumentsInfo* updatedOuterArgs);
+ ArgumentsInfo& arguments, ref_t expectedSignRef, ExpressionAttribute mode, ArgumentsInfo* updatedOuterArgs, bool& variadicArgList);
void writeParameterDebugInfo(BuildTreeWriter& writer, MethodScope& scope);
void writeMessageInfo(BuildTreeWriter& writer, MethodScope& scope);
@@ -1138,6 +1162,7 @@ namespace elena_lang
ObjectInfo boxArgument(BuildTreeWriter& writer, ExprScope& scope, ObjectInfo info,
bool stackSafe, bool boxInPlace, bool allowingRefArg, ref_t targetRef = 0);
ObjectInfo boxArgumentLocally(BuildTreeWriter& writer, ExprScope& scope, ObjectInfo info, bool stackSafe);
+ ObjectInfo boxVariadicArgument(BuildTreeWriter& writer, ExprScope& scope, ObjectInfo info);
ObjectInfo unboxArguments(BuildTreeWriter& writer, ExprScope& scope, ObjectInfo retVal, ArgumentsInfo* updatedOuterArgs);
void unboxArgumentLocaly(BuildTreeWriter& writer, ExprScope& scope, ObjectInfo tempLocal, ObjectKey targetKey);
@@ -1154,7 +1179,8 @@ namespace elena_lang
ObjectInfo compileExternalOp(BuildTreeWriter& writer, ExprScope& scope, ref_t externalRef, bool stdCall,
ArgumentsInfo& arguments, ref_t expectedRef);
- ObjectInfo compileNewArrayOp(BuildTreeWriter& writer, ExprScope& scope, ObjectInfo source, ref_t targetRef, ArgumentsInfo& arguments);
+ ObjectInfo compileNewArrayOp(BuildTreeWriter& writer, ExprScope& scope, SyntaxNode node, ObjectInfo source,
+ ref_t targetRef, ArgumentsInfo& arguments);
ObjectInfo compileNewOp(BuildTreeWriter& writer, ExprScope& scope, SyntaxNode node,
ObjectInfo source, ref_t signRef, ArgumentsInfo& arguments);
ObjectInfo compileNativeConversion(BuildTreeWriter& writer, ExprScope& scope, SyntaxNode node, ObjectInfo source, ref_t operationKey);
@@ -1190,8 +1216,10 @@ namespace elena_lang
SyntaxNode r2node, int operatorId, ArgumentsInfo* updatedOuterArgs);
ObjectInfo compileBranchingOperation(BuildTreeWriter& writer, ExprScope& scope, SyntaxNode node, int operatorId);
ObjectInfo compileCatchOperation(BuildTreeWriter& writer, ExprScope& scope, SyntaxNode node);
+ ObjectInfo compileFinalOperation(BuildTreeWriter& writer, ExprScope& scope, SyntaxNode node);
ObjectInfo compileAltOperation(BuildTreeWriter& writer, ExprScope& scope, SyntaxNode node);
ObjectInfo compileIsNilOperation(BuildTreeWriter& writer, ExprScope& scope, SyntaxNode node);
+ ObjectInfo compileTupleAssigning(BuildTreeWriter& writer, ExprScope& scope, SyntaxNode node);
void compileSwitchOperation(BuildTreeWriter& writer, ExprScope& scope, SyntaxNode node);
@@ -1260,6 +1288,7 @@ namespace elena_lang
void compileDispatcherMethod(BuildTreeWriter& writer, MethodScope& scope, SyntaxNode node,
bool withGenerics, bool withOpenArgGenerics);
void compileInitializerMethod(BuildTreeWriter& writer, MethodScope& scope, SyntaxNode classNode);
+ void compileStaticInitializerMethod(BuildTreeWriter& writer, ClassScope& scope, SyntaxNode classNode);
void compileClosureMethod(BuildTreeWriter& writer, MethodScope& scope, SyntaxNode node);
void compileExpressionMethod(BuildTreeWriter& writer, MethodScope& scope, SyntaxNode node);
void compileAbstractMethod(BuildTreeWriter& writer, MethodScope& scope, SyntaxNode node, bool abstractMode);
@@ -1272,6 +1301,7 @@ namespace elena_lang
void compileClassVMT(BuildTreeWriter& writer, ClassScope& classClassScope, ClassScope& scope, SyntaxNode node);
ObjectInfo compileCollection(BuildTreeWriter& writer, ExprScope& scope, SyntaxNode node, ExpressionAttribute mode);
+ ObjectInfo compileTupleCollectiom(BuildTreeWriter& writer, ExprScope& scope, SyntaxNode node);
void compileSymbol(BuildTreeWriter& writer, SymbolScope& scope, SyntaxNode node);
void compileClassSymbol(BuildTreeWriter& writer, ClassScope& scope);
@@ -1282,6 +1312,8 @@ namespace elena_lang
void compileNamespace(BuildTreeWriter& writer, NamespaceScope& ns, SyntaxNode node);
+ ref_t compileStaticAssigning(ClassScope& scope, SyntaxNode node);
+
void validateClassFields(ClassScope& scope, SyntaxNode node);
void validateScope(ModuleScopeBase* moduleScope);
@@ -1292,7 +1324,7 @@ namespace elena_lang
void injectVirtualMultimethod(SyntaxNode classNode, SyntaxKey methodType, ModuleScopeBase& scope,
ClassInfo& info, mssg_t multiMethod);
void injectVirtualEmbeddableWrapper(SyntaxNode classNode, SyntaxKey methodType, ModuleScopeBase& scope,
- ref_t targetRef, ClassInfo& info, mssg_t multiMethod);
+ ref_t targetRef, ClassInfo& info, mssg_t multiMethod, bool abstractOne);
void injectVirtualMethods(SyntaxNode classNode, SyntaxKey methodType, ModuleScopeBase& scope,
ref_t targetRef, ClassInfo& info, VirtualMethodList& implicitMultimethods);
@@ -1321,7 +1353,7 @@ namespace elena_lang
void injectInheritedStaticMethod(SyntaxNode node, SyntaxKey methodType, ref_t reference, mssg_t message, ref_t outputRef);
- ref_t callInitMethod(BuildTreeWriter& writer, SyntaxNode node, ExprScope& exprScope, ClassInfo& info, ref_t reference);
+ void callInitMethod(BuildTreeWriter& writer, SyntaxNode node, ExprScope& exprScope, ClassInfo& info, ref_t reference);
void generateOverloadListMember(ModuleScopeBase& scope, ref_t listRef, ref_t classRef,
mssg_t messageRef, MethodHint type) override;
@@ -1345,7 +1377,8 @@ namespace elena_lang
void injectVirtualReturningMethod(ModuleScopeBase* scope, SyntaxNode classNode,
mssg_t message, ustr_t retVar, ref_t classRef) override;
- ref_t resolvePrimitiveType(ModuleScopeBase& scope, TypeInfo typeInfo) override;
+ ref_t resolvePrimitiveType(ModuleScopeBase& moduleScope, ustr_t ns, TypeInfo typeInfo,
+ bool declarationMode = false) override;
ref_t generateExtensionTemplate(ModuleScopeBase& scope, ref_t templateRef, size_t argumentLen, ref_t* arguments,
ustr_t ns, ExtensionMap* outerExtensionList) override;
diff --git a/elenasrc3/elc/compilerlogic.cpp b/elenasrc3/elc/compilerlogic.cpp
index 3c8ee46309..1f968b2d3a 100644
--- a/elenasrc3/elc/compilerlogic.cpp
+++ b/elenasrc3/elc/compilerlogic.cpp
@@ -50,7 +50,7 @@ struct Op
ref_t output;
};
-constexpr auto OperationLength = 117;
+constexpr auto OperationLength = 137;
constexpr Op Operations[OperationLength] =
{
{
@@ -83,6 +83,9 @@ constexpr Op Operations[OperationLength] =
{
ADD_ASSIGN_OPERATOR_ID, BuildKey::ObjArrayOp, V_OBJARRAY, V_OBJECT, 0, V_OBJECT
},
+ {
+ ADD_ASSIGN_OPERATOR_ID, BuildKey::ObjArrayOp, V_OBJARRAY, V_DECLARATION, 0, V_OBJECT
+ },
{
ADD_OPERATOR_ID, BuildKey::IntOp, V_INT32, V_INT32, 0, V_INT32
},
@@ -143,6 +146,63 @@ constexpr Op Operations[OperationLength] =
{
NOTEQUAL_OPERATOR_ID, BuildKey::IntCondOp, V_WORD32, V_WORD32, 0, V_FLAG
},
+ {
+ ADD_OPERATOR_ID, BuildKey::UIntOp, V_UINT32, V_UINT32, 0, V_UINT32
+ },
+ {
+ SUB_OPERATOR_ID, BuildKey::UIntOp, V_UINT32, V_UINT32, 0, V_UINT32
+ },
+ {
+ MUL_OPERATOR_ID, BuildKey::UIntOp, V_UINT32, V_UINT32, 0, V_UINT32
+ },
+ {
+ DIV_OPERATOR_ID, BuildKey::UIntOp, V_UINT32, V_UINT32, 0, V_UINT32
+ },
+ {
+ ADD_ASSIGN_OPERATOR_ID, BuildKey::UIntOp, V_UINT32, V_UINT32, 0, 0
+ },
+ {
+ SUB_ASSIGN_OPERATOR_ID, BuildKey::UIntOp, V_UINT32, V_UINT32, 0, 0
+ },
+ {
+ MUL_ASSIGN_OPERATOR_ID, BuildKey::UIntOp, V_UINT32, V_UINT32, 0, 0
+ },
+ {
+ DIV_ASSIGN_OPERATOR_ID, BuildKey::UIntOp, V_UINT32, V_UINT32, 0, 0
+ },
+ {
+ BAND_OPERATOR_ID, BuildKey::IntOp, V_UINT32, V_UINT32, 0, V_UINT32
+ },
+ {
+ BOR_OPERATOR_ID, BuildKey::IntOp, V_UINT32, V_UINT32, 0, V_UINT32
+ },
+ {
+ BXOR_OPERATOR_ID, BuildKey::IntOp, V_UINT32, V_UINT32, 0, V_UINT32
+ },
+ {
+ BNOT_OPERATOR_ID, BuildKey::IntSOp, V_UINT32, 0, 0, V_UINT32
+ },
+ {
+ SHL_OPERATOR_ID, BuildKey::IntOp, V_UINT32, V_UINT32, 0, V_UINT32
+ },
+ {
+ SHR_OPERATOR_ID, BuildKey::IntOp, V_UINT32, V_UINT32, 0, V_UINT32
+ },
+ {
+ EQUAL_OPERATOR_ID, BuildKey::UIntCondOp, V_UINT32, V_UINT32, 0, V_FLAG
+ },
+ {
+ LESS_OPERATOR_ID, BuildKey::UIntCondOp, V_UINT32, V_UINT32, 0, V_FLAG
+ },
+ {
+ NOTEQUAL_OPERATOR_ID, BuildKey::UIntCondOp, V_UINT32, V_UINT32, 0, V_FLAG
+ },
+ {
+ EQUAL_OPERATOR_ID, BuildKey::UIntCondOp, V_UINT32, V_UINT32, 0, V_FLAG
+ },
+ {
+ LESS_OPERATOR_ID, BuildKey::UIntCondOp, V_UINT32, V_UINT32, 0, V_FLAG
+ },
{
ADD_OPERATOR_ID, BuildKey::LongOp, V_INT64, V_INT64, 0, V_INT64
},
@@ -585,6 +645,7 @@ bool CompilerLogic :: validateFieldAttribute(ref_t attribute, FieldAttributes& a
case V_FIELD:
break;
case V_INTBINARY:
+ case V_UINTBINARY:
case V_WORDBINARY:
case V_MSSGBINARY:
case V_SUBJBINARY:
@@ -605,6 +666,9 @@ bool CompilerLogic :: validateFieldAttribute(ref_t attribute, FieldAttributes& a
case V_STATIC:
attrs.isStatic = true;
break;
+ case V_READONLY:
+ attrs.isReadonly = true;
+ break;
default:
return false;
}
@@ -738,7 +802,7 @@ bool CompilerLogic :: validateExpressionAttribute(ref_t attrValue, ExpressionAtt
case V_EXTERN:
attrs |= ExpressionAttribute::Extern;
return true;
- case V_NEWOP:
+ case V_NEWOP:
if (ExpressionAttributes::test(attrs.attrs, ExpressionAttribute::Parameter)
|| ExpressionAttributes::test(attrs.attrs, ExpressionAttribute::NestedDecl)
|| ExpressionAttributes::test(attrs.attrs, ExpressionAttribute::Meta))
@@ -771,6 +835,9 @@ bool CompilerLogic :: validateExpressionAttribute(ref_t attrValue, ExpressionAtt
case V_IGNOREDUPLICATE:
attrs |= ExpressionAttribute::IgnoreDuplicate;
return true;
+ case V_VARIADIC:
+ attrs |= ExpressionAttribute::Variadic;
+ return true;
default:
return false;
}
@@ -1079,6 +1146,7 @@ void CompilerLogic :: tweakClassFlags(ModuleScopeBase& scope, ref_t classRef, Cl
auto inner = *info.fields.start();
switch (inner.typeInfo.typeRef) {
case V_INT32:
+ case V_UINT32:
case V_INT8:
case V_PTR32:
case V_WORD32:
@@ -1096,6 +1164,9 @@ void CompilerLogic :: tweakClassFlags(ModuleScopeBase& scope, ref_t classRef, Cl
case V_MESSAGE:
info.header.flags |= elMessage;
break;
+ case V_MESSAGENAME:
+ info.header.flags |= elMessage;
+ break;
case V_INT32ARRAY:
info.header.flags |= elDebugDWORDS;
break;
@@ -1293,6 +1364,7 @@ bool CompilerLogic :: defineClassInfo(ModuleScopeBase& scope, ClassInfo& info, r
info.size = 8;
break;
case V_INT32:
+ case V_UINT32:
case V_PTR32:
case V_WORD32:
info.header.parentRef = scope.buildins.superReference;
@@ -1707,8 +1779,8 @@ ref_t CompilerLogic :: retrieveImplicitConstructor(ModuleScopeBase& scope, ref_t
return 0;
}
-ConversionRoutine CompilerLogic :: retrieveConversionRoutine(CompilerBase* compiler, ModuleScopeBase& scope, ref_t targetRef,
- TypeInfo sourceInfo)
+ConversionRoutine CompilerLogic :: retrieveConversionRoutine(CompilerBase* compiler, ModuleScopeBase& scope, ustr_t ns,
+ ref_t targetRef, TypeInfo sourceInfo)
{
ClassInfo info;
if (!defineClassInfo(scope, info, targetRef))
@@ -1754,7 +1826,7 @@ ConversionRoutine CompilerLogic :: retrieveConversionRoutine(CompilerBase* compi
// if there is a implicit conversion routine
if (!isPrimitiveRef(targetRef)) {
- ref_t sourceRef = sourceInfo.isPrimitive() ? compiler->resolvePrimitiveType(scope, sourceInfo) : sourceInfo.typeRef;
+ ref_t sourceRef = sourceInfo.isPrimitive() ? compiler->resolvePrimitiveType(scope, ns, sourceInfo) : sourceInfo.typeRef;
ref_t signRef = scope.module->mapSignature(&sourceRef, 1, false);
int stackSafeAttrs = 0;
diff --git a/elenasrc3/elc/compilerlogic.h b/elenasrc3/elc/compilerlogic.h
index 57bbee8478..d135e5faba 100644
--- a/elenasrc3/elc/compilerlogic.h
+++ b/elenasrc3/elc/compilerlogic.h
@@ -148,8 +148,8 @@ namespace elena_lang
ref_t retrieveImplicitConstructor(ModuleScopeBase& scope, ref_t targetRef, ref_t signRef,
pos_t signLen, int& stackSafeAttrs);
- ConversionRoutine retrieveConversionRoutine(CompilerBase* compiler, ModuleScopeBase& scope, ref_t targetRef,
- TypeInfo sourceInfo);
+ ConversionRoutine retrieveConversionRoutine(CompilerBase* compiler, ModuleScopeBase& scope, ustr_t ns,
+ ref_t targetRef, TypeInfo sourceInfo);
bool checkMethod(ClassInfo& info, mssg_t message, CheckMethodResult& result);
bool checkMethod(ModuleScopeBase& scope, ref_t reference, mssg_t message, CheckMethodResult& result);
diff --git a/elenasrc3/elc/compiling.cpp b/elenasrc3/elc/compiling.cpp
index bf7754de7a..bfac5a25c1 100644
--- a/elenasrc3/elc/compiling.cpp
+++ b/elenasrc3/elc/compiling.cpp
@@ -606,7 +606,7 @@ int CompilingProcess :: build(Project& project,
break;
}
- return _errorProcessor->hasWarnings() ? -1 : 0;
+ return _errorProcessor->hasWarnings() ? WARNING_RET_CODE : 0;
}
//catch (LinkerException e)
//{
@@ -617,36 +617,36 @@ int CompilingProcess :: build(Project& project,
_presenter->printPath(e.message, e.path, e.lineInfo.row, e.lineInfo.column, e.token);
_presenter->print(ELC_UNSUCCESSFUL);
- return -2;
+ return ERROR_RET_CODE;
}
catch (InvalidChar& e) {
_presenter->print("(%d,%d): Invalid char %c\n", e.lineInfo.row, e.lineInfo.column, e.ch);
_presenter->print(ELC_UNSUCCESSFUL);
- return -2;
+ return ERROR_RET_CODE;
}
catch (JITUnresolvedException& ex)
{
_presenter->print(_presenter->getMessage(errUnresovableLink), ex.referenceInfo.referenceName);
_presenter->print(ELC_UNSUCCESSFUL);
- return -2;
+ return ERROR_RET_CODE;
}
catch (InternalError& ex) {
_presenter->print(_presenter->getMessage(ex.messageCode), ex.arg);
_presenter->print(ELC_UNSUCCESSFUL);
- return -2;
+ return ERROR_RET_CODE;
}
catch(AbortError&) {
_presenter->print(ELC_UNSUCCESSFUL);
- return -2;
+ return ERROR_RET_CODE;
}
catch (...)
{
_presenter->print(_presenter->getMessage(errFatalError));
_presenter->print(ELC_UNSUCCESSFUL);
- return -2;
+ return ERROR_RET_CODE;
}
}
diff --git a/elenasrc3/elc/derivation.cpp b/elenasrc3/elc/derivation.cpp
index 9dd35c9e4a..a37de59c0e 100644
--- a/elenasrc3/elc/derivation.cpp
+++ b/elenasrc3/elc/derivation.cpp
@@ -13,15 +13,15 @@
using namespace elena_lang;
-inline void testNodes(SyntaxNode node)
-{
- SyntaxNode current = node.firstChild();
- while (current != SyntaxKey::None) {
- testNodes(current);
-
- current = current.nextNode();
- }
-}
+//inline void testNodes(SyntaxNode node)
+//{
+// SyntaxNode current = node.firstChild();
+// while (current != SyntaxKey::None) {
+// testNodes(current);
+//
+// current = current.nextNode();
+// }
+//}
inline bool testNodeMask(SyntaxKey key, SyntaxKey mask)
{
@@ -136,10 +136,12 @@ void SyntaxTreeBuilder :: parseStatement(SyntaxTreeWriter& writer, Scope& scope,
break;
case SyntaxKey::NTExpression:
case SyntaxKey::TExpression:
+ case SyntaxKey::LTExpression:
// unpacking the statement body
//flushExpression();
writer.newNode(SyntaxKey::Idle);
- flushExpression(writer, scope, current.firstChild());
+ flushExpressionMember(writer, scope, current.firstChild());
+ //flushExpression(writer, scope, current.firstChild());
parameters.add(writer.CurrentNode().firstChild());
writer.closeNode();
break;
@@ -435,6 +437,49 @@ void SyntaxTreeBuilder :: flushMessage(SyntaxTreeWriter& writer, Scope& scope, S
writer.closeNode();
}
+void SyntaxTreeBuilder :: generateTemplateOperation(SyntaxTreeWriter& writer, Scope& scope, SyntaxNode node)
+{
+ List arguments({});
+ List parameters({});
+
+ SyntaxNode op = node.findChild(SyntaxKey::MessageOperation);
+ SyntaxNode operatorTerminal = op.findChild(SyntaxKey::Operator).firstChild();
+
+ IdentifierString templateName("operator:");
+ switch (operatorTerminal.key) {
+ case SyntaxKey::AltOperation:
+ templateName.append("alt#1#1");
+ break;
+ default:
+ assert(false);
+ break;
+ }
+
+ // generate template arguments
+ SyntaxTree tempTree;
+ SyntaxTreeWriter tempWriter(tempTree);
+
+ tempWriter.newNode(SyntaxKey::Idle);
+ flushObject(tempWriter, scope, op.firstChild(SyntaxKey::Object));
+ arguments.add(tempWriter.CurrentNode().firstChild());
+ tempWriter.closeNode();
+
+ tempWriter.newNode(SyntaxKey::Idle);
+ flushExpression(tempWriter, scope, op);
+ parameters.add(tempWriter.CurrentNode().firstChild());
+ tempWriter.closeNode();
+
+ ref_t templateRef = _moduleScope->operations.get(*templateName);
+
+ if (_templateProcessor->importCodeTemplate(*_moduleScope, templateRef, writer.CurrentNode(),
+ arguments, parameters))
+ {
+ }
+ else {
+ _errorProcessor->raiseTerminalError(errInvalidOperation, retrievePath(node), node);
+ }
+}
+
void SyntaxTreeBuilder :: flushExpressionMember(SyntaxTreeWriter& writer, Scope& scope, SyntaxNode current)
{
switch (current.key) {
@@ -442,6 +487,7 @@ void SyntaxTreeBuilder :: flushExpressionMember(SyntaxTreeWriter& writer, Scope&
flushMethodMember(writer, scope, current);
break;
case SyntaxKey::Object:
+ case SyntaxKey::SubVariable:
flushObject(writer, scope, current);
break;
case SyntaxKey::NestedBlock:
@@ -457,6 +503,9 @@ void SyntaxTreeBuilder :: flushExpressionMember(SyntaxTreeWriter& writer, Scope&
writer.CurrentNode().setKey(SyntaxKey::CodeBlock);
generateTemplateStatement(writer, scope, current);
break;
+ case SyntaxKey::TemplateOperation:
+ generateTemplateOperation(writer, scope, current);
+ break;
default:
if (SyntaxTree::testSuperKey(current.key, SyntaxKey::Expression)) {
current.setKey(SyntaxKey::Expression);
@@ -503,8 +552,12 @@ void SyntaxTreeBuilder :: flushDescriptor(SyntaxTreeWriter& writer, Scope& scope
bool typeDescriptor)
{
SyntaxNode nameNode = node.lastChild(SyntaxKey::TerminalMask);
- if (typeDescriptor)
+ if (typeDescriptor) {
nameNode = nameNode.nextNode();
+ }
+ else if (nameNode.nextNode() == SyntaxKey::SubDeclaration) {
+ nameNode = {};
+ }
SyntaxNode current = node.firstChild();
ref_t attributeCategory = V_CATEGORY_MAX;
@@ -531,6 +584,15 @@ void SyntaxTreeBuilder :: flushDescriptor(SyntaxTreeWriter& writer, Scope& scope
writer.closeNode();
}
+ else if (current == SyntaxKey::SubDeclaration) {
+ flushDescriptor(writer, scope, current, withNameNode, typeDescriptor);
+
+ current = current.nextNode();
+
+ // HOTFIX : the last sub declaration contains the name node and should be the last one to analyze
+ if (current != SyntaxKey::SubDeclaration)
+ break;
+ }
else {
bool allowType = nameNode.key == SyntaxKey::None || nextNode == nameNode;
if (current == SyntaxKey::ArrayType) {
@@ -767,6 +829,18 @@ void SyntaxTreeBuilder :: flushParent(SyntaxTreeWriter& writer, Scope& scope, Sy
}
}
+void SyntaxTreeBuilder :: flushSymbolPostfixes(SyntaxTreeWriter& writer, Scope& scope, SyntaxNode node)
+{
+ SyntaxNode current = node.firstChild();
+ while (current != SyntaxKey::None) {
+ if (current.key == SyntaxKey::Postfix) {
+ flushTemplageExpression(writer, scope, current, SyntaxKey::InlineTemplate, false);
+ }
+
+ current = current.nextNode();
+ }
+}
+
void SyntaxTreeBuilder :: flushClassPostfixes(SyntaxTreeWriter& writer, Scope& scope, SyntaxNode node)
{
SyntaxNode current = node.firstChild();
@@ -801,6 +875,35 @@ void SyntaxTreeBuilder :: flushMethodMember(SyntaxTreeWriter& writer, Scope& sco
writer.closeNode();
}
+void SyntaxTreeBuilder :: flushExpressionAsDescriptor(SyntaxTreeWriter& writer, Scope& scope, SyntaxNode node)
+{
+ SyntaxNode current = node.firstChild();
+ while (current != SyntaxKey::None) {
+ if (current == SyntaxKey::Object) {
+ flushDescriptor(writer, scope, current);
+ }
+ else _errorProcessor->raiseTerminalError(errInvalidSyntax, retrievePath(node), node);
+
+ current = current.nextNode();
+ }
+
+}
+
+void SyntaxTreeBuilder :: flushParameterBlock(SyntaxTreeWriter& writer, Scope& scope, SyntaxNode node)
+{
+ SyntaxNode current = node.firstChild();
+ while (current != SyntaxKey::None) {
+ if (current == SyntaxKey::Expression) {
+ // HOTFIX : treat an expression as a parameter
+ writer.newNode(SyntaxKey::Parameter);
+ flushExpressionAsDescriptor(writer, scope, current);
+ writer.closeNode();
+ }
+
+ current = current.nextNode();
+ }
+}
+
void SyntaxTreeBuilder :: flushMethodCode(SyntaxTreeWriter& writer, Scope& scope, SyntaxNode node)
{
writer.newNode(node.key);
@@ -837,6 +940,9 @@ void SyntaxTreeBuilder :: flushClosure(SyntaxTreeWriter& writer, Scope& scope, S
if (current == SyntaxKey::Parameter) {
flushMethodMember(writer, scope, current);
}
+ else if (current == SyntaxKey::ParameterBlock) {
+ flushParameterBlock(writer, scope, current);
+ }
else if (SyntaxTree::test(current.key, SyntaxKey::ScopeMask)) {
flushMethodCode(writer, scope, current);
break;
@@ -1247,6 +1353,10 @@ inline bool isTemplateDeclaration(SyntaxNode node, SyntaxNode declaration, bool&
else if (current == SyntaxKey::Parameter && (withPostfix || isTemplate(declaration))) {
return true;
}
+ else if (current == SyntaxKey::CodeBlock && !withPostfix && isTemplate(declaration)) {
+ // HOTFIX : recognize inline template with no arguments
+ return true;
+ }
else if (current != SyntaxKey::identifier)
break;
@@ -1293,12 +1403,17 @@ void SyntaxTreeBuilder :: flushDeclaration(SyntaxTreeWriter& writer, SyntaxNode
if(node.existChild(SyntaxKey::GetExpression)) {
writer.CurrentNode().setKey(SyntaxKey::Symbol);
+ flushSymbolPostfixes(writer, scope, node);
+
flushStatement(writer, scope, node.findChild(SyntaxKey::GetExpression));
}
else if (isTemplateDeclaration(node, writer.CurrentNode(), withComplexName)) {
if (withComplexName) {
SyntaxNode complexName = node.findChild(SyntaxKey::ComplexName);
- flushNode(writer, scope, complexName);
+ while (complexName == SyntaxKey::ComplexName) {
+ flushNode(writer, scope, complexName);
+ complexName = complexName.nextNode();
+ }
}
SyntaxNode body = node.firstChild(SyntaxKey::MemberMask);
diff --git a/elenasrc3/elc/derivation.h b/elenasrc3/elc/derivation.h
index adde5a9843..586a7fe6ab 100644
--- a/elenasrc3/elc/derivation.h
+++ b/elenasrc3/elc/derivation.h
@@ -122,6 +122,7 @@ namespace elena_lang
void parseStatement(SyntaxTreeWriter& writer, Scope& scope, SyntaxNode current,
List& arguments, List& parameters, IdentifierString& postfix);
void generateTemplateStatement(SyntaxTreeWriter& writer, Scope& scope, SyntaxNode node);
+ void generateTemplateOperation(SyntaxTreeWriter& writer, Scope& scope, SyntaxNode node);
void flushNode(SyntaxTreeWriter& writer, Scope& scope, SyntaxNode node);
void flushCollection(SyntaxTreeWriter& writer, Scope& scope, SyntaxNode node);
@@ -142,6 +143,7 @@ namespace elena_lang
void flushClosure(SyntaxTreeWriter& writer, Scope& scope, SyntaxNode node);
void flushExpression(SyntaxTreeWriter& writer, Scope& scope, SyntaxNode node);
void flushExpressionCollection(SyntaxTreeWriter& writer, Scope& scope, SyntaxNode node);
+ void flushExpressionAsDescriptor(SyntaxTreeWriter& writer, Scope& scope, SyntaxNode node);
void flushExpressionMember(SyntaxTreeWriter& writer, Scope& scope, SyntaxNode node);
void flushStatement(SyntaxTreeWriter& writer, Scope& scope, SyntaxNode node);
void flushMethodCode(SyntaxTreeWriter& writer, Scope& scope, SyntaxNode node);
@@ -155,6 +157,7 @@ namespace elena_lang
void flushClassMember(SyntaxTreeWriter& writer, Scope& scope, SyntaxNode node, bool functionMode = false);
void flushMethod(SyntaxTreeWriter& writer, Scope& scope, SyntaxNode node);
void flushMethodMember(SyntaxTreeWriter& writer, Scope& scope, SyntaxNode node);
+ void flushParameterBlock(SyntaxTreeWriter& writer, Scope& scope, SyntaxNode node);
void flushTemplate(SyntaxTreeWriter& writer, Scope& scope, SyntaxNode node);
bool flushAttribute(SyntaxTreeWriter& writer, Scope& scope, SyntaxNode node, ref_t& previusCategory,
bool allowType, int arrayNestLevel = 0);
@@ -163,6 +166,7 @@ namespace elena_lang
void flushInlineTemplatePostfixes(SyntaxTreeWriter& writer, Scope& scope, SyntaxNode node);
void flushClassMemberPostfixes(SyntaxTreeWriter& writer, Scope& scope, SyntaxNode node/*, bool ignorePostfix*/);
void flushClassPostfixes(SyntaxTreeWriter& writer, Scope& scope, SyntaxNode node);
+ void flushSymbolPostfixes(SyntaxTreeWriter& writer, Scope& scope, SyntaxNode node);
void flushParent(SyntaxTreeWriter& writer, Scope& scope, SyntaxNode node);
void flushParentTemplate(SyntaxTreeWriter& writer, Scope& scope, SyntaxNode node);
diff --git a/elenasrc3/elc/source.cpp b/elenasrc3/elc/source.cpp
index 63a7a74c40..2f4dc89b4f 100644
--- a/elenasrc3/elc/source.cpp
+++ b/elenasrc3/elc/source.cpp
@@ -14,17 +14,17 @@ using namespace elena_lang;
const char* source_dfa[31] =
{
- ".????????BB??B??????????????????BDFIRCDLDQDDDVDHEEEEEEEEEEDDDDYD?CCCCCCCCCCCCCCCCCCCCCCCCCCDDQDC?CCCCCCCCCCCCCCCCCCCCCCCCCCDDDDC",
+ ".????????BB??B??????????????????BDFIRCDLDQDDDVQHEEEEEEEEEEDDDDYD?CCCCCCCCCCCCCCCCCCCCCCCCCCDDQDC?CCCCCCCCCCCCCCCCCCCCCCCCCCDDDDC",
"*********BB*********************B***********************************************************************************************",
- "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAACCCCCCCCCCAAAAAAACCCCCCCCCCCCCCCCCCCCCCCCCCAAAACACCCCCCCCCCCCCCCCCCCCCCCCCCAAAAA",
- "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAQAADQDAAAAAAAAAAAAAAAAAAAAAAAAAAAAQQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAA",
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAACCCCCCCCCCAAAAAAACCCCCCCCCCCCCCCCCCCCCCCCCCAAAACACCCCCCCCCCCCCCCCCCCCCCCCCCAAAAC",
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAQAADQDAAAAAAAAAAAAAAAAAAAAAAAAAAAAQQQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAA",
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA$AEEEEEEEEEEAAAAAAAKKKKKKJJJJJJJJJJJJJJJJJJJJAAAAAAJJJJ$JJJJJJJJJJJJJJJJJJJJJJJAJJ",
"?FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFGFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFATAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXAAAAAAAA",
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAAAANAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIIIIIIIIIIIIIIIIIIIIIIIIIIAAAAIAIIIIIIIIIIIIIIIIIIIIIIIIIIAAAAA",
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
- "????????????????????????????????????????????????KKKKKKKKKK???????KKKKKK?????????????????????????????????J???????????????????????",
+ "????????????????????????????????????????????????KKKKKKKKKK???????KKKKKKJJJJJJJJJJJJJJJJJJJJ?????????????J???????????????????????",
"?????????????????????????????????????????????????????????????????MMMMMMMMMMMMMMMMMMMMMMMMMM????M?MMMMMMMMMMMMMMMMMMMMMMMMMM????M",
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAAMMMMMMMMMMAAAAAAAMMMMMMMMMMMMMMMMMMMMMMMMMMAAAAMAMMMMMMMMMMMMMMMMMMMMMMMMMMAAAAM",
"*NNNNNNNNN*NN*NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN",
diff --git a/elenasrc3/elc/source.h b/elenasrc3/elc/source.h
index 10b8f9235f..bd5f08cbe0 100644
--- a/elenasrc3/elc/source.h
+++ b/elenasrc3/elc/source.h
@@ -3,7 +3,7 @@
//
// This header contains ELENA Source Reader class declaration.
//
-// (C)2021-2022, by Aleksey Rakov
+// (C)2021-2023, by Aleksey Rakov
//---------------------------------------------------------------------------
#ifndef SOURCE_H
@@ -25,8 +25,13 @@ namespace elena_lang
}
};
+ inline bool isQuote(char state)
+ {
+ return state == dfaQuoteStart;
+ }
+
// --- SourceReader ---
- class SourceReader : protected TextParser
+ class SourceReader : protected TextParser
{
bool _operatorMode;
diff --git a/elenasrc3/elc/windows/elc.cpp b/elenasrc3/elc/windows/elc.cpp
index 90ae66f07f..d7de039186 100644
--- a/elenasrc3/elc/windows/elc.cpp
+++ b/elenasrc3/elc/windows/elc.cpp
@@ -207,7 +207,7 @@ int main()
PathString path(argv[i]);
if (!project.loadProject(*path)) {
- return -2;
+ return ERROR_RET_CODE;
}
}
else {
@@ -231,6 +231,6 @@ int main()
}
catch (CLIException)
{
- return -2;
+ return ERROR_RET_CODE;
}
}
diff --git a/elenasrc3/elenart/elenartmachine.cpp b/elenasrc3/elenart/elenartmachine.cpp
index 951ae9493d..0a1f8d029c 100644
--- a/elenasrc3/elenart/elenartmachine.cpp
+++ b/elenasrc3/elenart/elenartmachine.cpp
@@ -23,6 +23,8 @@ ELENARTMachine :: ELENARTMachine(path_t dllRootPath, path_t execPath, path_t con
PathString configPath(dllRootPath, configFile);
loadConfig(*configPath);
+
+ _providerInitialized = false;
}
void ELENARTMachine :: loadConfig(ConfigFile& config, path_t configPath, ConfigFile::Node root)
@@ -173,6 +175,14 @@ size_t ELENARTMachine :: loadAddressInfo(addr_t retPoint, char* lineInfo, size_t
return 0;
RTManager rtmanager(nullptr, &_debugSection);
+ if (!_providerInitialized) {
+ PathString rootPath;
+ rootPath.copySubPath(*_execPath, true);
+
+ rtmanager.loadRootPackage(_libraryProvider, *rootPath);
+
+ _providerInitialized = true;
+ }
return rtmanager.retriveAddressInfo(_libraryProvider, retPoint, lineInfo, length);
}
diff --git a/elenasrc3/elenart/elenartmachine.h b/elenasrc3/elenart/elenartmachine.h
index 171e42b42a..89495eaeaa 100644
--- a/elenasrc3/elenart/elenartmachine.h
+++ b/elenasrc3/elenart/elenartmachine.h
@@ -21,6 +21,7 @@ namespace elena_lang
PlatformType _platform;
LibraryProvider _libraryProvider;
+ bool _providerInitialized;
MemoryDump _debugSection;
diff --git a/elenasrc3/elenart/rtcommon.h b/elenasrc3/elenart/rtcommon.h
index 8ebfa91a0b..b2ce1e674d 100644
--- a/elenasrc3/elenart/rtcommon.h
+++ b/elenasrc3/elenart/rtcommon.h
@@ -14,7 +14,7 @@
namespace elena_lang
{
-#define ELENART_REVISION_NUMBER 0x001A
+#define ELENART_REVISION_NUMBER 0x001B
}
diff --git a/elenasrc3/elenart/windows/dllmain.cpp b/elenasrc3/elenart/windows/dllmain.cpp
index ebc8813473..538c495fdf 100644
--- a/elenasrc3/elenart/windows/dllmain.cpp
+++ b/elenasrc3/elenart/windows/dllmain.cpp
@@ -60,7 +60,7 @@ void init(HMODULE hModule)
// --- API export ---
-EXTERN_DLL_EXPORT void InitializeSTLA(SystemEnv* env, SymbolList* entry, void* criricalHandler)
+EXTERN_DLL_EXPORT void InitializeSTLA(SystemEnv* env, void* entry, void* criricalHandler)
{
systemEnv = env;
@@ -162,6 +162,20 @@ EXTERN_DLL_EXPORT addr_t LoadClassByStringLA(const char* symbolName)
return machine->loadClassReference(symbolName);
}
+EXTERN_DLL_EXPORT addr_t LoadClassByBufferLA(void* referenceName, size_t index, size_t length)
+{
+ if (length < 0x100) {
+ IdentifierString str((const char*)referenceName + index, length);
+
+ return LoadClassByStringLA(*str);
+ }
+ else {
+ DynamicString str((const char*)referenceName, index, length);
+
+ return LoadClassByStringLA(str.str());
+ }
+}
+
EXTERN_DLL_EXPORT addr_t LoadSymbolByString2LA(const char* ns, const char* symbolName)
{
ReferenceName fullName(ns, symbolName);
diff --git a/elenasrc3/elenasm/scriptmachine.cpp b/elenasrc3/elenasm/scriptmachine.cpp
index f8ba917268..f0dc51b405 100644
--- a/elenasrc3/elenasm/scriptmachine.cpp
+++ b/elenasrc3/elenasm/scriptmachine.cpp
@@ -44,6 +44,9 @@ ScriptEngineParserBase* ScriptEngine :: newParser(int id, ParserType type)
case ParserType::CF:
newOne = new ScriptEngineCFParser(baseOne);
break;
+ case ParserType::Build:
+ newOne = new ScriptEngineBuilder();
+ break;
default:
throw InvalidOperationError("Unknown parser type");
}
@@ -86,6 +89,9 @@ void ScriptEngine :: parseMetaScript(int id, ScriptEngineReaderBase& reader)
else if (reader.compare("text")) {
parser = newParser(id, ParserType::Text);
}
+ else if (reader.compare("build")) {
+ parser = newParser(id, ParserType::Build);
+ }
else throw SyntaxError("unrecognized parser", bm.lineInfo);
}
else {
@@ -211,3 +217,11 @@ void ScriptEngine :: free(void* tape)
// !! temporal solution : presuming only one tape at once
_tape.trim(0);
}
+
+pos_t ScriptEngine :: getLength(void* tape)
+{
+ if (_tape.get(0) == tape) {
+ return _tape.length();
+ }
+ else return 0;
+}
diff --git a/elenasrc3/elenasm/scriptmachine.h b/elenasrc3/elenasm/scriptmachine.h
index ea32c581e6..8d41b2c493 100644
--- a/elenasrc3/elenasm/scriptmachine.h
+++ b/elenasrc3/elenasm/scriptmachine.h
@@ -25,7 +25,7 @@ namespace elena_lang
CF = 0x10,
//ptTransform = 0x20,
Text = 0x30,
- //ptBuild = 0x40
+ Build = 0x40
};
PathString _rootPath;
@@ -54,6 +54,8 @@ namespace elena_lang
void free(void* tape);
+ pos_t getLength(void* tape);
+
ustr_t getLastError()
{
return _lastError.str();
diff --git a/elenasrc3/elenasm/transformer.cpp b/elenasrc3/elenasm/transformer.cpp
index f5e972258f..107ce8e27f 100644
--- a/elenasrc3/elenasm/transformer.cpp
+++ b/elenasrc3/elenasm/transformer.cpp
@@ -126,8 +126,6 @@ void ScriptEngineBuilder :: saveClass(MemoryWriter& writer, ScriptEngineReaderBa
void ScriptEngineBuilder :: flush(MemoryWriter& writer, ScriptEngineReaderBase& reader, Stack& stack)
{
- pos_t sizePos = writer.position();
- writer.writeDWord(0);
pos_t allocPos = writer.position();
writer.writeDWord(0);
@@ -138,10 +136,6 @@ void ScriptEngineBuilder :: flush(MemoryWriter& writer, ScriptEngineReaderBase&
saveClass(writer, reader, stack, 0, allocated, stackSize);
}
- pos_t len = writer.position() - sizePos - 8;
-
- writer.seek(sizePos);
- writer.writeDWord(len);
writer.seek(allocPos);
writer.writeDWord(allocated + stackSize);
writer.seekEOF();
@@ -151,7 +145,7 @@ void ScriptEngineBuilder :: parse(ScriptEngineReaderBase& reader, MemoryDump* ou
{
MemoryWriter writer(output);
- ScriptBookmark defVal;
+ ScriptBookmark defVal = {};
Stack stack(defVal);
Stack bookmarks(0);
@@ -181,6 +175,11 @@ void ScriptEngineBuilder :: parse(ScriptEngineReaderBase& reader, MemoryDump* ou
bm = reader.read();
}
+ if (output->length() == 0)
+ writer.writeDWord(0);
+}
- writer.writeDWord(0);
+bool ScriptEngineBuilder :: parseGrammarRule(ScriptEngineReaderBase& reader)
+{
+ return false;
}
diff --git a/elenasrc3/elenasm/transformer.h b/elenasrc3/elenasm/transformer.h
index 5213389104..5fb8d6dc86 100644
--- a/elenasrc3/elenasm/transformer.h
+++ b/elenasrc3/elenasm/transformer.h
@@ -30,8 +30,6 @@ namespace elena_lang
// --- ScriptEngineBuilder ---
class ScriptEngineBuilder : public ScriptEngineParserBase
{
- int _width;
-
void saveToken(MemoryWriter& writer, ScriptEngineReaderBase& reader, ScriptBookmark bm);
void saveClass(MemoryWriter& writer, ScriptEngineReaderBase& reader, Stack& stack, int allocated,
@@ -45,7 +43,6 @@ namespace elena_lang
ScriptEngineBuilder()
{
- _width = 0x50;
}
};
diff --git a/elenasrc3/elenasm/windows/dllmain.cpp b/elenasrc3/elenasm/windows/dllmain.cpp
index 13a66c7667..ec874b5aaa 100644
--- a/elenasrc3/elenasm/windows/dllmain.cpp
+++ b/elenasrc3/elenasm/windows/dllmain.cpp
@@ -27,7 +27,7 @@ void init(HMODULE hModule)
engine = new ScriptEngine(*rootPath);
}
-EXTERN_DLL_EXPORT int NewScope()
+EXTERN_DLL_EXPORT int NewScopeSMLA()
{
if (engine) {
return engine->newScope();
@@ -35,25 +35,33 @@ EXTERN_DLL_EXPORT int NewScope()
else return -1;
}
-EXTERN_DLL_EXPORT void* InterpretScopeFile(int scope_id, const char* pathStr, int encoding, bool autoDetect)
+EXTERN_DLL_EXPORT void* InterpretScopeFileSMLA(int scope_id, const char* pathStr, int encoding, bool autoDetect)
{
PathString path(pathStr);
return engine->translate(scope_id, *path, (FileEncoding)encoding, autoDetect);
}
-EXTERN_DLL_EXPORT void* InterpretScopeScript(int scope_id, ustr_t script)
+EXTERN_DLL_EXPORT void* InterpretScopeScriptSMLA(int scope_id, ustr_t script)
{
return engine->translate(scope_id, script);
}
-EXTERN_DLL_EXPORT void Release(void* tape)
+EXTERN_DLL_EXPORT int GetLengthSMLA(void* tape)
+{
+ if (tape) {
+ return engine->getLength(tape);
+ }
+ else return 0;
+}
+
+EXTERN_DLL_EXPORT void ReleaseSMLA(void* tape)
{
if (tape)
engine->free(tape);
}
-EXTERN_DLL_EXPORT size_t GetStatus(char* buffer, size_t maxLength)
+EXTERN_DLL_EXPORT size_t GetStatusSMLA(char* buffer, size_t maxLength)
{
if (engine) {
ustr_t error = engine->getLastError();
diff --git a/elenasrc3/elenavm/elenavmmachine.cpp b/elenasrc3/elenavm/elenavmmachine.cpp
index 1f8d925264..f1cf66afbc 100644
--- a/elenasrc3/elenavm/elenavmmachine.cpp
+++ b/elenasrc3/elenavm/elenavmmachine.cpp
@@ -74,7 +74,6 @@ class ELENAVMConfiguration : public XmlProjectBase
}
};
-
// --- ELENARTMachine ---
ELENAVMMachine :: ELENAVMMachine(path_t configPath, PresenterBase* presenter, PlatformType platform,
@@ -90,9 +89,6 @@ ELENAVMMachine :: ELENAVMMachine(path_t configPath, PresenterBase* presenter, Pl
_settings.autoLoadMode = _configuration->BoolSetting(ProjectOption::ClassSymbolAutoLoad);
_settings.virtualMode = false;
_settings.alignment = codeAlignment;
- _settings.jitSettings.mgSize = _configuration->IntSetting(ProjectOption::GCMGSize, gcSettings.mgSize);
- _settings.jitSettings.ygSize = _configuration->IntSetting(ProjectOption::GCYGSize, gcSettings.ygSize);
-// _settings.jitSettings.threadCounter = _configuration->IntSetting(ProjectOption::ThreadCounter, 1);
// configurate the loader
_configuration->initLoader(_libraryProvider);
@@ -100,15 +96,20 @@ ELENAVMMachine :: ELENAVMMachine(path_t configPath, PresenterBase* presenter, Pl
_compiler = jitCompilerFactory(&_libraryProvider, platform);
}
-void ELENAVMMachine :: init(JITLinker& linker, SystemEnv* env)
+void ELENAVMMachine :: init(JITLinker& linker, SystemEnv* exeEnv)
{
_presenter->print(ELENAVM_GREETING, ENGINE_MAJOR_VERSION, ENGINE_MINOR_VERSION, ELENAVM_REVISION_NUMBER);
_presenter->print(ELENAVM_INITIALIZING);
- _compiler->populatePreloaded((uintptr_t)env, (uintptr_t)env->th_table, (uintptr_t)env->gc_table);
+ _compiler->populatePreloaded((uintptr_t)exeEnv->th_table);
linker.prepare(_compiler);
+ _env = (SystemEnv*)_compiler->getSystemEnv();
+
+ // setting up system
+ __routineProvider.InitSTA(_env);
+
_initialized = true;
}
@@ -142,6 +143,9 @@ void ELENAVMMachine :: addPackage(ustr_t packageLine)
bool ELENAVMMachine :: configurateVM(MemoryReader& reader, SystemEnv* env)
{
+ _settings.jitSettings.ygSize = env->gc_yg_size;
+ _settings.jitSettings.mgSize = env->gc_mg_size;
+
pos_t command = 0;
ustr_t strArg = nullptr;
@@ -171,6 +175,9 @@ bool ELENAVMMachine :: configurateVM(MemoryReader& reader, SystemEnv* env)
case VM_INIT_CMD:
eop = true;
break;
+ case VM_PRELOADED_CMD:
+ _preloadedSection.copy(strArg);
+ break;
default:
break;
}
@@ -179,18 +186,35 @@ bool ELENAVMMachine :: configurateVM(MemoryReader& reader, SystemEnv* env)
return true;
}
-void ELENAVMMachine :: compileVMTape(MemoryReader& reader, MemoryDump& tapeSymbol, JITLinker& jitLinker, ModuleBase* dummyModule)
+void ELENAVMMachine :: fillPreloadedSymbols(MemoryWriter& writer, ModuleBase* dummyModule)
{
- MemoryWriter writer(&tapeSymbol);
+ ModuleInfoList symbolList({});
+ _mapper.forEachLazyReference(&symbolList, [](ModuleInfoList* symbolList, LazyReferenceInfo info)
+ {
+ if (info.mask == mskAutoSymbolRef) {
+ symbolList->add({ info.module, info.reference });
+ }
+ });
- pos_t sizePlaceholder = writer.position();
- writer.writePos(0);
+ for (auto it = symbolList.start(); !it.eof(); ++it) {
+ auto info = *it;
+ ustr_t symbolName = info.module->resolveReference(info.reference);
+ if (isWeakReference(symbolName)) {
+ IdentifierString fullName(info.module->name(), symbolName);
- pos_t command = 0;
- ustr_t strArg = nullptr;
+ ByteCodeUtil::write(writer, ByteCode::CallR, dummyModule->mapReference(*fullName) | mskSymbolRef);
+ }
+ else ByteCodeUtil::write(writer, ByteCode::CallR, dummyModule->mapReference(symbolName) | mskSymbolRef);
+ }
- ByteCodeUtil::write(writer, ByteCode::OpenIN, 2, 0);
+}
+void ELENAVMMachine :: compileVMTape(MemoryReader& reader, MemoryDump& tapeSymbol, JITLinker& jitLinker, ModuleBase* dummyModule)
+{
+ CachedList symbols;
+
+ pos_t command = 0;
+ ustr_t strArg = nullptr;
bool eop = false;
while (!eop) {
command = reader.getDWord();
@@ -202,14 +226,26 @@ void ELENAVMMachine :: compileVMTape(MemoryReader& reader, MemoryDump& tapeSymbo
eop = true;
break;
case VM_CALLSYMBOL_CMD:
- ByteCodeUtil::write(writer, ByteCode::CallR,
- dummyModule->mapReference(strArg) | mskProcedureRef);
+ jitLinker.resolve(strArg, mskSymbolRef, false);
+ symbols.add(dummyModule->mapReference(strArg) | mskSymbolRef);
break;
default:
break;
}
}
+ MemoryWriter writer(&tapeSymbol);
+
+ pos_t sizePlaceholder = writer.position();
+ writer.writePos(0);
+
+ ByteCodeUtil::write(writer, ByteCode::OpenIN, 2, 0);
+
+ fillPreloadedSymbols(writer, dummyModule);
+ for(size_t i = 0; i < symbols.count(); i++) {
+ ByteCodeUtil::write(writer, ByteCode::CallR, symbols[i]);
+ }
+
ByteCodeUtil::write(writer, ByteCode::CloseN);
ByteCodeUtil::write(writer, ByteCode::Quit);
@@ -219,17 +255,21 @@ void ELENAVMMachine :: compileVMTape(MemoryReader& reader, MemoryDump& tapeSymbo
writer.writePos(size);
}
-void ELENAVMMachine :: onNewCode()
+void ELENAVMMachine :: onNewCode(JITLinker& jitLinker)
{
-
+ ustr_t superClass = _configuration->resolveForward(SUPER_FORWARD);
+
+ jitLinker.complete(_compiler, superClass);
+
+ _mapper.clearLazyReferences();
}
-void ELENAVMMachine :: resumeVM(SystemEnv* env, void* criricalHandler)
+void ELENAVMMachine :: resumeVM(JITLinker& jitLinker, SystemEnv* env, void* criricalHandler)
{
if (!_initialized)
throw InternalError(errVMNotInitialized);
- onNewCode();
+ onNewCode(jitLinker);
__routineProvider.InitSTAExceptionHandling(env, criricalHandler);
}
@@ -261,7 +301,7 @@ int ELENAVMMachine :: interprete(SystemEnv* env, void* tape, pos_t size, const c
void* address = (void*)jitLinker->resolveTemporalByteCode(tapeSymbol, dummyModule);
- resumeVM(env, (void*)criricalHandler);
+ resumeVM(*jitLinker, env, (void*)criricalHandler);
freeobj(dummyModule);
freeobj(jitLinker);
@@ -271,9 +311,6 @@ int ELENAVMMachine :: interprete(SystemEnv* env, void* tape, pos_t size, const c
void ELENAVMMachine :: startSTA(SystemEnv* env, void* tape, const char* criricalHandlerReference)
{
- // setting up system
- __routineProvider.InitSTA(env);
-
int retVal = -1;
if (tape != nullptr) {
retVal = interprete(env, tape, INVALID_POS, criricalHandlerReference);
@@ -356,4 +393,33 @@ addr_t ELENAVMMachine::loadSymbol(ustr_t name)
// !! temporal
return 0;
}
-
+//
+//void ELENAVMMachine :: generateAutoSymbol(ModuleInfoList& list, ModuleBase* module, MemoryDump& tapeSymbol)
+//{
+// MemoryWriter writer(&tapeSymbol);
+//
+// pos_t sizePlaceholder = writer.position();
+// writer.writePos(0);
+//
+// pos_t command = 0;
+// ustr_t strArg = nullptr;
+//
+// ByteCodeUtil::write(writer, ByteCode::OpenIN, 2, 0);
+//
+// // generate the preloaded list
+// for (auto it = list.start(); !it.eof(); ++it) {
+// auto info = *it;
+// ustr_t symbolName = info.module->resolveReference(info.reference);
+// IdentifierString fullName(info.module->name(), symbolName);
+//
+// ByteCodeUtil::write(writer, ByteCode::CallR, module->mapReference(*fullName) | mskSymbolRef);
+// }
+//
+// ByteCodeUtil::write(writer, ByteCode::CloseN);
+// ByteCodeUtil::write(writer, ByteCode::Quit);
+//
+// pos_t size = writer.position() - sizePlaceholder - sizeof(pos_t);
+//
+// writer.seek(sizePlaceholder);
+// writer.writePos(size);
+//}
diff --git a/elenasrc3/elenavm/elenavmmachine.h b/elenasrc3/elenavm/elenavmmachine.h
index a390a9b29e..b182853ebb 100644
--- a/elenasrc3/elenavm/elenavmmachine.h
+++ b/elenasrc3/elenavm/elenavmmachine.h
@@ -27,12 +27,15 @@ namespace elena_lang
PresenterBase* _presenter;
ReferenceMapper _mapper;
JITLinkerSettings _settings;
+ SystemEnv* _env;
path_t _rootPath;
ProjectBase* _configuration;
JITCompilerBase* _compiler;
+ IdentifierString _preloadedSection;
+
virtual addr_t resolveExternal(ustr_t dll, ustr_t function) = 0;
void addForward(ustr_t forwardLine);
@@ -40,7 +43,7 @@ namespace elena_lang
int interprete(SystemEnv* env, void* tape, pos_t size, const char* criricalHandlerReference);
- void onNewCode();
+ void onNewCode(JITLinker& jitLinker);
void stopVM();
@@ -48,7 +51,7 @@ namespace elena_lang
void compileVMTape(MemoryReader& reader, MemoryDump& tapeSymbol, JITLinker& jitLinker,
ModuleBase* dummyModule);
- void resumeVM(SystemEnv* env, void* criricalHandler);
+ void resumeVM(JITLinker& jitLinker, SystemEnv* env, void* criricalHandler);
void init(JITLinker& jitLinker, SystemEnv* env);
@@ -56,6 +59,8 @@ namespace elena_lang
void loadSubjectName(IdentifierString& actionName, ref_t subjectRef);
+ void fillPreloadedSymbols(MemoryWriter& writer, ModuleBase* dummyModule);
+
public:
addr_t resolveExternal(ustr_t reference) override;
@@ -71,6 +76,13 @@ namespace elena_lang
void Exit(int exitCode);
+ SystemEnv* getSystemEnv()
+ {
+ return _env;
+ }
+
+ //void generateAutoSymbol(ModuleInfoList& list, ModuleBase* module, MemoryDump& tapeSymbol);
+
ELENAVMMachine(path_t configPath, PresenterBase* presenter, PlatformType platform,
int codeAlignment, JITSettings gcSettings,
JITCompilerBase* (*jitCompilerFactory)(LibraryLoaderBase*, PlatformType));
diff --git a/elenasrc3/elenavm/vmcommon.h b/elenasrc3/elenavm/vmcommon.h
index 5644ea6561..c2e300ccb8 100644
--- a/elenasrc3/elenavm/vmcommon.h
+++ b/elenasrc3/elenavm/vmcommon.h
@@ -3,13 +3,13 @@
//
// This file contains the compiler common interfaces & types
//
-// (C)2021-2022, by Aleksey Rakov
+// (C)2021-2023, by Aleksey Rakov
//---------------------------------------------------------------------------
#ifndef VMCOMMON_H
#define VMCOMMON_H
-#define ELENAVM_REVISION_NUMBER 0x000A
+#define ELENAVM_REVISION_NUMBER 0x000C
namespace elena_lang
{
diff --git a/elenasrc3/elenavm/windows/dllmain.cpp b/elenasrc3/elenavm/windows/dllmain.cpp
index bcdd6c7f1e..b05efbb8e1 100644
--- a/elenasrc3/elenavm/windows/dllmain.cpp
+++ b/elenasrc3/elenavm/windows/dllmain.cpp
@@ -49,7 +49,6 @@ JITCompilerBase* createJITCompiler(LibraryLoaderBase* loader, PlatformType platf
#endif
static ELENAVMMachine* machine = nullptr;
-static SystemEnv* systemEnv = nullptr;
#define EXTERN_DLL_EXPORT extern "C" __declspec(dllexport)
@@ -134,8 +133,6 @@ void printError(int errCode, ustr_t arg)
EXTERN_DLL_EXPORT void InitializeVMSTLA(SystemEnv* env, void* tape, const char* criricalHandlerReference)
{
- systemEnv = env;
-
#ifdef DEBUG_OUTPUT
printf("InitializeVMSTLA.6 %x,%x\n", (int)env, (int)criricalHandler);
@@ -179,12 +176,17 @@ EXTERN_DLL_EXPORT void ExitLA(int retVal)
EXTERN_DLL_EXPORT void* CollectGCLA(void* roots, size_t size)
{
- return __routineProvider.GCRoutine(systemEnv->gc_table, (GCRoot*)roots, size, false);
+ return __routineProvider.GCRoutine(machine->getSystemEnv()->gc_table, (GCRoot*)roots, size, false);
+}
+
+EXTERN_DLL_EXPORT void* CollectPermGCLA(size_t size)
+{
+ return __routineProvider.GCRoutinePerm(machine->getSystemEnv()->gc_table, size);
}
EXTERN_DLL_EXPORT void* ForcedCollectGCLA(void* roots, int fullMode)
{
- return __routineProvider.GCRoutine(systemEnv->gc_table, (GCRoot*)roots, INVALID_SIZE, fullMode != 0);
+ return __routineProvider.GCRoutine(machine->getSystemEnv()->gc_table, (GCRoot*)roots, INVALID_SIZE, fullMode != 0);
}
EXTERN_DLL_EXPORT size_t LoadMessageNameLA(size_t message, char* buffer, size_t length)
@@ -212,6 +214,20 @@ EXTERN_DLL_EXPORT addr_t LoadClassByStringLA(const char* symbolName)
return machine->loadClassReference(symbolName);
}
+EXTERN_DLL_EXPORT addr_t LoadClassByBufferLA(void* referenceName, size_t index, size_t length)
+{
+ if (length < 0x100) {
+ IdentifierString str((const char*)referenceName + index, length);
+
+ return LoadClassByStringLA(*str);
+ }
+ else {
+ DynamicString str((const char*)referenceName, index, length);
+
+ return LoadClassByStringLA(str.str());
+ }
+}
+
EXTERN_DLL_EXPORT addr_t LoadSymbolByString2LA(const char* ns, const char* symbolName)
{
ReferenceName fullName(ns, symbolName);
diff --git a/elenasrc3/elenavm/windows/elenawinvmachine.cpp b/elenasrc3/elenavm/windows/elenawinvmachine.cpp
index d7191938ab..9177a1d7d6 100644
--- a/elenasrc3/elenavm/windows/elenawinvmachine.cpp
+++ b/elenasrc3/elenavm/windows/elenawinvmachine.cpp
@@ -18,12 +18,12 @@ ELENAWinVMMachine :: ELENAWinVMMachine(path_t configPath, PresenterBase* present
JITCompilerBase*(* jitCompilerFactory)(LibraryLoaderBase*, PlatformType))
: ELENAVMMachine(configPath, presenter, platform, codeAlignment, gcSettings, jitCompilerFactory),
_text(TEXT_MAX_SIZE, false, true),
- _rdata(RDATA_MAX_SIZE, false, false),
+ _rdata(RDATA_MAX_SIZE, /*false*/true, false),
_data(DATA_MAX_SIZE, true, false),
_stat(STAT_MAX_SIZE, true, false),
- _adata(ADATA_MAX_SIZE, false, false),
- _mdata(MDATA_MAX_SIZE, false, false),
- _mbdata(MBDATA_MAX_SIZE, false, false),
+ _adata(ADATA_MAX_SIZE, /*false*/true, false),
+ _mdata(MDATA_MAX_SIZE, /*false*/true, false),
+ _mbdata(MBDATA_MAX_SIZE, /*false*/true, false),
_debug(DEBUG_MAX_SIZE, true, false)
{
}
diff --git a/elenasrc3/engine/arm64compiler.cpp b/elenasrc3/engine/arm64compiler.cpp
index 8c1baece65..b7d1810dbe 100644
--- a/elenasrc3/engine/arm64compiler.cpp
+++ b/elenasrc3/engine/arm64compiler.cpp
@@ -155,7 +155,8 @@ void ARM64JITCompiler :: prepare(
ImageProviderBase* imageProvider,
ReferenceHelperBase* helper,
LabelHelperBase*,
- JITSettings settings)
+ JITSettings settings,
+ bool virtualMode)
{
//_inlineMask = mskCodeRelRef32;
@@ -166,7 +167,7 @@ void ARM64JITCompiler :: prepare(
commands[(int)Overloads[i].value1] = Overloads[i].value2;
ARMLabelHelper labelHelper;
- JITCompiler64::prepare(loader, imageProvider, helper, &labelHelper, settings);
+ JITCompiler64::prepare(loader, imageProvider, helper, &labelHelper, settings, virtualMode);
}
void ARM64JITCompiler :: alignCode(MemoryWriter& writer, pos_t alignment, bool isText)
diff --git a/elenasrc3/engine/arm64compiler.h b/elenasrc3/engine/arm64compiler.h
index 5c82e82762..b7ad296e18 100644
--- a/elenasrc3/engine/arm64compiler.h
+++ b/elenasrc3/engine/arm64compiler.h
@@ -22,7 +22,8 @@ namespace elena_lang
ImageProviderBase* imageProvider,
ReferenceHelperBase* helper,
LabelHelperBase* lh,
- JITSettings settings) override;
+ JITSettings settings,
+ bool virtualMode) override;
friend void ARM64loadCallOp(JITCompilerScope* scope);
friend void ARM64compileOpenIN(JITCompilerScope* scope);
diff --git a/elenasrc3/engine/armhelper.h b/elenasrc3/engine/armhelper.h
index 17e2ec95eb..55aeee6baf 100644
--- a/elenasrc3/engine/armhelper.h
+++ b/elenasrc3/engine/armhelper.h
@@ -609,6 +609,38 @@ namespace elena_lang
writeBcc(offset, (int)JumpType::GE, writer);
}
+
+ void writeJleForward(pos_t label, MemoryWriter& writer, int byteCodeOffset) override
+ {
+ jumps.add(label, { writer.position() });
+
+ writeBcc(0, (int)JumpType::LE, writer);
+ }
+
+ void writeJleBack(pos_t label, MemoryWriter& writer) override
+ {
+ int offset = labels.get(label) - writer.position();
+ if (abs(offset) > 0x3FFFF)
+ throw InternalError(-1);
+
+ writeBcc(offset, (int)JumpType::LE, writer);
+ }
+
+ void writeJgrForward(pos_t label, MemoryWriter& writer, int byteCodeOffset) override
+ {
+ jumps.add(label, { writer.position() });
+
+ writeBcc(0, (int)JumpType::GT, writer);
+ }
+
+ void writeJgrBack(pos_t label, MemoryWriter& writer) override
+ {
+ int offset = labels.get(label) - writer.position();
+ if (abs(offset) > 0x3FFFF)
+ throw InternalError(-1);
+
+ writeBcc(offset, (int)JumpType::GT, writer);
+ }
};
}
diff --git a/elenasrc3/engine/bcwriter.cpp b/elenasrc3/engine/bcwriter.cpp
index 1a76b51e0b..58054469cf 100644
--- a/elenasrc3/engine/bcwriter.cpp
+++ b/elenasrc3/engine/bcwriter.cpp
@@ -243,7 +243,7 @@ void getArgument(CommandTape& tape, BuildNode& node, TapeScope&)
tape.write(ByteCode::PeekSI, node.arg.value);
}
-void getLocalAddredd(CommandTape& tape, BuildNode& node, TapeScope&)
+void getLocalAddress(CommandTape& tape, BuildNode& node, TapeScope&)
{
tape.write(ByteCode::SetDP, node.arg.value);
}
@@ -313,6 +313,11 @@ void mssgLiteral(CommandTape& tape, BuildNode& node, TapeScope& tapeScope)
tape.write(ByteCode::SetR, node.arg.reference | mskMssgLiteralRef);
}
+void mssgNameLiteral(CommandTape& tape, BuildNode& node, TapeScope& tapeScope)
+{
+ tape.write(ByteCode::SetR, node.arg.reference | mskMssgNameLiteralRef);
+}
+
void extMssgLiteral(CommandTape& tape, BuildNode& node, TapeScope& tapeScope)
{
tape.write(ByteCode::SetR, node.arg.reference | mskExtMssgLiteralRef);
@@ -495,6 +500,53 @@ void intOp(CommandTape& tape, BuildNode& node, TapeScope&)
}
}
+void uintOp(CommandTape& tape, BuildNode& node, TapeScope&)
+{
+ // NOTE : sp[0] - loperand, sp[1] - roperand
+ int targetOffset = node.findChild(BuildKey::Index).arg.value;
+
+ if (!isAssignOp(node.arg.value)) {
+ tape.write(ByteCode::CopyDPN, targetOffset, 4);
+ tape.write(ByteCode::XMovSISI, 0, 1);
+ }
+
+ switch (node.arg.value) {
+ case ADD_OPERATOR_ID:
+ case ADD_ASSIGN_OPERATOR_ID:
+ tape.write(ByteCode::IAddDPN, targetOffset, 4);
+ break;
+ case SUB_OPERATOR_ID:
+ case SUB_ASSIGN_OPERATOR_ID:
+ tape.write(ByteCode::ISubDPN, targetOffset, 4);
+ break;
+ case MUL_OPERATOR_ID:
+ case MUL_ASSIGN_OPERATOR_ID:
+ tape.write(ByteCode::IMulDPN, targetOffset, 4);
+ break;
+ case DIV_OPERATOR_ID:
+ case DIV_ASSIGN_OPERATOR_ID:
+ tape.write(ByteCode::UDivDPN, targetOffset, 4);
+ break;
+ case BAND_OPERATOR_ID:
+ tape.write(ByteCode::IAndDPN, targetOffset, 4);
+ break;
+ case BOR_OPERATOR_ID:
+ tape.write(ByteCode::IOrDPN, targetOffset, 4);
+ break;
+ case BXOR_OPERATOR_ID:
+ tape.write(ByteCode::IXorDPN, targetOffset, 4);
+ break;
+ case SHL_OPERATOR_ID:
+ tape.write(ByteCode::IShlDPN, targetOffset, 4);
+ break;
+ case SHR_OPERATOR_ID:
+ tape.write(ByteCode::IShrDPN, targetOffset, 4);
+ break;
+ default:
+ throw InternalError(errFatalError);
+ }
+}
+
void intSOp(CommandTape& tape, BuildNode& node, TapeScope&)
{
int targetOffset = node.findChild(BuildKey::Index).arg.value;
@@ -720,6 +772,40 @@ void intCondOp(CommandTape& tape, BuildNode& node, TapeScope&)
else tape.write(opCode, falseRef | mskVMTRef, trueRef | mskVMTRef);
}
+void uintCondOp(CommandTape& tape, BuildNode& node, TapeScope&)
+{
+ bool inverted = false;
+ ref_t trueRef = node.findChild(BuildKey::TrueConst).arg.reference;
+ ref_t falseRef = node.findChild(BuildKey::FalseConst).arg.reference;
+
+ // NOTE : sp[0] - loperand, sp[1] - roperand
+ tape.write(ByteCode::PeekSI, 1);
+
+ ByteCode opCode = ByteCode::None;
+ switch (node.arg.value) {
+ case LESS_OPERATOR_ID:
+ opCode = ByteCode::SelULtRR;
+ break;
+ case EQUAL_OPERATOR_ID:
+ tape.write(ByteCode::ICmpN, 4);
+ opCode = ByteCode::SelEqRR;
+ break;
+ case NOTEQUAL_OPERATOR_ID:
+ tape.write(ByteCode::ICmpN, 4);
+ opCode = ByteCode::SelEqRR;
+ inverted = true;
+ break;
+ default:
+ assert(false);
+ break;
+ }
+
+ if (!inverted) {
+ tape.write(opCode, trueRef | mskVMTRef, falseRef | mskVMTRef);
+ }
+ else tape.write(opCode, falseRef | mskVMTRef, trueRef | mskVMTRef);
+}
+
void byteCondOp(CommandTape& tape, BuildNode& node, TapeScope&)
{
bool inverted = false;
@@ -928,8 +1014,42 @@ void byteArraySOp(CommandTape& tape, BuildNode& node, TapeScope&)
tape.write(ByteCode::NLen, 1);
tape.write(ByteCode::SaveDP, targetOffset, 4);
break;
- default:
- throw InternalError(errFatalError);
+ default:
+ throw InternalError(errFatalError);
+ }
+}
+
+void vargSOp(CommandTape& tape, BuildNode& node, TapeScope&)
+{
+ // NOTE : sp[0] - loperand, sp[1] - roperand
+ int targetOffset = node.findChild(BuildKey::Index).arg.value;
+
+ switch (node.arg.value) {
+ case LEN_OPERATOR_ID:
+ // nsave dp : tmp, -1
+ // labNext :
+ // nadd dp : tmp, 1
+ // peek sp : 0
+ // load dp : tmp
+ // xget
+ // cmp terminator
+ // jne labNext
+ // nadd dp : tmp, 1
+
+ tape.write(ByteCode::NSaveDPN, targetOffset, -1);
+ tape.newLabel(); // declare symbol-end label
+ tape.setLabel(true);
+ tape.write(ByteCode::NAddDPN, targetOffset, 1);
+ tape.write(ByteCode::PeekSI, 0);
+ tape.write(ByteCode::LoadDP, targetOffset);
+ tape.write(ByteCode::XGet);
+ tape.write(ByteCode::CmpR, -1);
+ tape.write(ByteCode::Jne, PseudoArg::CurrentLabel);
+ tape.releaseLabel();
+ tape.write(ByteCode::NAddDPN, targetOffset, 1);
+ break;
+ default:
+ throw InternalError(errFatalError);
}
}
@@ -1252,6 +1372,14 @@ void newArrayOp(CommandTape& tape, BuildNode& node, TapeScope&)
else assert(false);
}
+void fillOp(CommandTape& tape, BuildNode& node, TapeScope&)
+{
+ if (node.arg.reference) {
+ tape.write(ByteCode::FillIR, node.arg.reference);
+ }
+ else tape.write(ByteCode::XFillR);
+}
+
void refParamAssigning(CommandTape& tape, BuildNode& node, TapeScope&)
{
// store si:0
@@ -1302,14 +1430,28 @@ void loadingBynaryLen(CommandTape& tape, BuildNode& node, TapeScope&)
tape.write(ByteCode::NLen, node.arg.value);
}
-void unboxingMessage(CommandTape& tape, BuildNode& node, TapeScope&)
+void loadArgCount(CommandTape& tape, BuildNode& node, TapeScope&)
{
// mlen
// add n:1
+ tape.write(ByteCode::MLen);
+ if (node.arg.value > 0)
+ tape.write(ByteCode::AddN, node.arg.value);
+}
+
+void incIndex(CommandTape& tape, BuildNode& node, TapeScope&)
+{
+ tape.write(ByteCode::AddN, node.arg.value);
+}
+
+void unboxingMessage(CommandTape& tape, BuildNode& node, TapeScope&)
+{
+ int index = node.findChild(BuildKey::Index).arg.value;
+
// dalloc
// sub n:1
// xassignsp
- // alloc i:1
+ // alloc i:1 + index
// store sp:0
// set fp:arg
// swap sp:0
@@ -1320,12 +1462,10 @@ void unboxingMessage(CommandTape& tape, BuildNode& node, TapeScope&)
// assign
// free i:1
- tape.write(ByteCode::MLen);
- tape.write(ByteCode::AddN, 1);
tape.write(ByteCode::DAlloc);
tape.write(ByteCode::SubN, 1);
tape.write(ByteCode::XAssignSP);
- tape.write(ByteCode::AllocI, 1);
+ tape.write(ByteCode::AllocI, 1 + index);
tape.write(ByteCode::StoreSI, 0);
tape.write(ByteCode::SetFP, node.arg.value);
tape.write(ByteCode::SwapSI);
@@ -1366,6 +1506,12 @@ void staticAssigning(CommandTape& tape, BuildNode& node, TapeScope&)
tape.write(ByteCode::StoreR, node.arg.value | mskStaticVariable);
}
+void freeStack(CommandTape& tape, BuildNode& node, TapeScope&)
+{
+ tape.write(ByteCode::Neg);
+ tape.write(ByteCode::DAlloc);
+}
+
inline void includeFrame(CommandTape& tape)
{
tape.write(ByteCode::Include);
@@ -1381,7 +1527,7 @@ ByteCodeWriter::Saver commands[] =
nullptr, openFrame, closeFrame, nilReference, symbolCall, classReference, sendOp, exit,
savingInStack, assigningLocal, getLocal, creatingClass, openStatement, closeStatement, addingBreakpoint, addingBreakpoint,
- creatingStruct, intLiteral, stringLiteral, goingToEOP, getLocalAddredd, copyingLocal, allocatingStack, freeingStack,
+ creatingStruct, intLiteral, stringLiteral, goingToEOP, getLocalAddress, copyingLocal, allocatingStack, freeingStack,
savingNInStack, extCallOp, savingIndex, directCallOp, dispatchOp, intOp, byteArraySOp, copyingToAcc,
getArgument, nullptr, directResend, resendOp, xdispatchOp, boolSOp, intCondOp, charLiteral,
@@ -1396,7 +1542,8 @@ ByteCodeWriter::Saver commands[] =
genericDispatchOp, bynaryArraySOp, binaryArrayOp, shortArrayOp, breakOp, constant, objArrayOp, intArrayOp,
intArraySOp, objArraySOp, copyingLocalArr, extMssgLiteral, loadingBynaryLen, unboxingMessage, loadingSubject, peekArgument,
- terminatorReference, copyingItem, savingLongIndex, longIntCondOp, constantArray, staticAssigning, savingLInStack
+ terminatorReference, copyingItem, savingLongIndex, longIntCondOp, constantArray, staticAssigning, savingLInStack, uintCondOp,
+ uintOp, mssgNameLiteral, vargSOp, loadArgCount, incIndex, freeStack, fillOp
};
inline bool duplicateBreakpoints(BuildNode lastNode)
@@ -1644,6 +1791,8 @@ void ByteCodeWriter :: saveCatching(CommandTape& tape, BuildNode node, TapeScope
retLabel = tape.exchangeFirstsLabel(retLabel);
BuildNode tryNode = node.findChild(BuildKey::Tape);
+ BuildNode catchNode = tryNode.nextNode(BuildKey::Tape);
+ BuildNode finallyNode = catchNode.nextNode(BuildKey::Tape);
saveTape(tape, tryNode, tapeScope, paths, tapeOptMode, false);
// unhook
@@ -1655,10 +1804,17 @@ void ByteCodeWriter :: saveCatching(CommandTape& tape, BuildNode node, TapeScope
// === exit redirect block ===
// restore the original ret label and return the overridden one
retLabel = tape.exchangeFirstsLabel(retLabel);
+
// ret-end-label:
tape.setPredefinedLabel(retLabel);
+
// unhook
tape.write(ByteCode::Unhook);
+
+ // finally-block
+ if (finallyNode != BuildKey::None)
+ saveTape(tape, finallyNode, tapeScope, paths, tapeOptMode, false);
+
tape.write(ByteCode::Jump, PseudoArg::FirstLabel);
// ===========================
@@ -1681,12 +1837,93 @@ void ByteCodeWriter :: saveCatching(CommandTape& tape, BuildNode node, TapeScope
tape.setLabel();
tape.write(ByteCode::Unhook);
- BuildNode catchNode = tryNode.nextNode(BuildKey::Tape);
saveTape(tape, catchNode, tapeScope, paths, tapeOptMode, false);
// eos:
tape.setLabel();
+ tape.releaseLabel(); // release ret-end-label
+
+ // finally-block
+ if (finallyNode != BuildKey::None)
+ saveTape(tape, finallyNode, tapeScope, paths, tapeOptMode, false);
+}
+
+void ByteCodeWriter :: saveFinally(CommandTape& tape, BuildNode node, TapeScope& tapeScope,
+ ReferenceMap& paths, bool tapeOptMode)
+{
+ int retLabel = tape.newLabel(); // declare ret-end-label
+ tape.newLabel(); // declare end-label
+ tape.newLabel(); // declare alternative-label
+
+ tape.write(ByteCode::XHookDPR, node.arg.value, PseudoArg::CurrentLabel, mskLabelRef);
+
+ retLabel = tape.exchangeFirstsLabel(retLabel);
+
+ BuildNode tryNode = node.findChild(BuildKey::Tape);
+ BuildNode finallyNode = tryNode.nextNode(BuildKey::Tape);
+ BuildNode index = node.findChild(BuildKey::Index);
+
+ saveTape(tape, tryNode, tapeScope, paths, tapeOptMode, false);
+
+ // unhook
+ tape.write(ByteCode::Unhook);
+
+ if (finallyNode != BuildKey::None)
+ saveTape(tape, finallyNode, tapeScope, paths, tapeOptMode, false);
+
+ // jump
+ tape.write(ByteCode::Jump, PseudoArg::PreviousLabel);
+
+ // === exit redirect block ===
+ // restore the original ret label and return the overridden one
+ retLabel = tape.exchangeFirstsLabel(retLabel);
+
+ // ret-end-label:
+ tape.setPredefinedLabel(retLabel);
+
+ // unhook
+ tape.write(ByteCode::Unhook);
+
+ // finally-block
+ if (finallyNode != BuildKey::None)
+ saveTape(tape, finallyNode, tapeScope, paths, tapeOptMode, false);
+
+ tape.write(ByteCode::Jump, PseudoArg::FirstLabel);
+ // ===========================
+
+ // catchLabel:
+ tape.setLabel();
+
+ // tstflg elMessage
+ // jeq labSkip
+ // load
+ // peeksi 0
+ // callvi 0
+ // labSkip:
+ // unhook
+ // store fp:index
+
+ tape.newLabel();
+ tape.write(ByteCode::TstFlag, elMessage);
+ tape.write(ByteCode::Jeq, PseudoArg::CurrentLabel);
+ tape.write(ByteCode::Load);
+ tape.write(ByteCode::PeekSI);
+ tape.write(ByteCode::CallVI);
+ tape.setLabel();
+ tape.write(ByteCode::Unhook);
+ tape.write(ByteCode::StoreFI, index.arg.value);
+
+ // finally-block
+ if (finallyNode != BuildKey::None)
+ saveTape(tape, finallyNode, tapeScope, paths, tapeOptMode, false);
+
+ // peek fp:index
+ // throw
+ tape.write(ByteCode::PeekFI, index.arg.value);
+ tape.write(ByteCode::Throw);
+ // eos:
+ tape.setLabel();
tape.releaseLabel(); // release ret-end-label
}
@@ -1782,6 +2019,9 @@ void ByteCodeWriter :: saveVariableInfo(CommandTape& tape, BuildNode node, TapeS
case BuildKey::IntVariableAddress:
saveDebugSymbol(DebugSymbol::IntLocalAddress, current.findChild(BuildKey::Index).arg.value, current.identifier(), tapeScope);
break;
+ case BuildKey::UIntVariableAddress:
+ saveDebugSymbol(DebugSymbol::UIntLocalAddress, current.findChild(BuildKey::Index).arg.value, current.identifier(), tapeScope);
+ break;
case BuildKey::ByteArrayAddress:
saveDebugSymbol(DebugSymbol::ByteArrayAddress, current.findChild(BuildKey::Index).arg.value, current.identifier(), tapeScope);
break;
@@ -1905,9 +2145,6 @@ void ByteCodeWriter :: saveTape(CommandTape& tape, BuildNode node, TapeScope& ta
importTree(tape, current, *tapeScope.scope);
tape.write(ByteCode::ImportOff);
break;
- case BuildKey::NestedClass:
- saveClass(current, tapeScope.scope->moduleScope, tapeScope.scope->minimalArgList, paths, tapeOptMode);
- break;
case BuildKey::BranchOp:
saveBranching(tape, current, tapeScope, paths, tapeOptMode, loopMode);
break;
@@ -1917,6 +2154,9 @@ void ByteCodeWriter :: saveTape(CommandTape& tape, BuildNode node, TapeScope& ta
case BuildKey::CatchOp:
saveCatching(tape, current, tapeScope, paths, tapeOptMode);
break;
+ case BuildKey::FinalOp:
+ saveFinally(tape, current, tapeScope, paths, tapeOptMode);
+ break;
case BuildKey::AltOp:
saveAlternate(tape, current, tapeScope, paths, tapeOptMode);
break;
@@ -2228,13 +2468,23 @@ void ByteCodeWriter :: saveClass(BuildNode node, SectionScopeBase* moduleScope,
ClassInfo::saveStaticFields(&vmtWriter, info.statics);
- if (!testany(info.header.flags, elClassClass | elAbstract)
- && info.attributes.exist({0, ClassAttribute::RuntimeLoadable}))
+ CachedList globalAttributes;
+ if (!testany(info.header.flags, elClassClass | elAbstract)
+ && info.attributes.exist({ 0, ClassAttribute::RuntimeLoadable }))
{
- vmtWriter.writePos(sizeof(unsigned int));
- vmtWriter.writeDWord((unsigned int)ClassAttribute::RuntimeLoadable);
+ globalAttributes.add((unsigned int)ClassAttribute::RuntimeLoadable);
+ }
+ if (info.attributes.exist({ 0, ClassAttribute::Initializer })) {
+ ref_t symbolRef = info.attributes.get({ 0, ClassAttribute::Initializer });
+
+ globalAttributes.add((unsigned int)ClassAttribute::Initializer);
+ globalAttributes.add(symbolRef);
+ }
+
+ vmtWriter.writePos(globalAttributes.count_pos() * sizeof(unsigned int));
+ for (int i = 0; i < globalAttributes.count_pos(); i++) {
+ vmtWriter.writeDWord(globalAttributes.get(i));
}
- else vmtWriter.writePos(0);
}
void ByteCodeWriter :: save(BuildTree& tree, SectionScopeBase* moduleScope,
diff --git a/elenasrc3/engine/bcwriter.h b/elenasrc3/engine/bcwriter.h
index 71097d043a..8642d14f74 100644
--- a/elenasrc3/engine/bcwriter.h
+++ b/elenasrc3/engine/bcwriter.h
@@ -72,6 +72,8 @@ namespace elena_lang
bool tapeOptMode);
void saveCatching(CommandTape& tape, BuildNode node, TapeScope& tapeScope, ReferenceMap& paths,
bool tapeOptMode);
+ void saveFinally(CommandTape& tape, BuildNode node, TapeScope& tapeScope, ReferenceMap& paths,
+ bool tapeOptMode);
void saveAlternate(CommandTape& tape, BuildNode node, TapeScope& tapeScope, ReferenceMap& paths,
bool tapeOptMode);
void saveExternOp(CommandTape& tape, BuildNode node, TapeScope& tapeScope, ReferenceMap& paths,
diff --git a/elenasrc3/engine/buildtree.h b/elenasrc3/engine/buildtree.h
index 215bc53a4e..2654366bb1 100644
--- a/elenasrc3/engine/buildtree.h
+++ b/elenasrc3/engine/buildtree.h
@@ -129,6 +129,14 @@ namespace elena_lang
ConstArrayReference = 0x0064,
StaticAssigning = 0x0065,
SavingLInStack = 0x0066,
+ UIntCondOp = 0x0067,
+ UIntOp = 0x0068,
+ MssgNameLiteral = 0x0069,
+ VArgSOp = 0x006A,
+ LoadArgCount = 0x006B, // argument contains the argument offset
+ IncIndex = 0x006C,
+ FreeVarStack = 0x006D,
+ FillOp = 0x006E, // if the argument is 0 - the size is in sp[0]
MaxOperationalKey = 0x0070,
@@ -146,8 +154,7 @@ namespace elena_lang
Switching = 0x007B,
SwitchOption = 0x007C,
ElseOption = 0x007D,
-
- NestedClass = 0x0080,
+ FinalOp = 0x007E,
VariableInfo = 0x0090,
Variable = 0x0091,
@@ -158,6 +165,7 @@ namespace elena_lang
ByteArrayAddress = 0x0096,
ShortArrayAddress = 0x0097,
IntArrayAddress = 0x0098,
+ UIntVariableAddress = 0x0099,
ParameterInfo = 0x00A0,
Parameter = 0x00A1,
diff --git a/elenasrc3/engine/bytecode.cpp b/elenasrc3/engine/bytecode.cpp
index 72133d24dd..21fc2db7d3 100644
--- a/elenasrc3/engine/bytecode.cpp
+++ b/elenasrc3/engine/bytecode.cpp
@@ -18,7 +18,7 @@ const char* _fnOpcodes[256] =
"class", "save", "throw", "unhook", "loadv", "xcmp", "bload", "wload",
"incude", "exclude", "assign", "mov frm", "loads", "mlen", "dalloc", "xassignsp",
- "dtrans", "xassign", "lload", "convl", "xlcmp", OPCODE_UNKNOWN, OPCODE_UNKNOWN, OPCODE_UNKNOWN,
+ "dtrans", "xassign", "lload", "convl", "xlcmp", "xload", "xlload", OPCODE_UNKNOWN,
"coalesce", "not", "neg", "bread", "lsave", "fsave", "wread", "xjump",
OPCODE_UNKNOWN, OPCODE_UNKNOWN, OPCODE_UNKNOWN, OPCODE_UNKNOWN, OPCODE_UNKNOWN, OPCODE_UNKNOWN, "xget", "xcall",
@@ -36,31 +36,31 @@ const char* _fnOpcodes[256] =
OPCODE_UNKNOWN, OPCODE_UNKNOWN, OPCODE_UNKNOWN, OPCODE_UNKNOWN, OPCODE_UNKNOWN, OPCODE_UNKNOWN, OPCODE_UNKNOWN, OPCODE_UNKNOWN,
OPCODE_UNKNOWN, OPCODE_UNKNOWN, OPCODE_UNKNOWN, OPCODE_UNKNOWN, OPCODE_UNKNOWN, OPCODE_UNKNOWN, OPCODE_UNKNOWN, OPCODE_UNKNOWN,
- OPCODE_UNKNOWN, OPCODE_UNKNOWN, OPCODE_UNKNOWN, OPCODE_UNKNOWN, OPCODE_UNKNOWN, OPCODE_UNKNOWN, OPCODE_UNKNOWN, OPCODE_UNKNOWN,
+ "fabs dp", "fsqrt dp", "fexp dp", "fln dp", "fsin dp", "fcos dp", "farctan dp", "fpi dp",
"set", "set dp", "nlen", "xassign i", "peek", "store", "xswap sp", "swap sp",
"mov mssg", "mov n", "load dp", "xcmp dp", "sub n", "add n", "set fp", "create",
- "copy", "close", "alloc", "free", "and n", "read", "write", "cmp n",
- "nconf dp", "ftrunc dp", "dcopy", "or n", "mul n", OPCODE_UNKNOWN, OPCODE_UNKNOWN, OPCODE_UNKNOWN,
+ "copy", "close", "alloc i", "free", "and n", "read", "write", "cmp n",
+ "nconf dp", "ftrunc dp", "dcopy", "or n", "mul n", "xadd dp", "xset fp", "fround dp",
"save dp", "store fp", "save sp", "store sp", "xflush sp", "get i", "assign i", "xrefresh sp",
- "peek fp", "peek sp", "lsave dp", "lsave sp", "lload dp", OPCODE_UNKNOWN, OPCODE_UNKNOWN, OPCODE_UNKNOWN,
+ "peek fp", "peek sp", "lsave dp", "lsave sp", "lload dp", "xfill", OPCODE_UNKNOWN, OPCODE_UNKNOWN,
"call", "call vt", "jump", "jeq", "jne", "jump vt", "xredirect mssg", "jlt",
- "jge", OPCODE_UNKNOWN, OPCODE_UNKNOWN, OPCODE_UNKNOWN, OPCODE_UNKNOWN, OPCODE_UNKNOWN, OPCODE_UNKNOWN, OPCODE_UNKNOWN,
+ "jge", "jgr", "jle", OPCODE_UNKNOWN, OPCODE_UNKNOWN, OPCODE_UNKNOWN, OPCODE_UNKNOWN, OPCODE_UNKNOWN,
"cmp", "fcmp", "icmp", "tst flag", "tstn", "tst mssg", OPCODE_UNKNOWN, OPCODE_UNKNOWN,
"cmp fp", "cmp sp", OPCODE_UNKNOWN, OPCODE_UNKNOWN, OPCODE_UNKNOWN, "xloadarg sp", "xcreate", "system",
- "fadd dp", "fsub dp", "fmul dp", "fdiv dp", OPCODE_UNKNOWN, OPCODE_UNKNOWN, OPCODE_UNKNOWN, OPCODE_UNKNOWN,
- "iand dp", "ior dp", "ixor dp", "inot dp", "ishl dp", "ishr dp", OPCODE_UNKNOWN, OPCODE_UNKNOWN,
+ "fadd dp", "fsub dp", "fmul dp", "fdiv dp", "udiv dp", OPCODE_UNKNOWN, OPCODE_UNKNOWN, OPCODE_UNKNOWN,
+ "iand dp", "ior dp", "ixor dp", "inot dp", "ishl dp", "ishr dp", OPCODE_UNKNOWN, "selult",
"copy dp", "iadd dp", "isub dp", "imul dp", "idiv dp", "nsave dp", "xhook dp", "xnewn",
"nadd dp", "dcopy dp", "xwrite offs", "xcopy offs", "vjump mssg", "jump mssg", "seleq", "sellt",
"open", "xstore sp", "open header", "mov sp", "new", "newn", "xmov sp", "createn",
- OPCODE_UNKNOWN, "xstore fp", "xdispatch mssg", "dispatch mssg", "vcall mssg", "call mssg", "call extern", OPCODE_UNKNOWN
+ "fillir", "xstore fp", "xdispatch mssg", "dispatch mssg", "vcall mssg", "call mssg", "call extern", OPCODE_UNKNOWN
};
// --- Auxiliary ---
@@ -235,12 +235,12 @@ mssg_t ByteCodeUtil :: resolveMessage(ustr_t messageName, ModuleBase* module, bo
size_t j = (*actionName).findSub(i, ',', end);
IdentifierString temp(actionName.str() + i, j - i);
- references[len++] = module->mapReference(*temp, true);
+ references[len++] = module->mapReference(*temp, readOnlyMode);
i = j + 1;
}
- signature = module->mapSignature(references, len, true);
+ signature = module->mapSignature(references, len, readOnlyMode);
actionName.truncate(index);
}
@@ -253,6 +253,22 @@ mssg_t ByteCodeUtil :: resolveMessage(ustr_t messageName, ModuleBase* module, bo
return encodeMessage(actionRef, argCount, flags);
}
+mssg_t ByteCodeUtil :: resolveMessageName(ustr_t messageName, ModuleBase* module, bool readOnlyMode)
+{
+ pos_t argCount = 0;
+ ref_t flags = 0;
+
+ IdentifierString actionName;
+ parseMessageName(messageName, actionName, flags, argCount);
+
+ ref_t actionRef = module->mapAction(*actionName, 0, readOnlyMode);
+ if (actionRef == 0) {
+ return 0;
+ }
+
+ return encodeMessage(actionRef, argCount, flags);
+}
+
void ByteCodeUtil :: importCommand(ByteCommand& command, SectionScopeBase* target, ModuleBase* importer)
{
if (isRCommand(command.code)) {
@@ -261,6 +277,7 @@ void ByteCodeUtil :: importCommand(ByteCommand& command, SectionScopeBase* targe
ref_t mask = command.arg1 & mskAnyRef;
switch (mask) {
case mskMssgLiteralRef:
+ case mskMssgNameLiteralRef:
command.arg1 = target->importMessageConstant(importer, command.arg1 & ~mskAnyRef) | mask;
break;
case mskExtMssgLiteralRef:
@@ -285,6 +302,39 @@ void ByteCodeUtil :: importCommand(ByteCommand& command, SectionScopeBase* targe
}
}
+void ByteCodeUtil :: generateAutoSymbol(ModuleInfoList& symbolList, ModuleBase* module, MemoryDump& tapeSymbol)
+{
+ MemoryWriter writer(&tapeSymbol);
+
+ pos_t sizePlaceholder = writer.position();
+ writer.writePos(0);
+
+ pos_t command = 0;
+ ustr_t strArg = nullptr;
+
+ ByteCodeUtil::write(writer, ByteCode::OpenIN, 2, 0);
+
+ // generate the preloaded list
+ for (auto it = symbolList.start(); !it.eof(); ++it) {
+ auto info = *it;
+ ustr_t symbolName = info.module->resolveReference(info.reference);
+ if (isWeakReference(symbolName)) {
+ IdentifierString fullName(info.module->name(), symbolName);
+
+ ByteCodeUtil::write(writer, ByteCode::CallR, module->mapReference(*fullName) | mskSymbolRef);
+ }
+ else ByteCodeUtil::write(writer, ByteCode::CallR, module->mapReference(symbolName) | mskSymbolRef);
+ }
+
+ ByteCodeUtil::write(writer, ByteCode::CloseN);
+ ByteCodeUtil::write(writer, ByteCode::Quit);
+
+ pos_t size = writer.position() - sizePlaceholder - sizeof(pos_t);
+
+ writer.seek(sizePlaceholder);
+ writer.writePos(size);
+}
+
// --- CommandTape ---
inline void addJump(int label, int index, CachedMemoryMap& labels,
@@ -423,6 +473,8 @@ inline bool optimizeProcJumps(ByteCodeIterator it)
case ByteCode::Jne:
case ByteCode::Jlt:
case ByteCode::Jge:
+ case ByteCode::Jgr:
+ case ByteCode::Jle:
// remove the label from idle list
idleLabels.exclude(command.arg1);
diff --git a/elenasrc3/engine/bytecode.h b/elenasrc3/engine/bytecode.h
index 0829d3cf99..4b68679299 100644
--- a/elenasrc3/engine/bytecode.h
+++ b/elenasrc3/engine/bytecode.h
@@ -47,6 +47,8 @@ namespace elena_lang
LLoad = 0x1A,
ConvL = 0x1B,
XLCmp = 0x1C,
+ XLoad = 0x1D,
+ XLLoad = 0x1E,
Coalesce = 0x20,
Not = 0x21,
@@ -59,7 +61,16 @@ namespace elena_lang
XGet = 0x2E,
XCall = 0x2F,
- MaxSingleOp = 0x7F,
+ MaxSingleOp = 0x77,
+
+ FAbsDP = 0x78,
+ FSqrtDP = 0x79,
+ FExpDP = 0x7A,
+ FLnDP = 0x7B,
+ FSinDP = 0x7C,
+ FCosDP = 0x7D,
+ FArctanDP = 0x7E,
+ FPiDP = 0x7F,
SetR = 0x80,
SetDP = 0x81,
@@ -91,6 +102,9 @@ namespace elena_lang
DCopy = 0x9A,
OrN = 0x9B,
MulN = 0x9C,
+ XAddDP = 0x9D,
+ XSetFP = 0x9E,
+ FRoundDP = 0x9F,
SaveDP = 0xA0,
StoreFI = 0xA1,
@@ -105,6 +119,7 @@ namespace elena_lang
LSaveDP = 0xAA,
LSaveSI = 0xAB,
LLoadDP = 0xAC,
+ XFillR = 0xAD,
CallR = 0xB0,
CallVI = 0xB1,
@@ -115,6 +130,8 @@ namespace elena_lang
XRedirectM = 0xB6,
Jlt = 0xB7,
Jge = 0xB8,
+ Jgr = 0xB9,
+ Jle = 0xBA,
CmpR = 0xC0,
FCmpN = 0xC1,
@@ -135,6 +152,7 @@ namespace elena_lang
FSubDPN = 0xD1,
FMulDPN = 0xD2,
FDivDPN = 0xD3,
+ UDivDPN = 0xD4,
IAndDPN = 0xD8,
IOrDPN = 0xD9,
@@ -142,6 +160,7 @@ namespace elena_lang
INotDPN = 0xDB,
IShlDPN = 0xDC,
IShrDPN = 0xDD,
+ SelULtRR = 0xDF,
CopyDPN = 0xE0,
IAddDPN = 0xE1,
@@ -168,6 +187,7 @@ namespace elena_lang
NewNR = 0xF5,
XMovSISI = 0xF6,
CreateNR = 0xF7,
+ FillIR = 0xF8,
XStoreFIR = 0xF9,
XDispatchMR = 0xFA,
DispatchMR = 0xFB,
@@ -346,10 +366,12 @@ namespace elena_lang
case ByteCode::CmpR:
case ByteCode::SelEqRR:
case ByteCode::SelLtRR:
+ case ByteCode::SelULtRR:
case ByteCode::PeekR:
case ByteCode::StoreR:
case ByteCode::CreateR:
case ByteCode::XCreateR:
+ case ByteCode::XFillR:
return true;
default:
return false;
@@ -372,8 +394,10 @@ namespace elena_lang
case ByteCode::XDispatchMR:
case ByteCode::SelEqRR:
case ByteCode::SelLtRR:
+ case ByteCode::SelULtRR:
case ByteCode::XHookDPR:
case ByteCode::CreateNR:
+ case ByteCode::FillIR:
return true;
default:
return false;
@@ -425,6 +449,9 @@ namespace elena_lang
static void parseMessageName(ustr_t messageName, IdentifierString& actionName, ref_t& flags, pos_t& argCount);
static mssg_t resolveMessage(ustr_t messageName, ModuleBase* module, bool readOnlyMode);
+ static mssg_t resolveMessageName(ustr_t messageName, ModuleBase* module, bool readOnlyMode);
+
+ static void generateAutoSymbol(ModuleInfoList& symbolList, ModuleBase* module, MemoryDump& tapeSymbol);
};
// --- ByteCodePattern ---
diff --git a/elenasrc3/engine/codescope.cpp b/elenasrc3/engine/codescope.cpp
index 4b4ed55f08..eafbe2721a 100644
--- a/elenasrc3/engine/codescope.cpp
+++ b/elenasrc3/engine/codescope.cpp
@@ -58,6 +58,8 @@ addr_t ReferenceMapper :: resolveReference(ustr_t referenceName, ref_t sectionMa
case mskStaticRef:
case mskStaticVariable:
return _statReferences.get(referenceName);
+ case mskMssgNameLiteralRef:
+ return _subjReferences.get(referenceName);
case mskMssgLiteralRef:
case mskExtMssgLiteralRef:
return _mssgReferences.get(referenceName);
@@ -100,6 +102,9 @@ void ReferenceMapper :: mapReference(ustr_t referenceName, addr_t address, ref_t
case mskExtMssgLiteralRef:
_mssgReferences.add(referenceName, address);
break;
+ case mskMssgNameLiteralRef:
+ _subjReferences.add(referenceName, address);
+ break;
case mskVMTRef:
_dataReferences.add(referenceName, address);
break;
diff --git a/elenasrc3/engine/codescope.h b/elenasrc3/engine/codescope.h
index 2d5f5bdc65..7a880fa560 100644
--- a/elenasrc3/engine/codescope.h
+++ b/elenasrc3/engine/codescope.h
@@ -30,7 +30,7 @@ namespace elena_lang
AddressMap _constReferences, _numberReferences, _literalReferences, _characterReferences;
AddressMap _longNumberReferences, _realNumberReferences;
AddressMap _wideReferences;
- AddressMap _mssgReferences;
+ AddressMap _mssgReferences, _subjReferences;
AddressMap _dataReferences;
AddressMap _statReferences;
@@ -61,6 +61,11 @@ namespace elena_lang
void addLazyReference(LazyReferenceInfo info) override;
+ void clearLazyReferences()
+ {
+ _lazyReferences.clear();
+ }
+
ReferenceMapper(ExternalMapper* externalMapper = nullptr) :
_symbolReferences(INVALID_ADDR),
_exportReferences(INVALID_ADDR),
@@ -72,6 +77,7 @@ namespace elena_lang
_realNumberReferences(INVALID_ADDR),
_wideReferences(INVALID_ADDR),
_mssgReferences(INVALID_ADDR),
+ _subjReferences(INVALID_ADDR),
_dataReferences(INVALID_ADDR),
_statReferences(INVALID_ADDR),
_actionNames(0),
diff --git a/elenasrc3/engine/core.h b/elenasrc3/engine/core.h
index 56751f6d2b..b66c258fa4 100644
--- a/elenasrc3/engine/core.h
+++ b/elenasrc3/engine/core.h
@@ -213,7 +213,7 @@ namespace elena_lang
struct SymbolList
{
size_t length;
- // NOTE : the array size if fictinal - it can contain the number of entried defined in the first field
+ // NOTE : the array size is not valud - the actual number of entries defined in the first field
Entry entries[1];
SymbolList()
diff --git a/elenasrc3/engine/dfa.h b/elenasrc3/engine/dfa.h
index f19521ca2d..033d286556 100644
--- a/elenasrc3/engine/dfa.h
+++ b/elenasrc3/engine/dfa.h
@@ -15,7 +15,7 @@ namespace elena_lang
{
".????????BB??B??????????????????BDFLND??DDDDDDDHEEEEEEEEEEDDDD?D?CCCCCCCCCCCCCCCCCCCCCCCCCCQ?DDC?CCCCCCCCCCCCCCCCCCCCCCCCCCDDDD?",
"*********BB*********************B***********************************************************************************************",
- "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACCCCCCCCCCAAAAAAACCCCCCCCCCCCCCCCCCCCCCCCCCAAAACACCCCCCCCCCCCCCCCCCCCCCCCCCAAAAA",
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAACCCCCCCCCCAAAAAAACCCCCCCCCCCCCCCCCCCCCCCCCCAAAACACCCCCCCCCCCCCCCCCCCCCCCCCCAAAAA",
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAADDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEEEEEEEEEEAAAAAAAKKKKKKAAAAAAAAAAAAAAAAAAAAAAAAAAEEEEEEEJAAAAAAAAAAAAAAAAAAAAAAA",
"?FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFGFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
@@ -25,7 +25,7 @@ namespace elena_lang
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
"????????????????????????????????????????????????KKKKKKKKKK???????KKKKKK?????????????????????????????????J???????????????????????",
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACCCCCCCCCCCCCCCCCCCCCCCCCCAAAACACCCCCCCCCCCCCCCCCCCCCCCCCCAAAAA",
- "????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????",
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA???????????A?????MMMMMMMMMMMMMMMMMMMMMMMMMM??????MMMMMMMMMMMMMMMMMMMMMMMMMM?????",
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANNNNNNNNNN?A?????NNNNNNNNNNNNNNNNNNNNNNNNNN??????NNNNNNNNNNNNNNNNNNNNNNNNNN?????",
"????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????",
"????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????",
diff --git a/elenasrc3/engine/elena.h b/elenasrc3/engine/elena.h
index bd605de572..c9db4c9366 100644
--- a/elenasrc3/engine/elena.h
+++ b/elenasrc3/engine/elena.h
@@ -335,8 +335,15 @@ namespace elena_lang
module = nullptr;
reference = 0;
}
+ ModuleInfo(ModuleBase* module, ref_t reference)
+ {
+ this->module = module;
+ this->reference = reference;
+ }
};
+ typedef List ModuleInfoList;
+
class LibraryLoaderListenerBase
{
public:
@@ -365,6 +372,8 @@ namespace elena_lang
virtual ModuleInfo getDebugModule(ReferenceInfo referenceInfo, bool silentMode) = 0;
virtual void resolvePath(ustr_t ns, PathString& path) = 0;
+
+ virtual void loadDistributedSymbols(ustr_t virtualSymbolName, ModuleInfoList& list) = 0;
};
class LibraryProviderBase
@@ -486,6 +495,12 @@ namespace elena_lang
virtual void writeJgeBack(pos_t label, MemoryWriter& writer) = 0;
virtual void writeJgeForward(pos_t label, MemoryWriter& writer, int byteCodeOffset) = 0;
+ virtual void writeJleBack(pos_t label, MemoryWriter& writer) = 0;
+ virtual void writeJleForward(pos_t label, MemoryWriter& writer, int byteCodeOffset) = 0;
+
+ virtual void writeJgrBack(pos_t label, MemoryWriter& writer) = 0;
+ virtual void writeJgrForward(pos_t label, MemoryWriter& writer, int byteCodeOffset) = 0;
+
virtual void writeLabelAddress(pos_t label, MemoryWriter& writer, ref_t mask) = 0;
};
@@ -498,7 +513,8 @@ namespace elena_lang
ImageProviderBase* imageProvider,
ReferenceHelperBase* helper,
LabelHelperBase* lh,
- JITSettings settings) = 0;
+ JITSettings settings,
+ bool virtualMode) = 0;
virtual bool isWithDebugInfo() = 0;
@@ -557,7 +573,9 @@ namespace elena_lang
virtual void resolveLabelAddress(MemoryWriter* writer, ref_t mask, pos_t position, bool virtualMode) = 0;
- virtual void populatePreloaded(uintptr_t env, uintptr_t eh_table, uintptr_t gc_table) = 0;
+ virtual void populatePreloaded(uintptr_t eh_table) = 0;
+
+ virtual void* getSystemEnv() = 0;
virtual void updateEnvironment(MemoryBase* rdata, pos_t staticCounter, bool virtualMode) = 0;
virtual void updateVoidObject(MemoryBase* rdata, addr_t superAddress, bool virtualMode) = 0;
@@ -813,6 +831,44 @@ namespace elena_lang
else return false;
}
+ void pathToName(path_t path)
+ {
+ char buf[IDENTIFIER_LEN];
+ size_t bufLen = IDENTIFIER_LEN;
+
+ while (!path.empty()) {
+ if (!empty())
+ append('\'');
+
+ size_t pos = path.find(PATH_SEPARATOR);
+ if (pos != NOTFOUND_POS) {
+ bufLen = IDENTIFIER_LEN;
+ path.copyTo(buf, pos, bufLen);
+
+ append(buf, bufLen);
+ path += pos + 1u;
+ }
+ else {
+ pos = path.findLast('.');
+ if (pos == NOTFOUND_POS)
+ pos = path.length();
+
+ bufLen = IDENTIFIER_LEN;
+ path.copyTo(buf, pos, bufLen);
+
+ // replace dots with apostrophes
+ for (size_t i = 0; i < bufLen; i++) {
+ if (buf[i] == '.')
+ buf[i] = '\'';
+ }
+
+ append(buf, bufLen);
+
+ break;
+ }
+ }
+ }
+
void trimLastSubNs()
{
size_t index = (**this).findLast('\'', 0);
@@ -886,44 +942,6 @@ namespace elena_lang
}
}
- void pathToName(path_t path)
- {
- char buf[IDENTIFIER_LEN];
- size_t bufLen = IDENTIFIER_LEN;
-
- while (!path.empty()) {
- if (!empty())
- append('\'');
-
- size_t pos = path.find(PATH_SEPARATOR);
- if (pos != NOTFOUND_POS) {
- bufLen = IDENTIFIER_LEN;
- path.copyTo(buf, pos, bufLen);
-
- append(buf, bufLen);
- path += pos + 1u;
- }
- else {
- pos = path.findLast('.');
- if (pos == NOTFOUND_POS)
- pos = path.length();
-
- bufLen = IDENTIFIER_LEN;
- path.copyTo(buf, pos, bufLen);
-
- // replace dots with apostrophes
- for (size_t i = 0; i < bufLen; i++) {
- if (buf[i] == '.')
- buf[i] = '\'';
- }
-
- append(buf, bufLen);
-
- break;
- }
- }
- }
-
bool combine(ustr_t name)
{
if (!name.empty()) {
@@ -980,6 +998,7 @@ namespace elena_lang
{
int offset;
TypeInfo typeInfo;
+ bool readOnly;
};
// --- StaticFieldInfo ---
diff --git a/elenasrc3/engine/elenaconst.h b/elenasrc3/engine/elenaconst.h
index f13cb2c54e..25a03a4d1c 100644
--- a/elenasrc3/engine/elenaconst.h
+++ b/elenasrc3/engine/elenaconst.h
@@ -12,34 +12,34 @@
namespace elena_lang
{
// --- Common ELENA Engine constants ---
- #define ENGINE_MAJOR_VERSION 6 // ELENA Engine version
- #define ENGINE_MINOR_VERSION 0
+ #define ENGINE_MAJOR_VERSION 6 // ELENA Engine version
+ #define ENGINE_MINOR_VERSION 0
- constexpr auto LINE_LEN = 0x1000; // the maximal source line length
- constexpr auto IDENTIFIER_LEN = 0x0300; // the maximal identifier length
- constexpr auto MESSAGE_LEN = 0x200; // the maximal message length
+ constexpr auto LINE_LEN = 0x1000; // the maximal source line length
+ constexpr auto IDENTIFIER_LEN = 0x0300; // the maximal identifier length
+ constexpr auto MESSAGE_LEN = 0x200; // the maximal message length
// --- ELENA Standart message constants ---
- constexpr auto ACTION_ORDER = 9;
+ constexpr auto ACTION_ORDER = 9;
- constexpr auto ACTION_MASK = 0x1C0u;
- constexpr auto MESSAGE_FLAG_MASK = 0x1E0u;
+ constexpr auto ACTION_MASK = 0x1C0u;
+ constexpr auto MESSAGE_FLAG_MASK = 0x1E0u;
- constexpr auto STATIC_MESSAGE = 0x100u;
- constexpr auto FUNCTION_MESSAGE = 0x020u; // indicates it is an invoke message (without target variable in the call stack)
- constexpr auto CONVERSION_MESSAGE = 0x040u;
- constexpr auto VARIADIC_MESSAGE = 0x080u;
- constexpr auto PROPERTY_MESSAGE = 0x0C0u;
- constexpr auto PREFIX_MESSAGE_MASK = 0x0C0u; // HOTFIX : is used to correctly identify VARIADIC_MESSAGE or PROPERTY_MESSAGE
+ constexpr auto STATIC_MESSAGE = 0x100u;
+ constexpr auto FUNCTION_MESSAGE = 0x020u; // indicates it is an invoke message (without target variable in the call stack)
+ constexpr auto CONVERSION_MESSAGE = 0x040u;
+ constexpr auto VARIADIC_MESSAGE = 0x080u;
+ constexpr auto PROPERTY_MESSAGE = 0x0C0u;
+ constexpr auto PREFIX_MESSAGE_MASK = 0x0C0u; // HOTFIX : is used to correctly identify VARIADIC_MESSAGE or PROPERTY_MESSAGE
- constexpr auto ARG_COUNT = 0x01Eu;
- constexpr auto ARG_MASK = 0x01Fu;
+ constexpr auto ARG_COUNT = 0x01Eu;
+ constexpr auto ARG_MASK = 0x01Fu;
// --- ELENA Module structure constants ---
- constexpr auto ELENA_SIGNITURE = "ELENA."; // the stand alone image
- constexpr auto ELENA_VM_SIGNITURE = "VM.ELENA."; // the stand alone image
- constexpr auto MODULE_SIGNATURE = "ELENA.0601"; // the module version
- constexpr auto DEBUG_MODULE_SIGNATURE = "ED.06";
+ constexpr auto ELENA_SIGNITURE = "ELENA."; // the stand alone image
+ constexpr auto ELENA_VM_SIGNITURE = "VM.ELENA."; // the stand alone image
+ constexpr auto MODULE_SIGNATURE = "ELENA.0601"; // the module version
+ constexpr auto DEBUG_MODULE_SIGNATURE = "ED.06";
// --- ELENA core module names ---
constexpr auto CORE_ALIAS = "core"; // Core functionality
@@ -54,6 +54,7 @@ namespace elena_lang
constexpr auto NAMESPACES_SECTION = "$namespaces";
constexpr auto IMPORTS_SECTION = "$import";
constexpr auto EXTENSION_SECTION = "#extensions";
+ constexpr auto INITIALIZER_SECTION = "#initializer";
constexpr auto NAMESPACE_REF = "$namespace";
@@ -65,64 +66,69 @@ namespace elena_lang
constexpr auto TEMPLATE_PREFIX_NS = "'$auto'";
constexpr auto TEMPLATE_PREFIX_NS_ENCODED = "@$auto@";
constexpr auto FORWARD_PREFIX_NS = "$forwards'";
+ constexpr auto AUTO_SYMBOL_PREFIX = "@autosymbol";
constexpr auto INLINE_CLASSNAME = "$inline"; // nested class generic name
constexpr auto PREDEFINED_MAP = "$forwards'meta$predefined";
constexpr auto ATTRIBUTES_MAP = "$forwards'meta$attributes";
constexpr auto OPERATION_MAP = "$forwards'meta$statementTemplates";
constexpr auto ALIASES_MAP = "$forwards'meta$aliasTypes";
- constexpr auto STARTUP_LIST = "$forwards'meta$startUpSymbols";
- constexpr auto STARTUP_ENTRY = "$forwards'startUpSymbols";
-
- constexpr auto VM_TAPE = "$elena'meta$startUpTape";
-
- constexpr auto PROGRAM_ENTRY = "$forwards'program"; // used by the linker to define the debug entry
-
- constexpr auto RETVAL_ARG = "$retVal";
- constexpr auto PARENT_VAR = "$parent";
- constexpr auto OWNER_VAR = "$owner";
-
- constexpr auto SYSTEM_FORWARD = "$system_entry"; // the system entry
- constexpr auto SUPER_FORWARD = "$super"; // the common class predecessor
- constexpr auto INTLITERAL_FORWARD = "$int"; // the int literal
- constexpr auto LONGLITERAL_FORWARD = "$long"; // the long literal
- constexpr auto REALLITERAL_FORWARD = "$real"; // the real literal
- constexpr auto INT8LITERAL_FORWARD = "$byte"; // the int literal
- constexpr auto INT16LITERAL_FORWARD = "$short"; // the int literal
- constexpr auto LITERAL_FORWARD = "$string"; // the string literal
- constexpr auto WIDELITERAL_FORWARD = "$wide"; // the wide string literal
- constexpr auto CHAR_FORWARD = "$char"; // the char literal
- constexpr auto BOOL_FORWARD = "$boolean"; // the boolean class
- constexpr auto TRUE_FORWARD = "$true"; // the true boolean value
- constexpr auto FALSE_FORWARD = "$false"; // the false boolean value
- constexpr auto WRAPPER_FORWARD = "$ref"; // the wrapper template
- constexpr auto ARRAY_FORWARD = "$array"; // the array template
- constexpr auto VARIADIC_ARRAY_FORWARD = "$varray"; // the array template
- constexpr auto MESSAGE_FORWARD = "$message"; // the message class
- constexpr auto EXT_MESSAGE_FORWARD = "$ext_message"; // the extension message class
- constexpr auto CLOSURE_FORWARD = "$closure"; // the closure template class
- constexpr auto DWORD_FORWARD = "$dword"; // the dword wrapper
- constexpr auto PTR_FORWARD = "$ptr"; // the dword wrapper
- constexpr auto LAZY_FORWARD = "$lazy";
+ constexpr auto STARTUP_ENTRY = "$auto'startUpSymbol";
+
+ constexpr auto VM_TAPE = "$elena'meta$startUpTape";
+
+ constexpr auto PROGRAM_ENTRY = "$forwards'program"; // used by the linker to define the debug entry
+
+ constexpr auto RETVAL_ARG = "$retVal";
+ constexpr auto PARENT_VAR = "$parent";
+ constexpr auto OWNER_VAR = "$owner";
+
+ constexpr auto SYSTEM_FORWARD = "$system_entry"; // the system entry
+ constexpr auto SUPER_FORWARD = "$super"; // the common class predecessor
+ constexpr auto INTLITERAL_FORWARD = "$int"; // the int literal
+ constexpr auto LONGLITERAL_FORWARD = "$long"; // the long literal
+ constexpr auto REALLITERAL_FORWARD = "$real"; // the real literal
+ constexpr auto INT8LITERAL_FORWARD = "$byte"; // the int literal
+ constexpr auto INT16LITERAL_FORWARD = "$short"; // the int literal
+ constexpr auto LITERAL_FORWARD = "$string"; // the string literal
+ constexpr auto WIDELITERAL_FORWARD = "$wide"; // the wide string literal
+ constexpr auto CHAR_FORWARD = "$char"; // the char literal
+ constexpr auto BOOL_FORWARD = "$boolean"; // the boolean class
+ constexpr auto TRUE_FORWARD = "$true"; // the true boolean value
+ constexpr auto FALSE_FORWARD = "$false"; // the false boolean value
+ constexpr auto WRAPPER_FORWARD = "$ref"; // the wrapper template
+ constexpr auto ARRAY_FORWARD = "$array"; // the array template
+ constexpr auto VARIADIC_ARRAY_FORWARD = "$varray"; // the array template
+ constexpr auto MESSAGE_FORWARD = "$message"; // the message class
+ constexpr auto MESSAGE_NAME_FORWARD = "$subject"; // the message class
+ constexpr auto EXT_MESSAGE_FORWARD = "$ext_message"; // the extension message class
+ constexpr auto CLOSURE_FORWARD = "$closure"; // the closure template class
+ constexpr auto TUPLE_FORWARD = "$tuple"; // the closure template class
+ constexpr auto UINT_FORWARD = "$uint"; // the uint wrapper
+ constexpr auto PTR_FORWARD = "$ptr"; // the ptr wrapper
+ constexpr auto LAZY_FORWARD = "$lazy";
+ constexpr auto PRELOADED_FORWARD = "preloadedSymbols";
+ constexpr auto START_FORWARD = "$symbol_entry";
// --- ELENA section prefixes
- constexpr auto META_PREFIX = "meta$";
- constexpr auto INLINE_PREFIX = "inline$";
- constexpr auto INLINE_PROPERTY_PREFIX = "prop$";
+ constexpr auto META_PREFIX = "meta$";
+ constexpr auto INLINE_PREFIX = "inline$";
+ constexpr auto INLINE_PROPERTY_PREFIX = "prop$";
+ constexpr auto AUTO_GENERATED_PREFIX = "generated$";
// --- ELENA class prefixes / postfixes ---
- constexpr auto PRIVATE_PREFIX_NS = "'$private'";
- constexpr auto INTERNAL_PREFIX_NS = "'$intern'";
+ constexpr auto PRIVATE_PREFIX_NS = "'$private'";
+ constexpr auto INTERNAL_PREFIX_NS = "'$intern'";
- constexpr auto TEMPLATE_PREFIX = "'$auto";
- constexpr auto PRIVATE_PREFIX = "'$private";
- constexpr auto INTERNAL_PREFIX = "'$intern";
+ constexpr auto TEMPLATE_PREFIX = "'$auto";
+ constexpr auto PRIVATE_PREFIX = "'$private";
+ constexpr auto INTERNAL_PREFIX = "'$intern";
- constexpr auto CLASSCLASS_POSTFIX = "#class";
- constexpr auto CONST_POSTFIX = "#const";
- constexpr auto STATICFIELD_POSTFIX = "#static";
- constexpr auto GENERIC_PREFIX = "#generic";
- constexpr auto PARAMETER_NAMES = "parameter_names";
+ constexpr auto CLASSCLASS_POSTFIX = "#class";
+ constexpr auto CONST_POSTFIX = "#const";
+ constexpr auto STATICFIELD_POSTFIX = "#static";
+ constexpr auto GENERIC_PREFIX = "#generic";
+ constexpr auto PARAMETER_NAMES = "parameter_names";
// --- ELENA verb messages ---
constexpr auto DISPATCH_MESSAGE = "#dispatch";
@@ -148,6 +154,7 @@ namespace elena_lang
constexpr auto NOT_MESSAGE = "Inverted";
constexpr auto NEGATE_MESSAGE = "Negative";
constexpr auto VALUE_MESSAGE = "Value";
+ constexpr auto ITEM_MESSAGE = "Value";
constexpr auto NOTEQUAL_MESSAGE = "notequal";
constexpr auto LESS_MESSAGE = "less";
constexpr auto NOTLESS_MESSAGE = "notless";
@@ -180,6 +187,7 @@ namespace elena_lang
constexpr ref_t elWithVariadics = 0x00400000;
constexpr ref_t elWithCustomDispatcher = 0x00800000;
constexpr ref_t elWithGenerics = 0x02000000;
+ constexpr ref_t elVirtualVMT = 0x04000000;
constexpr ref_t elTemplatebased = 0x40000000;
constexpr ref_t elDebugMask = 0x001F0000;
@@ -264,6 +272,7 @@ namespace elena_lang
ByteArrayAddress = 0x0105,
ShortArrayAddress = 0x0106,
IntArrayAddress = 0x0107,
+ UIntLocalAddress = 0x0108,
Parameter = 0x0200,
IntParameterAddress = 0x0202,
@@ -299,6 +308,7 @@ namespace elena_lang
SealedStatic = 0x908,
SingleDispatch = 0xA09,
ExtOverloadList = 0x90A,
+ Initializer = 0x10B,
};
// === Reference constants ====
@@ -342,6 +352,8 @@ namespace elena_lang
constexpr ref_t mskRealLiteralRef = 0x21000000u;
constexpr ref_t mskExtMssgLiteralRef = 0x22000000u;
constexpr ref_t mskPSTRRef = 0x23000000u;
+ constexpr ref_t mskAutoSymbolRef = 0x24000000u;
+ constexpr ref_t mskMssgNameLiteralRef = 0x25000000u;
// --- Image reference types ---
constexpr ref_t mskCodeRef = 0x01000000u;
diff --git a/elenasrc3/engine/elenamachine.cpp b/elenasrc3/engine/elenamachine.cpp
index 21b0f45e46..c86deffd3a 100644
--- a/elenasrc3/engine/elenamachine.cpp
+++ b/elenasrc3/engine/elenamachine.cpp
@@ -123,7 +123,7 @@ unsigned int SystemRoutineProvider :: GetRandomNumber(SeedStruct& seed)
// --- ELENAMachine ---
-int ELENAMachine :: execute(SystemEnv* env, void* symbolListEntry)
+int ELENAMachine :: execute(SystemEnv* env, void* entryAddress)
{
Entry entry;
entry.address = env->bc_invoker;
@@ -133,7 +133,7 @@ int ELENAMachine :: execute(SystemEnv* env, void* symbolListEntry)
int retVal = 0;
try
{
- retVal = entry.evaluate(symbolListEntry, nullptr);
+ retVal = entry.evaluate(entryAddress, nullptr);
}
catch (InternalError&)
{
diff --git a/elenasrc3/engine/gcroutines.cpp b/elenasrc3/engine/gcroutines.cpp
index 2a58918022..f471cb191b 100644
--- a/elenasrc3/engine/gcroutines.cpp
+++ b/elenasrc3/engine/gcroutines.cpp
@@ -101,6 +101,10 @@ inline void YGCollect(GCRoot* root, size_t start, size_t end, ObjectPage*& shado
uintptr_t new_ptr = 0;
GCRoot current;
+ if (size == 0x28) {
+ size = 0x28;
+ }
+
//printf("YGCollect %llx,%llx\n", (long long)ptr, (long long)size);
// ; collect roots
diff --git a/elenasrc3/engine/jitcompiler.cpp b/elenasrc3/engine/jitcompiler.cpp
index f2de410143..d2d669d62e 100644
--- a/elenasrc3/engine/jitcompiler.cpp
+++ b/elenasrc3/engine/jitcompiler.cpp
@@ -22,7 +22,7 @@ CodeGenerator _codeGenerators[256] =
loadOp, loadOp, loadOp, loadOp, loadOp, loadOp, loadOp, loadOp,
loadOp, loadOp, loadOp, loadOp, loadOp, loadOp, loadOp, loadOp,
- loadOp, loadOp, loadOp, loadOp, loadOp, loadNop, loadNop, loadNop,
+ loadOp, loadOp, loadOp, loadOp, loadOp, loadOp, loadOp, loadNop,
loadOp, loadOp, loadOp, loadOp, loadOp, loadOp, loadOp, loadOp,
loadNop, loadNop, loadNop, loadNop, loadNop, loadNop, loadOp, loadOp,
@@ -40,31 +40,31 @@ CodeGenerator _codeGenerators[256] =
loadNop, loadNop, loadNop, loadNop, loadNop, loadNop, loadNop, loadNop,
loadNop, loadNop, loadNop, loadNop, loadNop, loadNop, loadNop, loadNop,
- loadNop, loadNop, loadNop, loadNop, loadNop, loadNop, loadNop, loadNop,
+ loadFrameDispOp, loadFrameDispOp, loadFrameDispOp, loadFrameDispOp, loadFrameDispOp, loadFrameDispOp, loadFrameDispOp, loadFrameDispOp,
loadROp, loadFrameDispOp, loadLenOp, loadIndexOp, loadROp, loadROp, loadStackIndexOp, loadStackIndexOp,
loadMOp, loadNOp, loadFrameDispOp, loadFrameDispOp, loadNOp, loadNOp, loadFrameIndexOp, loadROp,
loadNOp, compileClose, loadIndexOp, loadIndexOp, loadNOp, loadNOp, loadNOp, loadNOp,
- loadFrameDispOp, loadFrameDispOp, loadNOp, loadNOp, loadNOp, loadNop, loadNop, loadNop,
+ loadFrameDispOp, loadFrameDispOp, loadNOp, loadNOp, loadNOp, loadFrameDispOp, loadFrameIndexOp, loadFrameDispOp,
loadFrameDispOp, loadFrameIndexOp, loadStackIndexOp, loadStackIndexOp, loadStackIndexOp, loadFieldIndexOp, loadFieldIndexOp, loadStackIndexOp,
- loadFrameIndexOp, loadStackIndexOp, loadFrameDispOp, loadStackIndexOp, loadFrameDispOp, loadNop, loadNop, loadNop,
+ loadFrameIndexOp, loadStackIndexOp, loadFrameDispOp, loadStackIndexOp, loadFrameDispOp, loadROp, loadNop, loadNop,
loadCallROp, loadVMTIndexOp, compileJump, compileJeq, compileJne, loadVMTIndexOp, loadMOp, compileJlt,
- compileJge, loadNop, loadNop, loadNop, loadNop, loadNop, loadNop, loadNop,
+ compileJge, compileJgr, compileJle, loadNop, loadNop, loadNop, loadNop, loadNop,
loadROp, loadIOp, loadIOp, loadNOp, loadNOp, loadMOp, loadNop, loadNop,
loadFrameIndexOp, loadStackIndexOp, loadNop, loadNop, loadNop, loadArgIndexOp, loadROp, loadSysOp,
- loadDPNOp, loadDPNOp, loadDPNOp, loadDPNOp, loadNop, loadNop, loadNop, loadNop,
- loadDPNOp, loadDPNOp, loadDPNOp, loadDPNOp, loadDPNOp, loadDPNOp, loadNop, loadNop,
+ loadDPNOp, loadDPNOp, loadDPNOp, loadDPNOp, loadDPNOp, loadNop, loadNop, loadNop,
+ loadDPNOp, loadDPNOp, loadDPNOp, loadDPNOp, loadDPNOp, loadDPNOp, loadNop, loadRROp,
loadDPNOp, loadDPNOp, loadDPNOp, loadDPNOp, loadDPNOp, loadDPNOp2, compileHookDPR, loadNewOp,
loadDPNOp, loadDPNOp, loadONOp, loadONOp, loadVMTROp, loadMROp, loadRROp, loadRROp,
compileOpen, loadStackIndexROp, compileOpen, loadStackIndexFrameIndexOp, loadNewOp, loadNewNOp, loadStackIndexIndexOp, loadCreateNOp,
- loadNop, loadFrameIndexROp, compileDispatchMR, compileDispatchMR, loadVMTROp, loadMROp, loadCallOp, loadNop,
+ loadIROp, loadFrameIndexROp, compileDispatchMR, compileDispatchMR, loadVMTROp, loadMROp, loadCallOp, loadNop,
};
// preloaded gc routines
@@ -90,7 +90,7 @@ constexpr ref_t coreFunctions[coreFunctionNumber] =
};
// preloaded bc commands
-constexpr size_t bcCommandNumber = 132;
+constexpr size_t bcCommandNumber = 149;
constexpr ByteCode bcCommands[bcCommandNumber] =
{
ByteCode::MovEnv, ByteCode::SetR, ByteCode::SetDP, ByteCode::CloseN, ByteCode::AllocI,
@@ -119,7 +119,10 @@ constexpr ByteCode bcCommands[bcCommandNumber] =
ByteCode::XJump, ByteCode::MLen, ByteCode::DAlloc, ByteCode::XAssignSP, ByteCode::DTrans,
ByteCode::XAssign, ByteCode::OrN, ByteCode::LSaveDP, ByteCode::LLoad, ByteCode::LSaveSI,
ByteCode::ConvL, ByteCode::XLCmp, ByteCode::System, ByteCode::XCreateR, ByteCode::MulN,
- ByteCode::LLoadDP, ByteCode::XLoadArgSI,
+ ByteCode::LLoadDP, ByteCode::XLoadArgSI, ByteCode::XLoad, ByteCode::XLLoad, ByteCode::XSetFP,
+ ByteCode::XAddDP, ByteCode::SelULtRR, ByteCode::UDivDPN, ByteCode::FRoundDP, ByteCode::FAbsDP,
+ ByteCode::FSqrtDP, ByteCode::FExpDP, ByteCode::FLnDP, ByteCode::FSinDP, ByteCode::FCosDP,
+ ByteCode::FArctanDP, ByteCode::FPiDP, ByteCode::FillIR, ByteCode::XFillR
};
void elena_lang :: writeCoreReference(JITCompilerScope* scope, ref_t reference,
@@ -134,7 +137,7 @@ void elena_lang :: writeCoreReference(JITCompilerScope* scope, ref_t reference,
case mskMDataRef32:
case mskStatDataRef32:
scope->helper->writeVAddress32(*scope->codeWriter->Memory(), scope->codeWriter->position(),
- (addr_t)scope->compiler->_preloaded.get(reference & ~mskAnyRef) & ~mskAnyRef,
+ (addr_t)scope->compiler->_preloaded.get(reference & ~mskAnyRef),
*(pos_t*)((char*)code + disp), mask);
break;
case mskCodeRef64:
@@ -142,13 +145,13 @@ void elena_lang :: writeCoreReference(JITCompilerScope* scope, ref_t reference,
case mskMDataRef64:
case mskStatDataRef64:
scope->helper->writeVAddress64(*scope->codeWriter->Memory(), scope->codeWriter->position(),
- (addr_t)scope->compiler->_preloaded.get(reference & ~mskAnyRef) & ~mskAnyRef,
+ (addr_t)scope->compiler->_preloaded.get(reference & ~mskAnyRef),
*(pos_t*)((char*)code + disp), mask);
break;
case mskCodeRelRef32:
case mskDataRelRef32:
scope->helper->writeRelAddress32(*scope->codeWriter->Memory(), scope->codeWriter->position(),
- (addr_t)scope->compiler->_preloaded.get(reference & ~mskAnyRef) & ~mskAnyRef,
+ (addr_t)scope->compiler->_preloaded.get(reference & ~mskAnyRef),
*(pos_t*)((char*)code + disp), mask);
break;
case mskImportRef32:
@@ -185,12 +188,12 @@ void elena_lang :: writeCoreReference(JITCompilerScope* scope, ref_t reference,
break;
case mskRDataRef32:
scope->helper->writeVAddress32(*scope->codeWriter->Memory(), scope->codeWriter->position(),
- (addr_t)scope->compiler->_preloaded.get(reference & ~mskAnyRef) & ~mskAnyRef,
+ (addr_t)scope->compiler->_preloaded.get(reference & ~mskAnyRef),
*(pos_t*)((char*)code + disp), mask);
break;
case mskRDataRef64:
scope->helper->writeVAddress64(*scope->codeWriter->Memory(), scope->codeWriter->position(),
- (addr_t)scope->compiler->_preloaded.get(reference & ~mskAnyRef) & ~mskAnyRef,
+ (addr_t)scope->compiler->_preloaded.get(reference & ~mskAnyRef),
*(pos_t*)((char*)code + disp), mask);
break;
case mskDataRef32Lo:
@@ -199,7 +202,7 @@ void elena_lang :: writeCoreReference(JITCompilerScope* scope, ref_t reference,
case mskCodeRef32Lo:
case mskStatDataRef32Lo:
scope->helper->writeVAddress32Lo(*scope->codeWriter->Memory(), scope->codeWriter->position(),
- (addr_t)scope->compiler->_preloaded.get(reference & ~mskAnyRef) & ~mskAnyRef,
+ (addr_t)scope->compiler->_preloaded.get(reference & ~mskAnyRef),
0, mask);
break;
case mskDataRef32Hi:
@@ -208,21 +211,21 @@ void elena_lang :: writeCoreReference(JITCompilerScope* scope, ref_t reference,
case mskCodeRef32Hi:
case mskStatDataRef32Hi:
scope->helper->writeVAddress32Hi(*scope->codeWriter->Memory(), scope->codeWriter->position(),
- (addr_t)scope->compiler->_preloaded.get(reference & ~mskAnyRef) & ~mskAnyRef,
+ (addr_t)scope->compiler->_preloaded.get(reference & ~mskAnyRef),
0, mask);
break;
case mskDataDisp32Hi:
case mskRDataDisp32Hi:
case mskCodeDisp32Hi:
scope->helper->writeDisp32Hi(*scope->codeWriter->Memory(), scope->codeWriter->position(),
- (addr_t)scope->compiler->_preloaded.get(reference & ~mskAnyRef) & ~mskAnyRef,
+ (addr_t)scope->compiler->_preloaded.get(reference & ~mskAnyRef),
*(pos_t*)((char*)code + disp), mask);
break;
case mskDataDisp32Lo:
case mskRDataDisp32Lo:
case mskCodeDisp32Lo:
scope->helper->writeDisp32Lo(*scope->codeWriter->Memory(), scope->codeWriter->position(),
- (addr_t)scope->compiler->_preloaded.get(reference & ~mskAnyRef) & ~mskAnyRef,
+ (addr_t)scope->compiler->_preloaded.get(reference & ~mskAnyRef),
*(pos_t*)((char*)code + disp), mask);
break;
default:
@@ -891,6 +894,75 @@ void elena_lang :: loadIOp(JITCompilerScope* scope)
writer->seekEOF();
}
+void elena_lang::loadIROp(JITCompilerScope* scope)
+{
+ MemoryWriter* writer = scope->codeWriter;
+
+ void* code = retrieveRCode(scope, scope->command.arg2);
+
+ ref_t arg2 = scope->command.arg2;
+ pos_t position = writer->position();
+ pos_t length = *(pos_t*)((char*)code - sizeof(pos_t));
+
+ // simply copy correspondent inline code
+ writer->write(code, length);
+
+ // resolve section references
+ pos_t count = *(pos_t*)((char*)code + length);
+ RelocationEntry* entries = (RelocationEntry*)((char*)code + length + sizeof(pos_t));
+ while (count > 0) {
+ // locate relocation position
+ writer->seek(position + entries->offset);
+ switch (entries->reference) {
+ case NARG_1:
+ writer->writeDWord(scope->command.arg1);
+ break;
+ case NARG16_1:
+ case ARG16_1:
+ scope->compiler->writeImm16(writer, (short)scope->command.arg1, 0);
+ break;
+ case NARG12_1:
+ scope->compiler->writeImm12(writer, (short)scope->command.arg1, 0);
+ break;
+ case PTR32_2:
+ scope->compiler->writeArgAddress(scope, arg2, 0, mskRef32);
+ break;
+ case PTR64_2:
+ scope->compiler->writeArgAddress(scope, arg2, 0, mskRef64);
+ break;
+ case DISP32HI_2:
+ scope->compiler->writeArgAddress(scope, arg2, 0, mskDisp32Hi);
+ break;
+ case DISP32LO_2:
+ scope->compiler->writeArgAddress(scope, arg2, 0, mskDisp32Lo);
+ break;
+ case XDISP32HI_2:
+ scope->compiler->writeArgAddress(scope, arg2, 0, mskXDisp32Hi);
+ break;
+ case XDISP32LO_2:
+ scope->compiler->writeArgAddress(scope, arg2, 0, mskXDisp32Lo);
+ break;
+ case PTR32HI_2:
+ {
+ scope->compiler->writeArgAddress(scope, scope->command.arg2, 0, mskRef32Hi);
+ break;
+ }
+ case PTR32LO_2:
+ {
+ scope->compiler->writeArgAddress(scope, scope->command.arg2, 0, mskRef32Lo);
+ break;
+ }
+ default:
+ //writeCoreReference();
+ break;
+ }
+
+ entries++;
+ count--;
+ }
+ writer->seekEOF();
+}
+
void elena_lang::loadLenOp(JITCompilerScope* scope)
{
MemoryWriter* writer = scope->codeWriter;
@@ -2259,7 +2331,7 @@ void elena_lang::compileHookDPR(JITCompilerScope* scope)
inline void loadPreloaded(JITCompilerScope& scope, LibraryLoaderBase* loader, size_t length,
const ref_t* functions, JITCompiler::PreloadedMap& map, Map& positions,
- ref_t mask, bool declarating)
+ ref_t mask, bool declarating, bool virtualMode)
{
for (size_t i = 0; i < length; i++) {
// due to optimization section must be ROModule::ROSection instance
@@ -2269,7 +2341,11 @@ inline void loadPreloaded(JITCompilerScope& scope, LibraryLoaderBase* loader, si
if (declarating) {
if (!map.exist(functions[i])) {
- map.add(functions[i], (void*)scope.helper->calculateVAddress(*scope.codeWriter, mask));
+ if (virtualMode) {
+ map.add(functions[i], (void*)(scope.helper->calculateVAddress(*scope.codeWriter, mask) & ~mskAnyRef));
+ }
+ else map.add(functions[i], (void*)scope.helper->calculateVAddress(*scope.codeWriter, mask));
+
positions.add(functions[i], scope.codeWriter->position());
allocateCode(&scope, info.section->get(0));
@@ -2277,9 +2353,12 @@ inline void loadPreloaded(JITCompilerScope& scope, LibraryLoaderBase* loader, si
}
else {
pos_t position = positions.get(functions[i]);
- scope.codeWriter->seek(position);
+ if (position != INVALID_POS) {
+ scope.codeWriter->seek(position);
+
+ loadCode(&scope, info.section->get(0), info.module);
+ }
- loadCode(&scope, info.section->get(0), info.module);
}
}
}
@@ -2388,6 +2467,32 @@ void elena_lang::compileJge(JITCompilerScope* scope)
}
}
+void elena_lang :: compileJle(JITCompilerScope* scope)
+{
+ pos_t label = scope->tapeReader->position() + scope->command.arg1;
+
+ if (scope->command.arg1 < 0) {
+ // if it is a back jump
+ scope->lh->writeJleBack(label, *scope->codeWriter);
+ }
+ else if (scope->command.arg1 > 0) {
+ scope->lh->writeJleForward(label, *scope->codeWriter, scope->command.arg1);
+ }
+}
+
+void elena_lang::compileJgr(JITCompilerScope* scope)
+{
+ pos_t label = scope->tapeReader->position() + scope->command.arg1;
+
+ if (scope->command.arg1 < 0) {
+ // if it is a back jump
+ scope->lh->writeJgrBack(label, *scope->codeWriter);
+ }
+ else if (scope->command.arg1 > 0) {
+ scope->lh->writeJgrForward(label, *scope->codeWriter, scope->command.arg1);
+ }
+}
+
void elena_lang::compileDispatchMR(JITCompilerScope* scope)
{
MemoryWriter* writer = scope->codeWriter;
@@ -2498,7 +2603,7 @@ void JITCompiler :: loadCoreRoutines(
ReferenceHelperBase* helper,
LabelHelperBase* lh,
JITSettings settings,
- Map& positions, bool declareMode)
+ Map& positions, bool declareMode, bool virtualMode)
{
// preload core data
MemoryBase* code = imageProvider->getTextSection();
@@ -2513,7 +2618,7 @@ void JITCompiler :: loadCoreRoutines(
JITCompilerScope dataScope(helper, this, lh, &dataWriter, nullptr, &_constants);
loadPreloaded(
dataScope, loader, coreVariableNumber, coreVariables,
- _preloaded, positions, _constants.inlineMask, declareMode);
+ _preloaded, positions, _constants.inlineMask, declareMode, virtualMode);
// fill the required number of thread-table slots
if (settings.threadCounter > 1)
@@ -2522,7 +2627,7 @@ void JITCompiler :: loadCoreRoutines(
// preload core constants
JITCompilerScope rdataScope(helper, this, lh, &rdataWriter, nullptr, &_constants);
loadPreloaded(rdataScope, loader, coreConstantNumber, coreConstants,
- _preloaded, positions, _constants.inlineMask, declareMode);
+ _preloaded, positions, _constants.inlineMask, declareMode, virtualMode);
// NOTE : SYSTEM_ENV table is tailed with GCMGSize,GCYGSize,GCPERMSize,threadCounter
rdataWriter.writeDWord(settings.mgSize);
rdataWriter.writeDWord(settings.ygSize);
@@ -2531,7 +2636,7 @@ void JITCompiler :: loadCoreRoutines(
// preload core functions
JITCompilerScope scope(helper, this, lh, &codeWriter, nullptr, &_constants);
loadPreloaded(scope, loader, coreFunctionNumber, coreFunctions, _preloaded, positions,
- _constants.inlineMask, declareMode);
+ _constants.inlineMask, declareMode, virtualMode);
}
void JITCompiler :: prepare(
@@ -2539,11 +2644,12 @@ void JITCompiler :: prepare(
ImageProviderBase* imageProvider,
ReferenceHelperBase* helper,
LabelHelperBase* lh,
- JITSettings settings)
+ JITSettings settings,
+ bool virtualMode)
{
- Map positions(0u);
- loadCoreRoutines(loader, imageProvider, helper, lh, settings, positions, true);
- loadCoreRoutines(loader, imageProvider, helper, lh, settings, positions, false);
+ Map positions(INVALID_POS);
+ loadCoreRoutines(loader, imageProvider, helper, lh, settings, positions, true, virtualMode);
+ loadCoreRoutines(loader, imageProvider, helper, lh, settings, positions, false, virtualMode);
// preload vm commands
for (ref_t i = 0; i < NumberOfInlines; i++) {
@@ -2551,11 +2657,14 @@ void JITCompiler :: prepare(
}
}
-void JITCompiler :: populatePreloaded(uintptr_t env, uintptr_t th_table, uintptr_t gc_table)
+void JITCompiler :: populatePreloaded(uintptr_t th_table)
{
- _preloaded.add(SYSTEM_ENV, (void*)env);
_preloaded.add(CORE_THREAD_TABLE, (void*)th_table);
- _preloaded.add(CORE_GC_TABLE, (void*)gc_table);
+}
+
+void* JITCompiler :: getSystemEnv()
+{
+ return _preloaded.get(SYSTEM_ENV);
}
CodeGenerator* JITCompiler :: codeGenerators()
@@ -2680,7 +2789,8 @@ void JITCompiler32 :: prepare(
ImageProviderBase* imageProvider,
ReferenceHelperBase* helper,
LabelHelperBase* lh,
- JITSettings settings)
+ JITSettings settings,
+ bool virtualMode)
{
_constants.indexPower = 2;
_constants.dataOffset = 4;
@@ -2688,7 +2798,7 @@ void JITCompiler32 :: prepare(
_constants.structMask = elStructMask32;
_constants.vmtSize = elVMTClassOffset32;
- JITCompiler::prepare(loader, imageProvider, helper, lh, settings);
+ JITCompiler::prepare(loader, imageProvider, helper, lh, settings, virtualMode);
}
pos_t JITCompiler32 :: getStaticCounter(MemoryBase* statSection, bool emptyNotAllowed)
@@ -3120,7 +3230,8 @@ void JITCompiler64 :: prepare(
ImageProviderBase* imageProvider,
ReferenceHelperBase* helper,
LabelHelperBase* lh,
- JITSettings settings)
+ JITSettings settings,
+ bool virtualMode)
{
_constants.indexPower = 3;
_constants.dataOffset = 8;
@@ -3128,7 +3239,7 @@ void JITCompiler64 :: prepare(
_constants.structMask = elStructMask64;
_constants.vmtSize = elVMTClassOffset64;
- JITCompiler::prepare(loader, imageProvider, helper, lh, settings);
+ JITCompiler::prepare(loader, imageProvider, helper, lh, settings, virtualMode);
}
void JITCompiler64 :: compileMetaList(ReferenceHelperBase* helper, MemoryReader& reader, MemoryWriter& writer, pos_t length)
@@ -3528,7 +3639,7 @@ void JITCompiler64 :: writeAttribute(MemoryWriter& writer, int category, ustr_t
writer.writeString(value);
if (virtualMode) {
- writer.writeQReference((ref_t)address | mskCodeRef64, 0);
+ writer.writeQReference((ref_t)address | mskRef64, 0);
}
else writer.writeQWord(address);
}
diff --git a/elenasrc3/engine/jitcompiler.h b/elenasrc3/engine/jitcompiler.h
index 5ea5f81d5c..a2d8900ce2 100644
--- a/elenasrc3/engine/jitcompiler.h
+++ b/elenasrc3/engine/jitcompiler.h
@@ -135,6 +135,7 @@ namespace elena_lang
friend void loadDPROp(JITCompilerScope* scope);
friend void loadDPLabelOp(JITCompilerScope* scope);
friend void loadIOp(JITCompilerScope* scope);
+ friend void loadIROp(JITCompilerScope* scope);
friend void compileBreakpoint(JITCompilerScope* scope);
friend void compileClose(JITCompilerScope* scope);
@@ -144,6 +145,8 @@ namespace elena_lang
friend void compileJne(JITCompilerScope* scope);
friend void compileJlt(JITCompilerScope* scope);
friend void compileJge(JITCompilerScope* scope);
+ friend void compileJle(JITCompilerScope* scope);
+ friend void compileJgr(JITCompilerScope* scope);
friend void compileDispatchMR(JITCompilerScope* scope);
friend void compileHookDPR(JITCompilerScope* scope);
@@ -153,7 +156,7 @@ namespace elena_lang
ReferenceHelperBase* helper,
LabelHelperBase* lh,
JITSettings settings,
- Map& positions, bool declareMode);
+ Map& positions, bool declareMode, bool virtualMode);
public:
void allocateBody(MemoryWriter& writer, int size) override;
@@ -170,7 +173,8 @@ namespace elena_lang
ImageProviderBase* imageProvider,
ReferenceHelperBase* helper,
LabelHelperBase* lh,
- JITSettings settings) override;
+ JITSettings settings,
+ bool virtualMode) override;
void compileProcedure(ReferenceHelperBase* helper, MemoryReader& bcReader,
MemoryWriter& codeWriter, LabelHelperBase* lh) override;
@@ -201,12 +205,14 @@ namespace elena_lang
void resolveLabelAddress(MemoryWriter* writer, ref_t mask, pos_t position, bool virtualMode) override;
- void populatePreloaded(uintptr_t env, uintptr_t eh_table, uintptr_t gc_table) override;
+ void populatePreloaded(uintptr_t eh_table) override;
addr_t allocateTLSIndex(ReferenceHelperBase* helper, MemoryWriter& writer) override;
void allocateThreadContent(MemoryWriter* tlsWriter) override;
+ void* getSystemEnv() override;
+
JITCompiler()
: _inlines{}, _preloaded(nullptr)
{
@@ -238,7 +244,8 @@ namespace elena_lang
ImageProviderBase* imageProvider,
ReferenceHelperBase* helper,
LabelHelperBase* lh,
- JITSettings settings) override;
+ JITSettings settings,
+ bool virtualMode) override;
int getExtMessageSize() override
{
@@ -312,7 +319,8 @@ namespace elena_lang
ImageProviderBase* imageProvider,
ReferenceHelperBase* helper,
LabelHelperBase* lh,
- JITSettings settings) override;
+ JITSettings settings,
+ bool virtualMode) override;
void compileMetaList(ReferenceHelperBase* helper, MemoryReader& reader, MemoryWriter& writer, pos_t length) override;
@@ -415,6 +423,7 @@ namespace elena_lang
void loadDPROp(JITCompilerScope* scope);
void loadDPLabelOp(JITCompilerScope* scope);
void loadIOp(JITCompilerScope* scope);
+ void loadIROp(JITCompilerScope* scope);
void compileClose(JITCompilerScope* scope);
void compileOpen(JITCompilerScope* scope);
@@ -424,6 +433,8 @@ namespace elena_lang
void compileJne(JITCompilerScope* scope);
void compileJlt(JITCompilerScope* scope);
void compileJge(JITCompilerScope* scope);
+ void compileJle(JITCompilerScope* scope);
+ void compileJgr(JITCompilerScope* scope);
void compileDispatchMR(JITCompilerScope* scope);
void compileHookDPR(JITCompilerScope* scope);
}
diff --git a/elenasrc3/engine/jitlinker.cpp b/elenasrc3/engine/jitlinker.cpp
index 81c3e81869..e64349e9c2 100644
--- a/elenasrc3/engine/jitlinker.cpp
+++ b/elenasrc3/engine/jitlinker.cpp
@@ -11,6 +11,7 @@
#include "jitlinker.h"
#include "langcommon.h"
#include "bytecode.h"
+#include "module.h"
//#define FULL_OUTOUT_INFO 1
@@ -295,16 +296,17 @@ void JITLinker::JITLinkerReferenceHelper :: writeReference(MemoryBase& target, p
module = _module;
addr_t vaddress = INVALID_ADDR;
- //switch (mask) {
- // case mskNameLiteralRef:
- // case mskPathLiteralRef:
- // break;
- // default:
+ switch (mask) {
+ case mskAutoSymbolRef:
+ // HOTFIX : preloaded symbols should be resolved later
+ _owner->_mapper->addLazyReference({ mask, position, module, reference, addressMask });
+ return;
+ default:
vaddress = _owner->_mapper->resolveReference(
_owner->_loader->retrieveReferenceInfo(module, refID, mask,
_owner->_forwardResolver), mask);
- // break;
- //}
+ break;
+ }
if (vaddress != INVALID_ADDR) {
switch (addressMask & mskRefType) {
@@ -503,6 +505,12 @@ void JITLinker :: fixReferences(VAddressMap& relocations, MemoryBase* image)
info.addressMask = 0; // clear because it is already fixed
break;
}
+ case mskMssgNameLiteralRef:
+ {
+ ref_t dummy = 0;
+ vaddress = resolve({ info.module, info.module->resolveAction(currentRef, dummy) }, currentMask, false);
+ break;
+ }
case mskMssgLiteralRef:
case mskExtMssgLiteralRef:
vaddress = resolve({ info.module, info.module->resolveConstant(currentRef) }, currentMask, false);
@@ -708,6 +716,8 @@ void JITLinker :: resolveStaticFields(ReferenceInfo& referenceInfo, MemoryReader
for (auto it = statics.start(); !it.eof(); ++it) {
auto fieldInfo = *it;
+ ref_t mask = fieldInfo.valueRef & mskAnyRef;
+
if (fieldInfo.valueRef && fieldInfo.offset < 0) {
addr_t vaddress = INVALID_REF;
@@ -721,12 +731,11 @@ void JITLinker :: resolveStaticFields(ReferenceInfo& referenceInfo, MemoryReader
default:
vaddress = resolve(
_loader->retrieveReferenceInfo(referenceInfo.module, fieldInfo.valueRef & ~mskAnyRef,
- fieldInfo.valueRef & mskAnyRef, _forwardResolver),
+ mask, _forwardResolver),
mskVMTRef, false);
}
assert(vaddress != INVALID_REF);
-
staticValues.add(fieldInfo.offset, vaddress);
}
}
@@ -854,6 +863,15 @@ void JITLinker :: resolveClassGlobalAttributes(ReferenceInfo referenceInfo, Memo
}
else createGlobalAttribute(GA_CLASS_NAME, referenceInfo.referenceName, vaddress);
break;
+ case ClassAttribute::Initializer:
+ {
+ ref_t symbolRef = vmtReader.getDWord();
+ attrCount -= sizeof(unsigned int);
+
+ _mapper->addLazyReference({ mskAutoSymbolRef, INVALID_POS, referenceInfo.module, symbolRef, 0 });
+
+ break;
+ }
default:
break;
}
@@ -1164,6 +1182,13 @@ mssg_t JITLinker :: parseMessageLiteral(ustr_t messageLiteral, ModuleBase* modul
return createMessage(module, message, references);
}
+mssg_t JITLinker :: parseMessageNameLiteral(ustr_t messageLiteral, ModuleBase* module, VAddressMap& references)
+{
+ mssg_t message = ByteCodeUtil::resolveMessageName(messageLiteral, module, true);
+
+ return createMessage(module, message, references);
+}
+
Pair JITLinker :: parseExtMessageLiteral(ustr_t messageLiteral, ModuleBase* module, VAddressMap& references)
{
Pair retVal = {};
@@ -1218,10 +1243,13 @@ addr_t JITLinker :: resolveConstant(ReferenceInfo referenceInfo, ref_t sectionMa
structMode = true;
break;
case mskWideLiteralRef:
+ {
+ WideMessage tmp(value);
vmtReferenceInfo.referenceName = _constantSettings.wideLiteralClass;
- size = (value.length_pos() + 1) << 1;
+ size = (tmp.length_pos() + 1) << 1;
structMode = true;
break;
+ }
case mskCharacterRef:
vmtReferenceInfo.referenceName = _constantSettings.characterClass;
size = 4;
@@ -1232,6 +1260,11 @@ addr_t JITLinker :: resolveConstant(ReferenceInfo referenceInfo, ref_t sectionMa
size = 4;
structMode = true;
break;
+ case mskMssgNameLiteralRef:
+ vmtReferenceInfo.referenceName = _constantSettings.messageNameClass;
+ size = 4;
+ structMode = true;
+ break;
case mskExtMssgLiteralRef:
vmtReferenceInfo.referenceName = _constantSettings.extMessageClass;
size = _compiler->getExtMessageSize();
@@ -1277,6 +1310,9 @@ addr_t JITLinker :: resolveConstant(ReferenceInfo referenceInfo, ref_t sectionMa
case mskMssgLiteralRef:
_compiler->writeMessage(writer, parseMessageLiteral(value, referenceInfo.module, messageReferences));
break;
+ case mskMssgNameLiteralRef:
+ _compiler->writeMessage(writer, parseMessageNameLiteral(value, referenceInfo.module, messageReferences));
+ break;
case mskExtMssgLiteralRef:
{
pos_t position = writer.position();
@@ -1322,6 +1358,21 @@ addr_t JITLinker :: resolveStaticVariable(ReferenceInfo referenceInfo, ref_t sec
return vaddress;
}
+void JITLinker :: copyMetaList(ModuleInfo info, ModuleInfoList& output)
+{
+ auto sectionInfo = _loader->getSection({ info.module, info.module->resolveReference(info.reference) }, mskTypeListRef, 0, true);
+ if (!sectionInfo.module)
+ return;
+
+ MemoryReader bcReader(sectionInfo.section);
+
+ while (!bcReader.eof()) {
+ ref_t symbolRef = bcReader.getRef();
+
+ output.add({ info.module, symbolRef & ~mskAnyRef });
+ }
+}
+
void JITLinker :: prepare(JITCompilerBase* compiler)
{
_compiler = compiler;
@@ -1350,7 +1401,7 @@ void JITLinker :: prepare(JITCompilerBase* compiler)
resolveWeakAction(CONSTRUCTOR_MESSAGE);
// prepare jit compiler
- _compiler->prepare(_loader, _imageProvider, &helper, nullptr, _jitSettings);
+ _compiler->prepare(_loader, _imageProvider, &helper, nullptr, _jitSettings, _virtualMode);
// fix not loaded references
fixReferences(references, _imageProvider->getTextSection());
@@ -1358,9 +1409,11 @@ void JITLinker :: prepare(JITCompilerBase* compiler)
void JITLinker :: complete(JITCompilerBase* compiler, ustr_t superClass)
{
- // set voidobj
- addr_t superAddr = resolve(superClass, mskVMTRef, true);
- compiler->updateVoidObject(_imageProvider->getRDataSection(), superAddr, _virtualMode);
+ if (!superClass.empty()) {
+ // set voidobj
+ addr_t superAddr = resolve(superClass, mskVMTRef, true);
+ compiler->updateVoidObject(_imageProvider->getRDataSection(), superAddr, _virtualMode);
+ }
// fix message body references
MemoryBase* mbSection = _imageProvider->getMBDataSection();
@@ -1436,6 +1489,7 @@ addr_t JITLinker :: resolve(ReferenceInfo referenceInfo, ref_t sectionMask, bool
case mskCharacterRef:
case mskMssgLiteralRef:
case mskExtMssgLiteralRef:
+ case mskMssgNameLiteralRef:
address = resolveConstant(referenceInfo, sectionMask);
break;
case mskConstant:
@@ -1499,3 +1553,23 @@ addr_t JITLinker :: resolveTLSSection(JITCompilerBase* compiler)
return address;
}
+void JITLinker :: loadPreloaded(ustr_t preloadedSection)
+{
+ ModuleInfoList list({});
+ ModuleInfoList symbolList({});
+
+ IdentifierString nameToResolve(META_PREFIX, preloadedSection);
+
+ // load preloaded symbols
+ _loader->loadDistributedSymbols(*nameToResolve, list);
+ for (auto it = list.start(); !it.eof(); ++it) {
+ copyMetaList(*it, symbolList);
+ }
+
+ // save preloaded symbols as auto symbols
+ for (auto it = symbolList.start(); !it.eof(); ++it) {
+ auto info = *it;
+
+ _mapper->addLazyReference({ mskAutoSymbolRef, INVALID_POS, info.module, info.reference, 0 });
+ }
+}
diff --git a/elenasrc3/engine/jitlinker.h b/elenasrc3/engine/jitlinker.h
index fd62ee2a35..2cab224055 100644
--- a/elenasrc3/engine/jitlinker.h
+++ b/elenasrc3/engine/jitlinker.h
@@ -62,6 +62,7 @@ namespace elena_lang
ustr_t characterClass;
ustr_t messageClass;
ustr_t extMessageClass;
+ ustr_t messageNameClass;
};
struct VAddressInfo
@@ -189,6 +190,7 @@ namespace elena_lang
mssg_t createMessage(ModuleBase* module, mssg_t message, VAddressMap& references);
mssg_t parseMessageLiteral(ustr_t messageLiteral, ModuleBase* module, VAddressMap& references);
+ mssg_t parseMessageNameLiteral(ustr_t messageLiteral, ModuleBase* module, VAddressMap& references);
Pair parseExtMessageLiteral(ustr_t messageLiteral, ModuleBase* module, VAddressMap& references);
addr_t resolveConstantDump(ReferenceInfo referenceInfo, SectionInfo sectionInfo, ref_t sectionMask);
@@ -218,6 +220,8 @@ namespace elena_lang
addr_t resolve(ReferenceInfo refrenceInfo, ref_t sectionMask, bool silentMode);
+ void copyMetaList(ModuleInfo info, ModuleInfoList& output);
+
public:
addr_t resolveTape(ustr_t referenceName, MemoryBase* tape);
addr_t resolveTemporalByteCode(MemoryDump& tapeSymbol, ModuleBase* module);
@@ -225,6 +229,7 @@ namespace elena_lang
addr_t resolve(ustr_t referenceName, ref_t sectionMask, bool silentMode);
+ void loadPreloaded(ustr_t preloadedSection);
void prepare(JITCompilerBase* compiler);
void complete(JITCompilerBase* compiler, ustr_t superClass);
@@ -256,6 +261,7 @@ namespace elena_lang
_constantSettings.characterClass = forwardResolver->resolveForward(CHAR_FORWARD);
_constantSettings.messageClass = forwardResolver->resolveForward(MESSAGE_FORWARD);
_constantSettings.extMessageClass = forwardResolver->resolveForward(EXT_MESSAGE_FORWARD);
+ _constantSettings.messageNameClass = forwardResolver->resolveForward(MESSAGE_NAME_FORWARD);
}
};
diff --git a/elenasrc3/engine/langcommon.h b/elenasrc3/engine/langcommon.h
index 93d462edd8..de554058f4 100644
--- a/elenasrc3/engine/langcommon.h
+++ b/elenasrc3/engine/langcommon.h
@@ -174,6 +174,7 @@ namespace elena_lang
constexpr auto V_CONST = 0x80002001u;
constexpr auto V_EMBEDDABLE = 0x80002002u;
constexpr auto V_WRAPPER = 0x80002003u;
+ constexpr auto V_READONLY = 0x80002004u;
constexpr auto V_OVERLOADRET = 0x8000200Au;
constexpr auto V_VARIADIC = 0x8000200Bu;
@@ -214,7 +215,7 @@ namespace elena_lang
constexpr auto V_STRINGOBJ = 0x80000801u;
constexpr auto V_FLOATBINARY = 0x80000802u;
constexpr auto V_INTBINARY = 0x80000803u;
- //constexpr auto V_DECLOBJ = 0x80000804u;
+ constexpr auto V_UINTBINARY = 0x80000804u;
constexpr auto V_WORDBINARY = 0x80000805u;
constexpr auto V_MSSGNAME = 0x80000806u;
constexpr auto V_SUBJBINARY = 0x80000807u;
@@ -254,11 +255,13 @@ namespace elena_lang
constexpr auto V_EXTMESSAGE64 = 0x8000001Cu;
constexpr auto V_EXTMESSAGE128 = 0x8000001Du;
constexpr auto V_WORD64 = 0x8000001Eu;
+ constexpr auto V_UINT32 = 0x8000001Fu;
/// built-in variables
constexpr auto V_SELF_VAR = 0x80000081u;
constexpr auto V_DECL_VAR = 0x80000082u;
constexpr auto V_SUPER_VAR = 0x80000083u;
+ constexpr auto V_RECEIVED_VAR = 0x80000084u;
// === Operators ===
constexpr auto OPERATOR_MAKS = 0x1840;
@@ -320,6 +323,7 @@ namespace elena_lang
constexpr pos_t VM_INIT_CMD = 0x005;
constexpr pos_t VM_FORWARD_CMD = 0x106;
constexpr pos_t VM_PACKAGE_CMD = 0x107;
+ constexpr pos_t VM_PRELOADED_CMD = 0x108;
// --- Configuration xpaths ---
constexpr auto WIN_X86_KEY = "Win_x86";
diff --git a/elenasrc3/engine/libman.cpp b/elenasrc3/engine/libman.cpp
index d6fc66255a..541cd423c6 100644
--- a/elenasrc3/engine/libman.cpp
+++ b/elenasrc3/engine/libman.cpp
@@ -426,6 +426,7 @@ ReferenceInfo LibraryProvider :: retrieveReferenceInfo(ModuleBase* module, ref_t
case mskWideLiteralRef:
case mskCharacterRef:
case mskMssgLiteralRef:
+ case mskMssgNameLiteralRef:
return module->resolveConstant(reference);
default:
{
@@ -542,3 +543,33 @@ bool LibraryProvider::saveDebugModule(ModuleBase* module)
FileWriter writer(*path, FileEncoding::Raw, false);
return dynamic_cast(module)->save(writer);
}
+
+void LibraryProvider :: loadDistributedSymbols(ustr_t virtualSymbolName, ModuleInfoList& list)
+{
+ for (auto it = _modules.start(); !it.eof(); ++it) {
+ IdentifierString rootName("'", virtualSymbolName);
+
+ ref_t reference = (*it)->mapReference(*rootName, true);
+ if (reference) {
+ list.add({ *it, reference });
+ }
+
+ // get list of nested namespaces
+ IdentifierString nsSectionName("'", NAMESPACES_SECTION);
+ auto nsSection = (*it)->mapSection((*it)->mapReference(*nsSectionName, true) | mskLiteralListRef, true);
+ if (nsSection) {
+ MemoryReader nsReader(nsSection);
+ while (!nsReader.eof()) {
+ IdentifierString nsProperName("'");
+ nsReader.appendString(nsProperName);
+ nsProperName.append("'");
+ nsProperName.append(virtualSymbolName);
+
+ reference = (*it)->mapReference(*nsProperName, true);
+ if (reference) {
+ list.add({ *it, reference });
+ }
+ }
+ }
+ }
+}
diff --git a/elenasrc3/engine/libman.h b/elenasrc3/engine/libman.h
index f8c0e08c91..8dd236c8e0 100644
--- a/elenasrc3/engine/libman.h
+++ b/elenasrc3/engine/libman.h
@@ -3,7 +3,7 @@
//
// This header contains the declaration of the base class implementing
// ELENA JIT Loader.
-// (C)2021-2022, by Aleksey Rakov
+// (C)2021-2023, by Aleksey Rakov
//---------------------------------------------------------------------------
#ifndef LIBMAN_H
@@ -87,6 +87,8 @@ namespace elena_lang
ReferenceInfo retrieveReferenceInfo(ustr_t referenceName,
ForwardResolverBase* forwardResolver) override;
+ void loadDistributedSymbols(ustr_t virtualSymbolName, ModuleInfoList& list) override;
+
ModuleBase* createModule(ustr_t name);
ModuleBase* createDebugModule(ustr_t name);
diff --git a/elenasrc3/engine/ppc64compiler.cpp b/elenasrc3/engine/ppc64compiler.cpp
index 94d1ae5462..bb59903ae4 100644
--- a/elenasrc3/engine/ppc64compiler.cpp
+++ b/elenasrc3/engine/ppc64compiler.cpp
@@ -157,7 +157,8 @@ void PPC64leJITCompiler:: prepare(
ImageProviderBase* imageProvider,
ReferenceHelperBase* helper,
LabelHelperBase*,
- JITSettings settings)
+ JITSettings settings,
+ bool virtualMode)
{
//_inlineMask = mskCodeRelRef32;
@@ -168,7 +169,7 @@ void PPC64leJITCompiler:: prepare(
commands[(int)Overloads[i].value1] = Overloads[i].value2;
PPCLabelHelper labelHelper;
- JITCompiler64::prepare(loader, imageProvider, helper, &labelHelper, settings);
+ JITCompiler64::prepare(loader, imageProvider, helper, &labelHelper, settings, virtualMode);
}
void PPC64leJITCompiler :: resolveLabelAddress(MemoryWriter* writer, ref_t mask, pos_t position, bool virtualMode)
diff --git a/elenasrc3/engine/ppc64compiler.h b/elenasrc3/engine/ppc64compiler.h
index e94b3fa1af..d309bbaaaf 100644
--- a/elenasrc3/engine/ppc64compiler.h
+++ b/elenasrc3/engine/ppc64compiler.h
@@ -23,7 +23,8 @@ namespace elena_lang
ImageProviderBase* imageProvider,
ReferenceHelperBase* helper,
LabelHelperBase* lh,
- JITSettings settings) override;
+ JITSettings settings,
+ bool virtualMode) override;
friend void PPC64loadCallOp(JITCompilerScope* scope);
friend void PPC64compileOpenIN(JITCompilerScope* scope);
diff --git a/elenasrc3/engine/ppchelper.h b/elenasrc3/engine/ppchelper.h
index 0c821ec73b..59f6700020 100644
--- a/elenasrc3/engine/ppchelper.h
+++ b/elenasrc3/engine/ppchelper.h
@@ -363,6 +363,38 @@ namespace elena_lang
writeBCxx(4, 0, offset, 0, 0, writer);
}
+
+ void writeJgrForward(pos_t label, MemoryWriter& writer, int byteCodeOffset) override
+ {
+ jumps.add(label, { writer.position() });
+
+ writeBCxx(12, 1, 0, 0, 0, writer);
+ }
+
+ void writeJgrBack(pos_t label, MemoryWriter& writer) override
+ {
+ int offset = labels.get(label) - writer.position();
+ if (abs(offset) > 0xFFFF)
+ throw InternalError(-1);
+
+ writeBCxx(12, 1, offset, 0, 0, writer);
+ }
+
+ void writeJleForward(pos_t label, MemoryWriter& writer, int byteCodeOffset) override
+ {
+ jumps.add(label, { writer.position() });
+
+ writeBCxx(4, 1, 0, 0, 0, writer);
+ }
+
+ void writeJleBack(pos_t label, MemoryWriter& writer) override
+ {
+ int offset = labels.get(label) - writer.position();
+ if (abs(offset) > 0xFFFF)
+ throw InternalError(-1);
+
+ writeBCxx(4, 1, offset, 0, 0, writer);
+ }
};
}
diff --git a/elenasrc3/engine/rtmanager.cpp b/elenasrc3/engine/rtmanager.cpp
index 631adca2fc..577344bf32 100644
--- a/elenasrc3/engine/rtmanager.cpp
+++ b/elenasrc3/engine/rtmanager.cpp
@@ -17,6 +17,18 @@ RTManager :: RTManager(MemoryBase* msection, MemoryBase* dbgsection)
}
+void RTManager :: loadRootPackage(LibraryProviderBase& provider, path_t rootPath)
+{
+ MemoryReader reader(dbgsection);
+
+ // skip a debugger entry pointer
+ addr_t tempAddr = 0;
+ reader.read(&tempAddr, sizeof(tempAddr));
+
+ ustr_t ns = reader.getString(DEFAULT_STR);
+ provider.addPackage(ns, rootPath);
+}
+
bool RTManager :: readAddressInfo(addr_t retAddress, LibraryLoaderBase& provider, ustr_t& symbol, ustr_t& method, ustr_t& path, int& row)
{
MemoryReader reader(dbgsection);
@@ -90,6 +102,7 @@ bool RTManager :: readAddressInfo(addr_t retAddress, LibraryLoaderBase& provider
stringReader.seek(info.addresses.source.nameRef);
method = stringReader.getString(DEFAULT_STR);
break;
+ case DebugSymbol::Class: // NOTE : to take into account vmt address
case DebugSymbol::Breakpoint:
case DebugSymbol::VirtualBreakpoint:
index--;
diff --git a/elenasrc3/engine/rtmanager.h b/elenasrc3/engine/rtmanager.h
index 49abfb7bcc..6d40e1061b 100644
--- a/elenasrc3/engine/rtmanager.h
+++ b/elenasrc3/engine/rtmanager.h
@@ -20,6 +20,8 @@ namespace elena_lang
bool readAddressInfo(addr_t retAddress, LibraryLoaderBase& provider, ustr_t& symbol, ustr_t& method, ustr_t& path, int& row);
public:
+ void loadRootPackage(LibraryProviderBase& provider, path_t rootPath);
+
ref_t loadSubject(ustr_t actionName);
void loadSubjectName(IdentifierString& actionName, ref_t subjectRef);
diff --git a/elenasrc3/engine/scriptreader.cpp b/elenasrc3/engine/scriptreader.cpp
index 500e873126..76ccf544fa 100644
--- a/elenasrc3/engine/scriptreader.cpp
+++ b/elenasrc3/engine/scriptreader.cpp
@@ -3,7 +3,7 @@
//
// This file contains ELENA ScriptReader class implementation.
//
-// (C)2005-2021, by Alexei Rakov
+// (C)2021-2023, by Aleksey Rakov
//---------------------------------------------------------------------------
#include "elena.h"
diff --git a/elenasrc3/engine/syntaxtree.cpp b/elenasrc3/engine/syntaxtree.cpp
index 1ec4ba1169..13bd11430d 100644
--- a/elenasrc3/engine/syntaxtree.cpp
+++ b/elenasrc3/engine/syntaxtree.cpp
@@ -58,6 +58,27 @@ void SyntaxTree :: copyNode(SyntaxTreeWriter& writer, SyntaxNode node, bool incl
writer.closeNode();
}
+void SyntaxTree :: copyNodeSafe(SyntaxTreeWriter& writer, SyntaxNode node, bool includingNode)
+{
+ if (includingNode) {
+ if (node.arg.strArgPosition != INVALID_POS) {
+ IdentifierString tmp(node.identifier());
+ writer.newNode(node.key, *tmp);
+ }
+ else writer.newNode(node.key, node.arg.reference);
+ }
+
+ SyntaxNode current = node.firstChild();
+ while (current != SyntaxKey::None) {
+ copyNodeSafe(writer, current, true);
+
+ current = current.nextNode();
+ }
+
+ if (includingNode)
+ writer.closeNode();
+}
+
void SyntaxTree :: saveNode(SyntaxNode node, MemoryBase* section, bool includingNode)
{
SyntaxTree tree;
diff --git a/elenasrc3/engine/syntaxtree.h b/elenasrc3/engine/syntaxtree.h
index 04c3d81845..fc95303b8b 100644
--- a/elenasrc3/engine/syntaxtree.h
+++ b/elenasrc3/engine/syntaxtree.h
@@ -109,6 +109,7 @@ namespace elena_lang
XorOperation = 0x001863,
BreakOperation = 0x001864,
LazyOperation = 0x001865,
+ TupleAssignOperation = 0x001866,
Postfix = 0x001068,
TemplatePostfix = 0x001069,
//MethodPostfix = 0x00106A,
@@ -128,6 +129,8 @@ namespace elena_lang
L7Expression = 0x001899,
L3SingleExpression = 0x00189A,
NestedRootExpression = 0x00189B,
+ TemplateOperation = 0x00189C,
+ LTExpression = 0x00189D,
TemplateExpression = 0x0018A0,
FieldInitializer = 0x0018B0,
Message = 0x0010C0,
@@ -151,6 +154,14 @@ namespace elena_lang
SwitchLastOption = 0x0018D2,
SwitchCode = 0x0018D3,
CollectionExpression = 0x0018D4,
+ TupleCollection = 0x0018D5,
+ Operator = 0x0010D6,
+ SubVariable = 0x0010D7,
+ SubDeclaration = 0x0010D8,
+ FinallyBlock = 0x001CD9,
+ FinalOperation = 0x001CDA,
+ ParameterBlock = 0x0010F0,
+ StaticInitializerMethod = 0x0010F1,
Name = 0x000101,
Namespace = 0x000103,
@@ -213,6 +224,7 @@ namespace elena_lang
}
static void copyNode(SyntaxTreeWriter& writer, SyntaxNode node, bool includingNode = false);
+ static void copyNodeSafe(SyntaxTreeWriter& writer, SyntaxNode node, bool includingNode = false);
static void saveNode(SyntaxNode node, MemoryBase* section, bool includingNode = false);
};
diff --git a/elenasrc3/engine/textparser.h b/elenasrc3/engine/textparser.h
index 57d5c1c623..f3cc6c262d 100644
--- a/elenasrc3/engine/textparser.h
+++ b/elenasrc3/engine/textparser.h
@@ -20,6 +20,7 @@ namespace elena_lang
constexpr char dfaIdentifier = 'C';
constexpr char dfaOperator = 'D';
constexpr char dfaInteger = 'E';
+ constexpr char dfaQuoteStart = 'F';
constexpr char dfaQuote = 'G';
constexpr char dfaHexInteger = 'J';
constexpr char dfaReference = 'M';
diff --git a/elenasrc3/engine/x86_64compiler.cpp b/elenasrc3/engine/x86_64compiler.cpp
index 7577b27954..532dc626a1 100644
--- a/elenasrc3/engine/x86_64compiler.cpp
+++ b/elenasrc3/engine/x86_64compiler.cpp
@@ -3,7 +3,7 @@
//
// This file contains ELENA JIT-X linker class.
// Supported platforms: x86-64
-// (C)2021-2022 by Aleksey Rakov
+// (C)2021-2023 by Aleksey Rakov
//---------------------------------------------------------------------------
#include "elena.h"
@@ -147,7 +147,8 @@ void X86_64JITCompiler :: prepare(
ImageProviderBase* imageProvider,
ReferenceHelperBase* helper,
LabelHelperBase*,
- JITSettings _settings)
+ JITSettings _settings,
+ bool virtualMode)
{
_constants.inlineMask = mskCodeRelRef32;
@@ -158,7 +159,7 @@ void X86_64JITCompiler :: prepare(
commands[(int)Overloads[i].value1] = Overloads[i].value2;
X86LabelHelper lh;
- JITCompiler64::prepare(loader, imageProvider, helper, &lh, _settings);
+ JITCompiler64::prepare(loader, imageProvider, helper, &lh, _settings, virtualMode);
}
void X86_64JITCompiler :: writeImm9(MemoryWriter* writer, int value, int type)
diff --git a/elenasrc3/engine/x86_64compiler.h b/elenasrc3/engine/x86_64compiler.h
index 0679d58d71..13bfa6dd83 100644
--- a/elenasrc3/engine/x86_64compiler.h
+++ b/elenasrc3/engine/x86_64compiler.h
@@ -3,7 +3,7 @@
//
// This file contains ELENA JIT-X linker class.
// Supported platforms: x86-64
-// (C)2021-2022, by Aleksey Rakov
+// (C)2021-2023, by Aleksey Rakov
//---------------------------------------------------------------------------
#ifndef X86_64COMPILER_H
@@ -22,7 +22,8 @@ namespace elena_lang
ImageProviderBase* imageProvider,
ReferenceHelperBase* helper,
LabelHelperBase* lh,
- JITSettings settings) override;
+ JITSettings settings,
+ bool virtualMode) override;
friend void x86_64loadCallOp(JITCompilerScope* scope);
friend void x86_64compileStackOp(JITCompilerScope* scope);
diff --git a/elenasrc3/engine/x86compiler.cpp b/elenasrc3/engine/x86compiler.cpp
index e797295376..5c00b78839 100644
--- a/elenasrc3/engine/x86compiler.cpp
+++ b/elenasrc3/engine/x86compiler.cpp
@@ -19,13 +19,14 @@ void X86JITCompiler :: prepare(
ImageProviderBase* imageProvider,
ReferenceHelperBase* helper,
LabelHelperBase*,
- JITSettings settings)
+ JITSettings settings,
+ bool virtualMode)
{
X86LabelHelper lh;
_constants.inlineMask = mskCodeRef32;
- JITCompiler32::prepare(loader, imageProvider, helper, &lh, settings);
+ JITCompiler32::prepare(loader, imageProvider, helper, &lh, settings, virtualMode);
}
void X86JITCompiler :: writeImm9(MemoryWriter* writer, int value, int type)
diff --git a/elenasrc3/engine/x86compiler.h b/elenasrc3/engine/x86compiler.h
index 0ea75c949b..ce7af757b0 100644
--- a/elenasrc3/engine/x86compiler.h
+++ b/elenasrc3/engine/x86compiler.h
@@ -21,7 +21,8 @@ namespace elena_lang
ImageProviderBase* imageProvider,
ReferenceHelperBase* helper,
LabelHelperBase* lh,
- JITSettings settings) override;
+ JITSettings settings,
+ bool virtualMode) override;
public:
void writeImm9(MemoryWriter* writer, int value, int type) override;
diff --git a/elenasrc3/engine/x86helper.h b/elenasrc3/engine/x86helper.h
index 6cc8d3c568..27bcc95255 100644
--- a/elenasrc3/engine/x86helper.h
+++ b/elenasrc3/engine/x86helper.h
@@ -120,8 +120,11 @@ namespace elena_lang
JA = 0x07,
JS = 0x08,
JNS = 0x09,
+ JP = 0x0A,
JL = 0x0C,
JGE = 0x0D,
+ JLE = 0x0E,
+ JG = 0x0F,
};
inline bool test(X86OperandType type, X86OperandType mask)
@@ -485,6 +488,26 @@ namespace elena_lang
{
writeJccBack(X86JumpType::JGE, label, writer);
}
+
+ void writeJgrForward(pos_t label, MemoryWriter& writer, int byteCodeOffset) override
+ {
+ writeJccForward(X86JumpType::JG, label, writer, byteCodeOffset);
+ }
+
+ void writeJgrBack(pos_t label, MemoryWriter& writer) override
+ {
+ writeJccBack(X86JumpType::JG, label, writer);
+ }
+
+ void writeJleForward(pos_t label, MemoryWriter& writer, int byteCodeOffset) override
+ {
+ writeJccForward(X86JumpType::JLE, label, writer, byteCodeOffset);
+ }
+
+ void writeJleBack(pos_t label, MemoryWriter& writer) override
+ {
+ writeJccBack(X86JumpType::JLE, label, writer);
+ }
};
}
diff --git a/elenasrc3/gui/controller.cpp b/elenasrc3/gui/controller.cpp
index 1499ed1154..ca4099f3d4 100644
--- a/elenasrc3/gui/controller.cpp
+++ b/elenasrc3/gui/controller.cpp
@@ -16,7 +16,7 @@ using namespace elena_lang;
//
//}
-void TextViewController :: newDocument(TextViewModelBase* model, ustr_t name, int notifyMessage)
+void TextViewController :: newDocument(TextViewModelBase* model, ustr_t name)
{
Text* text = new Text(_settings.eolMode);
text->create();
@@ -267,7 +267,7 @@ void TextViewController::selectAll(TextViewModelBase* model)
DocumentChangeStatus status = {};
auto docView = model->DocView();
- docView->moveHome(status, false);
+ docView->moveFirst(status, false);
docView->moveEnd(status, true);
notifyOnChange(model, status);
diff --git a/elenasrc3/gui/controller.h b/elenasrc3/gui/controller.h
index 0fbc81ee90..2439080a81 100644
--- a/elenasrc3/gui/controller.h
+++ b/elenasrc3/gui/controller.h
@@ -12,8 +12,17 @@
namespace elena_lang
{
- // --- DialogBase ---
- class DialogBase
+ // --- FileDialogBase ---
+ class FileDialogBase
+ {
+ public:
+ virtual bool openFile(PathString& path) = 0;
+ virtual bool openFiles(List& files) = 0;
+ virtual bool saveFile(path_t ext, PathString& path) = 0;
+ };
+
+ // --- MessageDialogBase ---
+ class MessageDialogBase
{
public:
enum Answer
@@ -21,11 +30,15 @@ namespace elena_lang
Yes, No, Cancel
};
- virtual bool openFile(PathString& path) = 0;
- virtual bool openFiles(List& files) = 0;
- virtual bool saveFile(path_t ext, PathString& path) = 0;
-
virtual Answer question(text_str message, const text_str param) = 0;
+ virtual Answer question(text_str message) = 0;
+ };
+
+ // --- ProjectSettingsBase ---
+ class ProjectSettingsBase
+ {
+ public:
+ virtual bool showModal() = 0;
};
// --- TextViewSettings ---
@@ -55,8 +68,7 @@ namespace elena_lang
void selectPreviousDocument(TextViewModelBase* model);
void closeDocument(TextViewModelBase* model, int index, NotificationStatus& status) override;
- void newDocument(TextViewModelBase* model, ustr_t name,
- int notifyMessage) override;
+ void newDocument(TextViewModelBase* model, ustr_t name) override;
bool insertNewLine(TextViewModelBase* model) override;
bool insertChar(TextViewModelBase* model, text_c ch) override;
diff --git a/elenasrc3/gui/document.cpp b/elenasrc3/gui/document.cpp
index 23dac6b36e..11abaf8340 100644
--- a/elenasrc3/gui/document.cpp
+++ b/elenasrc3/gui/document.cpp
@@ -77,16 +77,22 @@ void LexicalFormatter :: format()
bool LexicalFormatter :: checkMarker(ReaderInfo& info)
{
- auto it = _markers->getIt(info.row + 1);
- if (!it.eof()) {
- auto marker = *it;
+ Marker marker = { INVALID_POS };
+ for (auto it = _markers->start(); !it.eof(); ++it) {
+ if (it.key() == info.row + 1) {
+ marker = *it;
+ }
+ }
+ if (marker.style != INVALID_POS) {
info.bandStyle = true;
info.style = marker.style;
+ info.toggleMark = marker.toggleMark;
info.step = 0;
return true;
}
+
return false;
}
@@ -175,6 +181,7 @@ void DocumentView::LexicalReader :: readFirst(TextWriter& writer, pos_t
{
style = step = 0;
newLine = true;
+ toggleMark = false;
region.topLeft = docView->_frame.getCaret();
region.bottomRight = region.topLeft + docView->_size;
@@ -902,6 +909,7 @@ void DocumentView :: save(path_t path)
_text->save(path);
status.modifiedMode = false;
+ status.unnamed = false;
DocumentChangeStatus changeStatus = {};
notifyOnChange(changeStatus);
diff --git a/elenasrc3/gui/document.h b/elenasrc3/gui/document.h
index fd6374e838..3a34cbe0e8 100644
--- a/elenasrc3/gui/document.h
+++ b/elenasrc3/gui/document.h
@@ -32,11 +32,13 @@ namespace elena_lang
bool newLine;
bool bandStyle;
+ bool toggleMark;
};
struct Marker
{
pos_t style;
+ bool toggleMark;
bool operator ==(const Marker& m)
{
@@ -170,6 +172,7 @@ namespace elena_lang
this->row = 0;
this->newLine = false;
this->bandStyle = false;
+ this->toggleMark = false;
this->bm.invalidate();
}
@@ -255,9 +258,9 @@ namespace elena_lang
_notifiers.cut(notifier);
}
- void addMarker(int row, pos_t style, bool instanteMode, DocumentChangeStatus& changeStatus)
+ void addMarker(int row, pos_t style, bool instanteMode, bool togleMark, DocumentChangeStatus& changeStatus)
{
- _markers.add(row, { style });
+ _markers.add(row, { style, togleMark });
changeStatus.formatterChanged = true;
}
@@ -302,6 +305,15 @@ namespace elena_lang
bool isUnnamed() { return status.unnamed; }
bool isModified() { return status.modifiedMode; }
+ void markAsUnnamed()
+ {
+ status.unnamed = true;
+ }
+ void markAsModified()
+ {
+ status.modifiedMode = true;
+ }
+
Point getSize() const { return _size; }
virtual void setSize(Point size);
diff --git a/elenasrc3/gui/guicommon.h b/elenasrc3/gui/guicommon.h
index 68191b097b..c2a902a9dc 100644
--- a/elenasrc3/gui/guicommon.h
+++ b/elenasrc3/gui/guicommon.h
@@ -150,6 +150,7 @@ namespace elena_lang
public:
virtual void notify(int id, NotificationStatus status) = 0;
virtual void notifySelection(int id, size_t param) = 0;
+ virtual void notifyTreeItem(int id, size_t item, size_t param) = 0;
virtual void notifyCompletion(int id, int param) = 0;
};
diff --git a/elenasrc3/gui/guieditor.h b/elenasrc3/gui/guieditor.h
index 6c5fb8faa6..0e0074b0cb 100644
--- a/elenasrc3/gui/guieditor.h
+++ b/elenasrc3/gui/guieditor.h
@@ -20,6 +20,7 @@ namespace elena_lang
constexpr auto STYLE_SELECTION = 2;
constexpr auto STYLE_TRACE_LINE = 3;
constexpr auto STYLE_ERROR_LINE = 4;
+ constexpr auto STYLE_BREAKPOINT = 5;
//#define STYLE_KEYWORD 3
//#define STYLE_COMMENT 4
//#define STYLE_OPERATOR 5
@@ -28,9 +29,8 @@ namespace elena_lang
//#define STYLE_STRING 8
//#define STYLE_HINT 9 // !! not used
//#define STYLE_TRACE 12
- //#define STYLE_BREAKPOINT 13
//#define STYLE_HIGHLIGHTED_BRACKET 14
- constexpr auto STYLE_MAX = 4;
+ constexpr auto STYLE_MAX = 5;
// --- ClipboardBase ----
class ClipboardBase
@@ -110,7 +110,7 @@ namespace elena_lang
TextViewModelBase()
{
this->_currentView = nullptr;
- this->lineNumbersVisible = false;
+ this->lineNumbersVisible = true; // !! temporal hard-coded
this->empty = true;
this->fontSize = 10;
this->schemeIndex = 0;
@@ -121,8 +121,7 @@ namespace elena_lang
class TextViewControllerBase
{
public:
- virtual void newDocument(TextViewModelBase* model, ustr_t name,
- int notifyMessage) = 0;
+ virtual void newDocument(TextViewModelBase* model, ustr_t name) = 0;
virtual bool openDocument(TextViewModelBase* model, ustr_t name, path_t path,
FileEncoding encoding) = 0;
diff --git a/elenasrc3/gui/view.cpp b/elenasrc3/gui/view.cpp
index 5a8dd4452c..e0115ec3fa 100644
--- a/elenasrc3/gui/view.cpp
+++ b/elenasrc3/gui/view.cpp
@@ -155,6 +155,10 @@ void TextViewModel :: addDocumentView(ustr_t name, Text* text, path_t path)
docView->setSize(_size);
_documents.add(new DocumentViewScope(name, path, docView));
+ if (emptystr(path)) {
+ docView->markAsUnnamed();
+ docView->markAsModified();
+ }
for (auto it = _docListeners.start(); !it.eof(); ++it) {
docView->attachNotifier(*it);
diff --git a/elenasrc3/gui/windows/wincommon.cpp b/elenasrc3/gui/windows/wincommon.cpp
index 22ff855862..8eff1907d0 100644
--- a/elenasrc3/gui/windows/wincommon.cpp
+++ b/elenasrc3/gui/windows/wincommon.cpp
@@ -221,6 +221,19 @@ void WindowApp :: notifySelection(int messageCode, size_t param)
::SendMessage(_hwnd, WM_NOTIFY, 0, (LPARAM)¬ification);
}
+void WindowApp :: notifyTreeItem(int messageCode, size_t item, size_t param)
+{
+ TreeItemNMHDR notification;
+
+ notification.nmhrd.code = STATUS_TREEITEM;
+ notification.nmhrd.hwndFrom = _hwnd;
+ notification.code = messageCode;
+ notification.item = item;
+ notification.param = param;
+
+ ::SendMessage(_hwnd, WM_NOTIFY, 0, (LPARAM)¬ification);
+}
+
void WindowApp::notifyCompletion(int messageCode, int param)
{
CompletionNMHDR notification;
diff --git a/elenasrc3/gui/windows/wincommon.h b/elenasrc3/gui/windows/wincommon.h
index ead8eb9716..4d19f862ce 100644
--- a/elenasrc3/gui/windows/wincommon.h
+++ b/elenasrc3/gui/windows/wincommon.h
@@ -33,7 +33,7 @@ namespace elena_lang
constexpr int STATUS_NOTIFICATION = 0x101;
constexpr int STATUS_SELECTION = 0x102;
constexpr int STATUS_COMPLETION = 0x103;
- //constexpr int NMHDR_Model = 0x102;
+ constexpr int STATUS_TREEITEM = 0x104;
// --- ExtNMHDR ---
struct StatusNMHDR
@@ -50,6 +50,14 @@ namespace elena_lang
size_t param;
};
+ struct TreeItemNMHDR
+ {
+ NMHDR nmhrd;
+ int code;
+ size_t item;
+ size_t param;
+ };
+
struct CompletionNMHDR
{
NMHDR nmhrd;
@@ -195,6 +203,7 @@ namespace elena_lang
void notify(int messageCode, NotificationStatus status) override;
void notifySelection(int id, size_t param) override;
+ void notifyTreeItem(int id, size_t item, size_t param) override;
void notifyCompletion(int id, int param) override;
WindowApp(HINSTANCE instance, wstr_t accelerators)
diff --git a/elenasrc3/gui/windows/winmenu.cpp b/elenasrc3/gui/windows/winmenu.cpp
index 533d5b6da0..60296d94ac 100644
--- a/elenasrc3/gui/windows/winmenu.cpp
+++ b/elenasrc3/gui/windows/winmenu.cpp
@@ -5,6 +5,7 @@
//---------------------------------------------------------------------------
#include "winmenu.h"
+#include
using namespace elena_lang;
@@ -30,3 +31,35 @@ RootMenu :: RootMenu(HMENU hMenu)
{
_handle = hMenu;
}
+
+// --- ContextMenu ---
+
+ContextMenu::ContextMenu()
+{
+
+}
+
+ContextMenu::~ContextMenu()
+{
+ if (isLoaded())
+ ::DestroyMenu(_handle);
+}
+
+void ContextMenu :: create(int count, MenuInfo* items)
+{
+ _handle = ::CreatePopupMenu();
+
+ for (int i = 0; i < count; i++) {
+ if (items[i].key == 0) {
+ ::AppendMenu(_handle, MF_SEPARATOR, 0, _T(""));
+ }
+ else ::AppendMenu(_handle, MF_STRING, items[i].key, items[i].text);
+ }
+
+}
+
+void ContextMenu :: show(HWND parent, Point& p) const
+{
+ ::TrackPopupMenu(_handle, TPM_LEFTALIGN, p.x, p.y, 0, parent, nullptr);
+}
+
diff --git a/elenasrc3/gui/windows/winmenu.h b/elenasrc3/gui/windows/winmenu.h
index 27bfc62fee..985af6b017 100644
--- a/elenasrc3/gui/windows/winmenu.h
+++ b/elenasrc3/gui/windows/winmenu.h
@@ -1,7 +1,7 @@
//---------------------------------------------------------------------------
// E L E N A P r o j e c t: ELENA IDE
// WinAPI Menu Header File
-// (C)2021-2022, by Aleksey Rakov
+// (C)2021-2023, by Aleksey Rakov
//---------------------------------------------------------------------------
#ifndef WINMENU_H
@@ -42,6 +42,29 @@ namespace elena_lang
public:
RootMenu(HMENU hMenu);
};
+
+ // --- ContextMenu ---
+
+ struct MenuInfo
+ {
+ size_t key;
+ const wchar_t* text;
+ };
+
+ class ContextMenu : public MenuBase
+ {
+ bool isLoaded() const { return _handle != nullptr; }
+
+ public:
+ void create(int count, MenuInfo* items);
+
+ void show(HWND parent, Point& p) const;
+
+ ContextMenu();
+ virtual ~ContextMenu();
+ };
+
+
}
#endif
diff --git a/elenasrc3/gui/windows/winsdi.cpp b/elenasrc3/gui/windows/winsdi.cpp
index 1b8a19644f..9f780f1814 100644
--- a/elenasrc3/gui/windows/winsdi.cpp
+++ b/elenasrc3/gui/windows/winsdi.cpp
@@ -399,15 +399,10 @@ LRESULT SDIWindow :: proceed(UINT message, WPARAM wParam, LPARAM lParam)
case WM_SIZING:
onResizing((RECT*)lParam);
return TRUE;
- case WM_SIZE:
- if (wParam != SIZE_MINIMIZED) {
- onResize();
- }
- return 0;
case WM_COMMAND:
if(!onCommand(LOWORD(wParam)))
return DefWindowProc(_handle, message, wParam, lParam);
- break;
+ return 0;
//case WM_PAINT:
//{
// PAINTSTRUCT ps;
@@ -420,7 +415,7 @@ LRESULT SDIWindow :: proceed(UINT message, WPARAM wParam, LPARAM lParam)
//}
case WM_DESTROY:
PostQuitMessage(0);
- break;
+ return 0;
case WM_ACTIVATE:
if (LOWORD(wParam) != WA_INACTIVE) {
onActivate();
diff --git a/elenasrc3/gui/windows/wintabbar.cpp b/elenasrc3/gui/windows/wintabbar.cpp
index 1c6d06d137..a4de439d68 100644
--- a/elenasrc3/gui/windows/wintabbar.cpp
+++ b/elenasrc3/gui/windows/wintabbar.cpp
@@ -314,5 +314,7 @@ void TabBar :: refresh()
{
if (_current)
_current->refresh();
+
+ CustomTabBar::refresh();
}
diff --git a/elenasrc3/gui/windows/wintextview.cpp b/elenasrc3/gui/windows/wintextview.cpp
index e50b58ff95..612dba2ad1 100644
--- a/elenasrc3/gui/windows/wintextview.cpp
+++ b/elenasrc3/gui/windows/wintextview.cpp
@@ -249,6 +249,8 @@ void TextViewWindow :: paint(Canvas& canvas, Rectangle clientRect)
int marginWidth = _styles->getMarginWidth() + getLineNumberMargin();
if (!_cached) {
+ String lineNumber;
+
if (!defaultStyle->valid) {
_styles->validate(&canvas);
@@ -299,6 +301,27 @@ void TextViewWindow :: paint(Canvas& canvas, Rectangle clientRect)
x = clientRect.topLeft.x + marginWidth;
y += lineHeight;
+
+ if (_model->lineNumbersVisible) {
+ lineNumber.clear();
+ lineNumber.appendInt(reader.row + 1);
+
+ int numLen = getlength_int(lineNumber.str());
+ canvas.drawTextClipped(
+ Rectangle(x - marginWidth, y, marginWidth, lineHeight + 1),
+ x - marginStyle->avgCharWidth * numLen - 6,
+ y,
+ lineNumber.str(),
+ numLen,
+ marginStyle);
+ }
+
+ // !! HOTFIX: allow to see breakpoint ellipse on margin if STYLE_TRACELINe set for this line
+ if (reader.toggleMark) {
+ canvas.drawEllipse(Rectangle(3, y + 2, 12, 12), *style);
+
+ reader.toggleMark = false;
+ }
}
if (reader.bandStyle) {
canvas.fillRectangle(Rectangle(x, y, clientRect.bottomRight.x - x, lineHeight + 1), style);
@@ -444,7 +467,22 @@ void TextViewWindow :: onButtonUp()
releaseMouse();
}
-void TextViewWindow :: onMouseMove(short wheelDelta, bool kbCtrl)
+void TextViewWindow :: onMouseMove(Point point, bool kbLButton)
+{
+ auto docView = _model->DocView();
+ if (kbLButton && isMouseCaptured() && docView != nullptr) {
+ DocumentChangeStatus status = {};
+ int col = 0, row = 0;
+ bool margin = false;
+ mouseToScreen(point, col, row, margin);
+
+ docView->moveToFrame(status, col, row, true);
+
+ onDocumentUpdate(status);
+ }
+}
+
+void TextViewWindow :: onMouseWheel(short wheelDelta, bool kbCtrl)
{
DocumentChangeStatus status = {};
auto docView = _model->DocView();
@@ -541,7 +579,10 @@ LRESULT TextViewWindow :: proceed(UINT message, WPARAM wParam, LPARAM lParam)
onDoubleClick(nullptr);
return 0;
case WM_MOUSEWHEEL:
- onMouseMove(HIWORD(wParam), (wParam & MK_CONTROL) != 0);
+ onMouseWheel(HIWORD(wParam), (wParam & MK_CONTROL) != 0);
+ return 0;
+ case WM_MOUSEMOVE:
+ onMouseMove(Point(LOWORD(lParam), HIWORD(lParam)), (wParam & MK_LBUTTON) != 0);
return 0;
case WM_KEYDOWN:
if (onKeyDown((int)wParam, isKeyDown(VK_SHIFT), isKeyDown(VK_CONTROL))) {
diff --git a/elenasrc3/gui/windows/wintextview.h b/elenasrc3/gui/windows/wintextview.h
index 8ad25b5145..a9a271c751 100644
--- a/elenasrc3/gui/windows/wintextview.h
+++ b/elenasrc3/gui/windows/wintextview.h
@@ -97,6 +97,8 @@ namespace elena_lang
return (bar == SB_VERT) ? getVScrollerPosition() : getHScrollerPosition();
}
+ bool isMouseCaptured() { return _mouseCaptured; }
+
bool getScrollInfo(int bar, SCROLLINFO* info);
void resizeDocument();
@@ -122,8 +124,9 @@ namespace elena_lang
void releaseMouse();
void onButtonDown(Point point, bool kbShift);
+ void onMouseMove(Point point, bool kbLButton);
void onButtonUp();
- void onMouseMove(short wheelDelta, bool kbCtrl);
+ void onMouseWheel(short wheelDelta, bool kbCtrl);
void onDoubleClick(NMHDR* hdr) override;
bool onKeyDown(int keyCode, bool kbShift, bool kbCtrl);
diff --git a/elenasrc3/gui/windows/wintreeview.cpp b/elenasrc3/gui/windows/wintreeview.cpp
index 811dab88f4..459176b092 100644
--- a/elenasrc3/gui/windows/wintreeview.cpp
+++ b/elenasrc3/gui/windows/wintreeview.cpp
@@ -166,3 +166,17 @@ void TreeView :: remove(TreeViewItem item)
{
TreeView_DeleteItem(_handle, item);
}
+
+TreeViewItem TreeView :: hitTest(short x, short y)
+{
+ TVHITTESTINFO hit;
+
+ hit.pt.x = x;
+ hit.pt.y = y;
+
+ ::ScreenToClient(_handle, &hit.pt);
+
+ HTREEITEM i = TreeView_HitTest(_handle, &hit);
+
+ return i;
+}
diff --git a/elenasrc3/gui/windows/wintreeview.h b/elenasrc3/gui/windows/wintreeview.h
index 75e474d831..c084df2b05 100644
--- a/elenasrc3/gui/windows/wintreeview.h
+++ b/elenasrc3/gui/windows/wintreeview.h
@@ -17,7 +17,10 @@ namespace elena_lang
// --- TreeView ---
class TreeView : public ControlBase
{
- NotifierBase* _notifier;
+ protected:
+ NotifierBase* _notifier;
+
+ private:
int _notificationId;
bool _persistentSelection;
@@ -31,6 +34,8 @@ namespace elena_lang
void onSelChanged() override;
+ virtual void onItemExpand(TreeViewItem item) {}
+
void select(TreeViewItem item);
void expand(TreeViewItem item);
void collapse(TreeViewItem item);
@@ -46,6 +51,8 @@ namespace elena_lang
TreeViewItem insertTo(TreeViewItem parent, const wchar_t* caption, size_t param, bool isNode);
+ TreeViewItem hitTest(short x, short y);
+
void clear(TreeViewItem item);
void remove(TreeViewItem item);
diff --git a/elenasrc3/ide/debugcontroller.cpp b/elenasrc3/ide/debugcontroller.cpp
index e287a484e5..8bf4b99c38 100644
--- a/elenasrc3/ide/debugcontroller.cpp
+++ b/elenasrc3/ide/debugcontroller.cpp
@@ -64,6 +64,21 @@ void DebugInfoProvider :: retrievePath(ustr_t name, PathString& path, path_t ext
}
}
+void DebugInfoProvider :: fixNamespace(NamespaceString& name)
+{
+ PathString path;
+ retrievePath(*name, path, _T("dnl"));
+
+ while (name.length() != 0) {
+ retrievePath(*name, path, _T("dnl"));
+
+ if (!PathUtil::ifExist(*path)) {
+ name.trimLastSubNs();
+ }
+ else break;
+ }
+}
+
ModuleBase* DebugInfoProvider :: loadDebugModule(ustr_t reference)
{
NamespaceString name(reference);
@@ -209,6 +224,7 @@ bool DebugInfoProvider :: loadSymbol(ustr_t reference, StreamReader& addressRead
case DebugSymbol::Local:
case DebugSymbol::LocalAddress:
case DebugSymbol::IntLocalAddress:
+ case DebugSymbol::UIntLocalAddress:
case DebugSymbol::LongLocalAddress:
case DebugSymbol::RealLocalAddress:
case DebugSymbol::ByteArrayAddress:
@@ -356,7 +372,7 @@ addr_t DebugInfoProvider :: findNearestAddress(ModuleBase* module, ustr_t path,
int nearestRow = 0;
bool skipping = true;
for (size_t i = 0; i < count; i++) {
- if (info[i].symbol == DebugSymbol::Procedure) {
+ if (info[i].symbol == DebugSymbol::Procedure && info[i].addresses.source.nameRef != INVALID_ADDR) {
ustr_t procPath = (const char*)strings->get(info[i].addresses.source.nameRef);
if (procPath.compare(path)) {
skipping = false;
@@ -365,7 +381,7 @@ addr_t DebugInfoProvider :: findNearestAddress(ModuleBase* module, ustr_t path,
else if (info[i].symbol == DebugSymbol::End) {
skipping = true;
}
- else if ((info[i].symbol & DebugSymbol::DebugMask) == DebugSymbol::Breakpoint) {
+ else if (!skipping && (info[i].symbol & DebugSymbol::DebugMask) == DebugSymbol::Breakpoint) {
if (_abs(nearestRow - row) > _abs(info[i].row - row)) {
nearestRow = info[i].row;
@@ -478,7 +494,6 @@ DebugController :: DebugController(DebugProcessBase* process, ProjectModel* mode
_sourceModel = sourceModel;
_model = model;
_notifier = notifier;
- _currentModule = nullptr;
_currentPath = nullptr;
_sourceController = sourceController;
}
@@ -532,7 +547,7 @@ void DebugController :: debugThread()
}
}
_running = false;
- //_currentModule = nullptr;
+ _currentModule.clear();
_process->clearEvents();
onStop();
@@ -650,12 +665,11 @@ void DebugController :: onCurrentStep(DebugLineInfo* lineInfo, ustr_t moduleName
if (lineInfo) {
_sourceModel->clearTraceLine();
- if (!moduleName.compare(_currentModule) || !sourcePath.compare(_currentPath)) {
- _currentModule = moduleName;
+ if (!_currentModule.compare(moduleName) || !sourcePath.compare(_currentPath)) {
+ _currentModule.copy(moduleName);
_currentPath = sourcePath;
- PathString path(sourcePath);
- found = _sourceController->selectSource(_model, _sourceModel, moduleName, *path);
+ PathString path(sourcePath);found = _sourceController->selectSource(_model, _sourceModel, moduleName, *path);
}
if (found) {
@@ -672,7 +686,7 @@ void DebugController :: onStop()
_process->reset();
_provider.clear();
- _currentModule = nullptr;
+ _currentModule.clear();
_currentPath = nullptr;
_notifier->notifyCompletion(NOTIFY_DEBUGGER_RESULT, DEBUGGER_STOPPED);
@@ -719,6 +733,17 @@ void DebugController :: runToCursor(ustr_t ns, ustr_t path, int row)
_process->setEvent(DEBUG_RESUME);
}
+void DebugController :: addBreakpoint(Breakpoint* bp)
+{
+ ModuleBase* currentModule = _provider.resolveModule(*bp->module);
+ if (currentModule != nullptr) {
+ addr_t address = _provider.findNearestAddress(currentModule, *bp->source, bp->row);
+ if (address != INVALID_ADDR) {
+ _process->addBreakpoint(address);
+ }
+ }
+}
+
void DebugController :: stepInto()
{
if (_running || !_process->isStarted())
@@ -796,6 +821,7 @@ bool DebugController :: startThread()
while (_process->waitForEvent(DEBUG_ACTIVE, 0));
//_listener->onStart();
+ _notifier->notify(NOTIFY_DEBUG_START, 0);
return _process->isStarted();
}
@@ -807,7 +833,7 @@ void DebugController :: clearBreakpoints()
bool DebugController :: start(path_t programPath, path_t arguments, bool debugMode)
{
- //_currentModule = NULL;
+ _currentModule.clear();
_debuggee.copy(programPath);
_arguments.copy(arguments);
@@ -842,7 +868,7 @@ void DebugController :: loadDebugSection(StreamReader& reader, bool starting)
if (!reader.eof()) {
_provider.load(reader, starting, _process);
- //_listener->onDebuggerHook();
+ _notifier->notify(NOTIFY_DEBUG_LOAD, 0);
_provider.setDebugInfoSize(reader.position());
@@ -1014,6 +1040,17 @@ void* DebugController :: readIntLocal(ContextBrowserBase* watch, void* parent, a
else return nullptr;
}
+void* DebugController :: readUIntLocal(ContextBrowserBase* watch, void* parent, addr_t address, ustr_t name, int level)
+{
+ if (level > 0) {
+ unsigned int value = _process->getDWORD(address);
+
+ WatchContext context = { parent, address };
+ return watch->addOrUpdateUINT(&context, name, value);
+ }
+ else return nullptr;
+}
+
void* DebugController :: readLongLocal(ContextBrowserBase* watch, void* parent, addr_t address, ustr_t name, int level)
{
if (level > 0) {
@@ -1135,6 +1172,11 @@ void DebugController :: readAutoContext(ContextBrowserBase* watch, int level, Wa
_process->getStackItemAddress(getFPOffset(lineInfo[index].addresses.local.offset, _process->getDataOffset())),
(const char*)lineInfo[index].addresses.local.nameRef, level - 1);
break;
+ case DebugSymbol::UIntLocalAddress:
+ item = readUIntLocal(watch, nullptr,
+ _process->getStackItemAddress(getFPOffset(lineInfo[index].addresses.local.offset, _process->getDataOffset())),
+ (const char*)lineInfo[index].addresses.local.nameRef, level - 1);
+ break;
case DebugSymbol::ByteArrayAddress:
item = readByteArrayLocal(watch, nullptr,
_process->getStackItemAddress(getFPOffset(lineInfo[index].addresses.local.offset, _process->getDataOffset())),
@@ -1220,3 +1262,8 @@ void DebugController :: readAutoContext(ContextBrowserBase* watch, int level, Wa
}
}
}
+
+void DebugController::resolveNamespace(NamespaceString& ns)
+{
+ _provider.fixNamespace(ns);
+}
diff --git a/elenasrc3/ide/debugcontroller.h b/elenasrc3/ide/debugcontroller.h
index b046e0b6f1..573dcc08cf 100644
--- a/elenasrc3/ide/debugcontroller.h
+++ b/elenasrc3/ide/debugcontroller.h
@@ -95,6 +95,8 @@ namespace elena_lang
DebugLineInfo* seekClassInfo(addr_t address, IdentifierString& className, addr_t vmtAddress, ref_t flags);
+ void fixNamespace(NamespaceString& str);
+
void clear()
{
_entryPoint = 0;
@@ -224,7 +226,7 @@ namespace elena_lang
NotifierBase* _notifier;
DebugSourceController* _sourceController;
- ustr_t _currentModule;
+ IdentifierString _currentModule;
ustr_t _currentPath;
void debugThread() override;
@@ -244,6 +246,7 @@ namespace elena_lang
void* readObject(ContextBrowserBase* watch, void* parent, addr_t address, ustr_t name, int level, ustr_t className = nullptr);
void* readIntLocal(ContextBrowserBase* watch, void* parent, addr_t address, ustr_t name, int level);
+ void* readUIntLocal(ContextBrowserBase* watch, void* parent, addr_t address, ustr_t name, int level);
void* readLongLocal(ContextBrowserBase* watch, void* parent, addr_t address, ustr_t name, int level);
void* readRealLocal(ContextBrowserBase* watch, void* parent, addr_t address, ustr_t name, int level);
void* readByteArrayLocal(ContextBrowserBase* watch, void* parent, addr_t address, ustr_t name, int level);
@@ -265,10 +268,13 @@ namespace elena_lang
void stepInto();
void stop();
void runToCursor(ustr_t name, ustr_t path, int row);
+ void addBreakpoint(Breakpoint* bp);
void readAutoContext(ContextBrowserBase* watch, int level, WatchItems* refreshedItems);
void readContext(ContextBrowserBase* watch, void* parentItem, addr_t address, int level);
+ void resolveNamespace(NamespaceString& ns);
+
virtual void clearDebugInfo()
{
_provider.clear();
diff --git a/elenasrc3/ide/editframe.cpp b/elenasrc3/ide/editframe.cpp
index a336c89b9e..84a69b4c95 100644
--- a/elenasrc3/ide/editframe.cpp
+++ b/elenasrc3/ide/editframe.cpp
@@ -26,7 +26,7 @@ void SourceViewModel :: setTraceLine(int row, bool withCursor)
_currentView->removeMarker(STYLE_TRACE_LINE, status);
- _currentView->addMarker(row, STYLE_TRACE_LINE, false, status);
+ _currentView->addMarker(row, STYLE_TRACE_LINE, false, false, status);
if (withCursor)
_currentView->setCaret({ 0, row - 1 }, false, status);
@@ -48,7 +48,7 @@ void SourceViewModel :: setErrorLine(int row, int column, bool withCursor)
_currentView->removeMarker(STYLE_ERROR_LINE, status);
- _currentView->addMarker(row, STYLE_ERROR_LINE, true, status);
+ _currentView->addMarker(row, STYLE_ERROR_LINE, true, false, status);
if (withCursor)
_currentView->setCaret({ column - 1, row - 1 }, false, status);
diff --git a/elenasrc3/ide/eng/messages.h b/elenasrc3/ide/eng/messages.h
index d9ba881cb5..1668cd5617 100644
--- a/elenasrc3/ide/eng/messages.h
+++ b/elenasrc3/ide/eng/messages.h
@@ -16,6 +16,7 @@ namespace elena_lang
constexpr auto SAVEAS_PROJECT_CAPTION = _T("Save File As");
constexpr auto QUESTION_SAVE_FILECHANGES = _T("Save changes to ");
+ constexpr auto QUESTION_CLOSE_UNSAVED = _T("Close the tab anyway");
}
diff --git a/elenasrc3/ide/idecommon.cpp b/elenasrc3/ide/idecommon.cpp
index 2212e1b968..0919f6b0f2 100644
--- a/elenasrc3/ide/idecommon.cpp
+++ b/elenasrc3/ide/idecommon.cpp
@@ -37,6 +37,21 @@ void* ContextBrowserBase :: addOrUpdateDWORD(WatchContext* context, ustr_t varia
return item;
}
+void* ContextBrowserBase :: addOrUpdateUINT(WatchContext* context, ustr_t variableName, int value)
+{
+ void* item = findWatchNodeStartingWith(context, variableName);
+ if (item != nullptr) {
+ editWatchNode(item, variableName, "", context->address);
+ }
+ else item = addWatchNode(context->root, variableName, "", context->address);
+
+ WatchContext dwordContext = { item };
+
+ populateUINT(&dwordContext, value);
+
+ return item;
+}
+
void* ContextBrowserBase :: addOrUpdateWORD(WatchContext* context, ustr_t variableName, short value)
{
void* item = findWatchNodeStartingWith(context, variableName);
@@ -95,6 +110,20 @@ void ContextBrowserBase :: populateDWORD(WatchContext* context, unsigned value)
}
+void ContextBrowserBase :: populateUINT(WatchContext* context, unsigned value)
+{
+ String number;
+ /*if (_browser->isHexNumberMode()) {
+ number.appendHex(value);
+ number.append('h');
+ }
+ else*/ number.appendUInt(value);
+
+ clearNode(context->root);
+ populateNode(context->root, number.str());
+
+}
+
void ContextBrowserBase :: populateString(WatchContext* context, const char* value)
{
clearNode(context->root);
@@ -124,7 +153,7 @@ void* ContextBrowserBase :: addOrUpdateQWORD(WatchContext* context, ustr_t varia
return item;
}
-void ContextBrowserBase :: populateQWORD(WatchContext* context, unsigned long long value)
+void ContextBrowserBase :: populateQWORD(WatchContext* context, long long value)
{
String number;
/*if (_browser->isHexNumberMode()) {
diff --git a/elenasrc3/ide/idecommon.h b/elenasrc3/ide/idecommon.h
index 82a9da6c53..ccd4b47bd8 100644
--- a/elenasrc3/ide/idecommon.h
+++ b/elenasrc3/ide/idecommon.h
@@ -7,9 +7,10 @@
#ifndef IDECOMMON_H
#define IDECOMMON_H
+#include "elena.h"
#include "guicommon.h"
-#define IDE_REVISION_NUMBER 0x004A
+#define IDE_REVISION_NUMBER 0x0052
namespace elena_lang
{
@@ -17,6 +18,10 @@ namespace elena_lang
constexpr auto NAMESPACE_CATEGORY = "configuration/project/namespace";
constexpr auto TARGET_SUB_CATEGORY = "project/executable";
+ constexpr auto TEMPLATE_SUB_CATEGORY = "project/template";
+ constexpr auto NAMESPACE_SUB_CATEGORY = "project/namespace";
+ constexpr auto OPTIONS_SUB_CATEGORY = "project/options";
+
constexpr auto MODULE_CATEGORY = "files/*";
constexpr auto WIN_X86_KEY = "Win_x86";
@@ -49,6 +54,9 @@ namespace elena_lang
constexpr int NOTIFY_IDE_CHANGE = 13;
constexpr int NOTIFY_ONSTART = 14;
constexpr int NOTIFY_REFRESH = 15;
+ constexpr int NOTIFY_DEBUG_START = 16;
+ constexpr int NOTIFY_DEBUG_CONTEXT_EXPANDED = 17;
+ constexpr int NOTIFY_DEBUG_LOAD = 18;
// --- Notification statuses ---
constexpr NotificationStatus IDE_ONSTART = -1;
@@ -161,12 +169,18 @@ namespace elena_lang
virtual void populateNode(void* item, ustr_t value) = 0;
public:
+ virtual void clearRootNode() = 0;
virtual void expandRootNode() = 0;
+ virtual void expandNode(size_t param) = 0;
+
+ virtual void refreshCurrentNode() = 0;
+
virtual void* addOrUpdate(WatchContext* root, ustr_t name, ustr_t className);
virtual void* addOrUpdateBYTE(WatchContext* root, ustr_t name, int value);
virtual void* addOrUpdateWORD(WatchContext* root, ustr_t name, short value);
virtual void* addOrUpdateDWORD(WatchContext* root, ustr_t name, int value);
+ virtual void* addOrUpdateUINT(WatchContext* root, ustr_t name, int value);
virtual void* addOrUpdateQWORD(WatchContext* root, ustr_t name, long long value);
virtual void* addOrUpdateFLOAT64(WatchContext* root, ustr_t name, double value);
@@ -174,10 +188,13 @@ namespace elena_lang
virtual void populateWORD(WatchContext* root, unsigned short value);
virtual void populateDWORD(WatchContext* root, unsigned int value);
- virtual void populateQWORD(WatchContext* root, unsigned long long value);
+ virtual void populateUINT(WatchContext* root, unsigned int value);
+ virtual void populateQWORD(WatchContext* root, long long value);
virtual void populateFLOAT64(WatchContext* root, double value);
virtual void populateString(WatchContext* root, const char* value);
virtual void populateWideString(WatchContext* root, const wide_c* value);
+
+ //virtual void browse() = 0;
};
// --- DebugControllerBase ---
@@ -256,6 +273,7 @@ namespace elena_lang
virtual double getFLOAT64(addr_t address) = 0;
virtual void setBreakpoint(addr_t address, bool withStackLevelControl) = 0;
+ virtual void addBreakpoint(addr_t address) = 0;
virtual void addStep(addr_t address, void* current) = 0;
@@ -267,6 +285,19 @@ namespace elena_lang
virtual ~DebugProcessBase() = default;
};
+ struct Breakpoint
+ {
+ int row;
+ IdentifierString source;
+ IdentifierString module;
+ void* param;
+
+ Breakpoint(int row, ustr_t source, ustr_t module)
+ : row(row), source(source), module(module), param(nullptr)
+ {
+ }
+ };
+
struct GUISettinngs
{
bool withTabAboverscore;
diff --git a/elenasrc3/ide/idecontroller.cpp b/elenasrc3/ide/idecontroller.cpp
index 5c1b6346e4..4659257835 100644
--- a/elenasrc3/ide/idecontroller.cpp
+++ b/elenasrc3/ide/idecontroller.cpp
@@ -35,18 +35,22 @@ inline ustr_t getPlatformName(PlatformType type)
// --- SourceViewController ---
-void SourceViewController :: newSource(TextViewModelBase* model, ustr_t caption, bool autoSelect)
+void SourceViewController :: newSource(TextViewModelBase* model, ustr_t caption, bool autoSelect, NotificationStatus& status)
{
-// IdentifierString tabName("unnamed");
+ IdentifierString tabName("unnamed");
- //newDocument(model, caption, model->empty ? NOTIFY_CURRENTVIEW_SHOW : 0);
+ bool empty = model->empty;
+
+ newDocument(model, caption);
- //if (autoSelect) {
- // selectDocument(model, caption);
+ if (empty)
+ status |= FRAME_VISIBILITY_CHANGED;
- // model->DocView()->status.unnamed = true;
- // model->DocView()->status.modifiedMode = true;
- //}
+ if (autoSelect) {
+ int index = model->getDocumentIndex(caption);
+
+ selectDocument(model, index, status);
+ }
}
bool SourceViewController :: openSource(TextViewModelBase* model, ustr_t caption, path_t sourcePath,
@@ -133,7 +137,7 @@ void ProjectController :: defineFullPath(ProjectModel& model, ustr_t ns, path_t
}
}
-path_t ProjectController :: retrieveSourceName(ProjectModel* model, path_t sourcePath, ReferenceName& name)
+path_t ProjectController :: retrieveSourceName(ProjectModel* model, path_t sourcePath, NamespaceString& name)
{
size_t projectPathLen = model->projectPath.length();
@@ -144,6 +148,8 @@ path_t ProjectController :: retrieveSourceName(ProjectModel* model, path_t sourc
name.copy(model->getPackage());
if (path.length() > projectPathLen) {
name.pathToName(*path + projectPathLen);
+
+ _debugController.resolveNamespace(name);
}
return sourcePath + projectPathLen;
}
@@ -154,6 +160,8 @@ path_t ProjectController :: retrieveSourceName(ProjectModel* model, path_t sourc
if (!rootPath.empty() && PathUtil::compare(sourcePath, rootPath, rootPathLen)) {
name.pathToName(sourcePath + rootPathLen);
+ _debugController.resolveNamespace(name);
+
return sourcePath + rootPathLen;
}
else {
@@ -167,7 +175,7 @@ path_t ProjectController :: retrieveSourceName(ProjectModel* model, path_t sourc
return sourcePath;
}
-void ProjectController :: defineSourceName(ProjectModel* model, path_t path, ReferenceName& retVal)
+void ProjectController :: defineSourceName(ProjectModel* model, path_t path, NamespaceString& retVal)
{
if (path.empty()) {
retVal.copy("undefined");
@@ -285,10 +293,13 @@ void ProjectController :: runToCursor(ProjectModel& model, SourceViewModel& sour
ustr_t currentSource = sourceModel.getDocumentName(index);
path_t currentPath = sourceModel.getDocumentPath(index);
- ReferenceName ns;
+ NamespaceString ns;
currentPath = retrieveSourceName(&model, currentPath, ns);
- IdentifierString pathStr(currentPath);
+ // !! temporal solution : skip the project folder
+ size_t rootNsLen = (*ns).find('\'');
+
+ IdentifierString pathStr(currentPath + rootNsLen + 1);
_debugController.runToCursor(*ns, *pathStr, currentDoc->getCaret().y);
}
}
@@ -347,6 +358,27 @@ void ProjectController :: loadConfig(ProjectModel& model, ConfigFile& config, Co
model.target.copy(value.str());
}
+ auto templateOption = config.selectNode(configRoot, TEMPLATE_SUB_CATEGORY);
+ if (!templateOption.isNotFound()) {
+ templateOption.readContent(value);
+
+ model.templateName.copy(value.str());
+ }
+
+ auto nsOption = config.selectNode(configRoot, NAMESPACE_SUB_CATEGORY);
+ if (!nsOption.isNotFound()) {
+ nsOption.readContent(value);
+
+ model.package.copy(value.str());
+ }
+
+ auto optionsOption = config.selectNode(configRoot, OPTIONS_SUB_CATEGORY);
+ if (!optionsOption.isNotFound()) {
+ optionsOption.readContent(value);
+
+ model.options.copy(value.str());
+ }
+
// load source files
DynamicString subNs;
DynamicString path;
@@ -375,6 +407,18 @@ void ProjectController :: loadConfig(ProjectModel& model, ConfigFile& config, Co
}
}
+NotificationStatus ProjectController :: newProject(ProjectModel& model)
+{
+ model.sources.clear();
+
+ model.empty = false;
+ model.name.copy("unnamed");
+ model.package.copy("unnamed");
+ model.notSaved = true;
+
+ return PROJECT_CHANGED;
+}
+
NotificationStatus ProjectController :: openProject(ProjectModel& model, path_t projectFile)
{
ustr_t key = getPlatformName(_platform);
@@ -473,6 +517,57 @@ void ProjectController :: refreshDebugContext(ContextBrowserBase* contextBrowser
contextBrowser->removeUnused(refreshedItems);
}
+void ProjectController :: refreshDebugContext(ContextBrowserBase* contextBrowser, size_t param, addr_t address)
+{
+ _debugController.readContext(contextBrowser, (void*)param, address, 4);
+}
+
+void ProjectController :: toggleBreakpoint(ProjectModel& model, SourceViewModel& sourceModel, int row)
+{
+ auto currentDoc = sourceModel.DocView();
+ if (currentDoc != nullptr) {
+ if (row == -1)
+ row = currentDoc->getCaret().y + 1;
+
+ int index = sourceModel.getCurrentIndex();
+ ustr_t currentSource = sourceModel.getDocumentName(index);
+ path_t currentPath = sourceModel.getDocumentPath(index);
+
+ NamespaceString ns;
+ currentPath = retrieveSourceName(&model, currentPath, ns);
+
+ bool addMode = true;
+ IdentifierString pathStr(currentSource + currentSource.find(':') + 1);
+ for(auto it = model.breakpoints.start(); !it.eof(); ++it) {
+ auto bm = *it;
+ if (bm->row == row && bm->module.compare(*ns) && bm->source.compare(*pathStr)) {
+ model.breakpoints.cut(bm);
+ addMode = false;
+ break;
+ }
+ }
+
+ DocumentChangeStatus status = {};
+ if (addMode) {
+ model.breakpoints.add(new Breakpoint(row, *pathStr, *ns));
+
+ currentDoc->addMarker(row, STYLE_BREAKPOINT, false, true, status);
+ }
+ else {
+ currentDoc->removeMarker(row, STYLE_BREAKPOINT, status);
+ }
+
+ currentDoc->notifyOnChange(status);
+ }
+}
+
+void ProjectController :: loadBreakpoints(ProjectModel& model)
+{
+ for (auto it = model.breakpoints.start(); !it.eof(); ++it) {
+ _debugController.addBreakpoint(*it);
+ }
+}
+
// --- IDEController ---
inline int loadSetting(ConfigFile& config, ustr_t xpath, int defValue)
@@ -488,6 +583,19 @@ inline int loadSetting(ConfigFile& config, ustr_t xpath, int defValue)
else return defValue;
}
+inline void loadSetting(ConfigFile& config, ustr_t xpath, IdentifierString& retVal)
+{
+ // read target type; merge it with platform if required
+ ConfigFile::Node targetType = config.selectNode(xpath);
+ if (!targetType.isNotFound()) {
+ DynamicString key;
+ targetType.readContent(key);
+
+ retVal.copy(key.str());
+ }
+ else retVal.clear();
+}
+
inline void loadRecentFiles(ConfigFile& config, ustr_t xpath, ProjectPaths& paths)
{
DynamicString path;
@@ -505,6 +613,22 @@ inline void loadRecentFiles(ConfigFile& config, ustr_t xpath, ProjectPaths& path
}
}
+inline void loadCollectionKey(ConfigFile& config, ConfigFile::Node& rootNode, ustr_t xpath, StringList& keyList)
+{
+ DynamicString key;
+
+ ConfigFile::Collection list;
+ if (config.select(rootNode, xpath, list)) {
+ for (auto m_it = list.start(); !m_it.eof(); ++m_it) {
+ ConfigFile::Node keyNode = *m_it;
+
+ keyNode.readAttribute("key", key);
+
+ keyList.add(ustr_t(key.str()).clone());
+ }
+ }
+}
+
inline void saveSetting(ConfigFile& config, ustr_t xpath, int value)
{
String number;
@@ -524,6 +648,19 @@ inline void saveRecentFiles(ConfigFile& config, ustr_t xpath, ProjectPaths& path
}
}
+void IDEController :: loadSystemConfig(IDEModel* model, path_t path, ustr_t typeXPath, ustr_t platformXPath)
+{
+ ConfigFile config;
+ if (config.load(path, FileEncoding::UTF8)) {
+ ConfigFile::Node platformRoot = config.selectNode(PLATFORM_CATEGORY, platformXPath, [](ustr_t key, ConfigFile::Node& node)
+ {
+ return node.compareAttribute("key", key);
+ });
+
+ loadCollectionKey(config, platformRoot, typeXPath, model->projectModel.projectTypeList);
+ }
+}
+
bool IDEController :: loadConfig(IDEModel* model, path_t path)
{
model->projectModel.paths.configPath.copy(path);
@@ -589,16 +726,17 @@ bool IDEController :: selectSource(ProjectModel* model, SourceViewModel* sourceM
void IDEController :: doNewFile(IDEModel* model)
{
- ReferenceName sourceNameStr;
+ NotificationStatus status = NONE_CHANGED;
+ NamespaceString sourceNameStr;
projectController.defineSourceName(&model->projectModel, nullptr, sourceNameStr);
- sourceController.newSource(&model->sourceViewModel, *sourceNameStr, true);
-}
+ sourceController.newSource(&model->sourceViewModel, *sourceNameStr, true, status);
+
+ if (test(status, FRAME_VISIBILITY_CHANGED))
+ status |= IDE_LAYOUT_CHANGED;
-//bool IDEController :: openFile(IDEModel* model, path_t sourceFile)
-//{
-//
-//}
+ _notifier->notify(NOTIFY_IDE_CHANGE, status);
+}
bool IDEController :: openFile(IDEModel* model, path_t sourceFile, NotificationStatus& status)
{
@@ -618,7 +756,7 @@ bool IDEController :: openFile(SourceViewModel* model, ProjectModel* projectMode
return sourceController.selectDocument(model, index, status);
}
else {
- ReferenceName sourceNameStr;
+ NamespaceString sourceNameStr;
projectController.defineSourceName(projectModel, sourceFile, sourceNameStr);
sourceName = *sourceNameStr;
@@ -657,7 +795,7 @@ bool IDEController :: openProject(IDEModel* model, path_t projectFile, Notificat
return true;
}
-void IDEController :: doOpenFile(DialogBase& dialog, IDEModel* model)
+void IDEController :: doOpenFile(FileDialogBase& dialog, IDEModel* model)
{
NotificationStatus status = {};
@@ -677,7 +815,7 @@ void IDEController :: doOpenFile(DialogBase& dialog, IDEModel* model)
}
}
-bool IDEController :: doSaveFile(DialogBase& dialog, IDEModel* model, bool saveAsMode, bool forcedSave)
+bool IDEController :: doSaveFile(FileDialogBase& dialog, IDEModel* model, bool saveAsMode, bool forcedSave)
{
auto docView = model->sourceViewModel.DocView();
if (!docView)
@@ -688,7 +826,7 @@ bool IDEController :: doSaveFile(DialogBase& dialog, IDEModel* model, bool saveA
if (!dialog.saveFile(_T("l"), path))
return false;
- ReferenceName sourceNameStr;
+ NamespaceString sourceNameStr;
projectController.defineSourceName(&model->projectModel, *path, sourceNameStr);
sourceController.renameSource(&model->sourceViewModel, nullptr, *sourceNameStr, *path);
@@ -702,13 +840,28 @@ bool IDEController :: doSaveFile(DialogBase& dialog, IDEModel* model, bool saveA
return true;
}
-bool IDEController :: doOpenProject(DialogBase& dialog, IDEModel* model)
+void IDEController :: doNewProject(FileDialogBase& dialog, MessageDialogBase& mssgDialog,
+ ProjectSettingsBase& prjDialog, IDEModel* model)
+{
+ NotificationStatus status = NONE_CHANGED;
+
+ if (!closeAll(dialog, mssgDialog, model, status))
+ return;
+
+ status |= projectController.newProject(model->projectModel);
+
+ if (prjDialog.showModal()) {
+
+ }
+}
+
+bool IDEController :: doOpenProject(FileDialogBase& dialog, MessageDialogBase& mssgDialog, IDEModel* model)
{
NotificationStatus status = NONE_CHANGED;
PathString path;
if (dialog.openFile(path)) {
- if (!closeProject(dialog, model, status))
+ if (!closeProject(dialog, mssgDialog, model, status))
return false;
if (openProject(model, *path, status)) {
@@ -726,7 +879,7 @@ bool IDEController :: doOpenProject(DialogBase& dialog, IDEModel* model)
}
-bool IDEController :: doSaveProject(DialogBase& dialog, IDEModel* model, bool forcedMode)
+bool IDEController :: doSaveProject(FileDialogBase& dialog, IDEModel* model, bool forcedMode)
{
//// !! temporal
//if (!doSaveFile(dialog, model, false, forcedMode))
@@ -735,9 +888,10 @@ bool IDEController :: doSaveProject(DialogBase& dialog, IDEModel* model, bool fo
return true;
}
-bool IDEController :: closeProject(DialogBase& dialog, IDEModel* model, NotificationStatus& status)
+bool IDEController :: closeProject(FileDialogBase& dialog, MessageDialogBase& mssgDialog, IDEModel* model,
+ NotificationStatus& status)
{
- if (closeAll(dialog, model, status)) {
+ if (closeAll(dialog, mssgDialog, model, status)) {
status |= projectController.closeProject(model->projectModel);
return true;
@@ -745,11 +899,11 @@ bool IDEController :: closeProject(DialogBase& dialog, IDEModel* model, Notifica
else return false;
}
-bool IDEController :: doCloseProject(DialogBase& dialog, IDEModel* model)
+bool IDEController :: doCloseProject(FileDialogBase& dialog, MessageDialogBase& mssgDialog, IDEModel* model)
{
NotificationStatus status = NONE_CHANGED;
- if (closeAll(dialog, model, status)) {
+ if (closeAll(dialog, mssgDialog, model, status)) {
status |= projectController.closeProject(model->projectModel);
model->changeStatus(IDEStatus::Empty);
status |= IDE_LAYOUT_CHANGED;
@@ -762,23 +916,28 @@ bool IDEController :: doCloseProject(DialogBase& dialog, IDEModel* model)
else return false;
}
-bool IDEController :: closeFile(DialogBase& dialog, IDEModel* model, int index, NotificationStatus& status)
+bool IDEController :: closeFile(FileDialogBase& dialog, MessageDialogBase& mssgDialog, IDEModel* model,
+ int index, NotificationStatus& status)
{
auto docView = model->sourceViewModel.getDocument(index);
if (docView->isUnnamed()) {
- if (!doSaveFile(dialog, model, false, true))
- return false;
+ if (!doSaveFile(dialog, model, false, true)) {
+ auto result = mssgDialog.question(QUESTION_CLOSE_UNSAVED);
+
+ if (result != MessageDialogBase::Answer::Yes)
+ return false;
+ }
}
else if (docView->isModified()) {
path_t path = model->sourceViewModel.getDocumentPath(index);
- auto result = dialog.question(
+ auto result = mssgDialog.question(
QUESTION_SAVE_FILECHANGES, path);
- if (result == DialogBase::Answer::Cancel) {
+ if (result == MessageDialogBase::Answer::Cancel) {
return false;
}
- else if (result == DialogBase::Answer::Yes) {
+ else if (result == MessageDialogBase::Answer::Yes) {
if (!doSaveFile(dialog, model, false, true))
return false;
}
@@ -789,7 +948,7 @@ bool IDEController :: closeFile(DialogBase& dialog, IDEModel* model, int index,
return true;
}
-bool IDEController :: doCloseFile(DialogBase& dialog, IDEModel* model)
+bool IDEController :: doCloseFile(FileDialogBase& dialog, MessageDialogBase& mssgDialog, IDEModel* model)
{
auto docView = model->sourceViewModel.DocView();
if (docView) {
@@ -797,7 +956,7 @@ bool IDEController :: doCloseFile(DialogBase& dialog, IDEModel* model)
int index = model->sourceViewModel.getCurrentIndex();
if (index > 0) {
- bool retVal = closeFile(dialog, model, index, status);
+ bool retVal = closeFile(dialog, mssgDialog, model, index, status);
if (status != NONE_CHANGED)
_notifier->notify(NOTIFY_IDE_CHANGE, status);
@@ -806,20 +965,21 @@ bool IDEController :: doCloseFile(DialogBase& dialog, IDEModel* model)
return false;
}
-bool IDEController :: closeAll(DialogBase& dialog, IDEModel* model, NotificationStatus& status)
+bool IDEController :: closeAll(FileDialogBase& dialog, MessageDialogBase& mssgDialog, IDEModel* model,
+ NotificationStatus& status)
{
while (model->sourceViewModel.getDocumentCount() > 0) {
- if (!closeFile(dialog, model, 1, status))
+ if (!closeFile(dialog, mssgDialog, model, 1, status))
return false;
}
return true;
}
-bool IDEController :: doCloseAll(DialogBase& dialog, IDEModel* model)
+bool IDEController :: doCloseAll(FileDialogBase& dialog, MessageDialogBase& mssgDialog, IDEModel* model)
{
NotificationStatus status = NONE_CHANGED;
- if (closeAll(dialog, model, status)) {
+ if (closeAll(dialog, mssgDialog, model, status)) {
if (status != NONE_CHANGED)
_notifier->notify(NOTIFY_IDE_CHANGE, status);
@@ -829,9 +989,9 @@ bool IDEController :: doCloseAll(DialogBase& dialog, IDEModel* model)
return false;
}
-bool IDEController :: doExit(DialogBase& dialog, IDEModel* model)
+bool IDEController :: doExit(FileDialogBase& dialog, MessageDialogBase& mssgDialog, IDEModel* model)
{
- return doCloseAll(dialog, model);
+ return doCloseAll(dialog, mssgDialog, model);
}
void IDEController :: doSelectNextWindow(IDEModel* model)
@@ -984,7 +1144,7 @@ void IDEController :: onCompilationCompletion(IDEModel* model, int exitCode,
}
}
-bool IDEController :: doCompileProject(DialogBase& dialog, IDEModel* model)
+bool IDEController :: doCompileProject(FileDialogBase& dialog, IDEModel* model)
{
onCompilationStart(model);
@@ -997,6 +1157,13 @@ bool IDEController :: doCompileProject(DialogBase& dialog, IDEModel* model)
return projectController.doCompileProject(model->projectModel, DebugAction::None);
}
+void IDEController :: doChangeProject(ProjectSettingsBase& prjDialog, IDEModel* model)
+{
+ if (prjDialog.showModal()) {
+
+ }
+}
+
void IDEController :: refreshDebugContext(ContextBrowserBase* contextBrowser, IDEModel* model)
{
projectController.refreshDebugContext(contextBrowser);
@@ -1004,16 +1171,21 @@ void IDEController :: refreshDebugContext(ContextBrowserBase* contextBrowser, ID
_notifier->notifySelection(NOTIFY_REFRESH, model->ideScheme.debugWatch);
}
-bool IDEController :: onClose(DialogBase& dialog, IDEModel* model)
+void IDEController :: refreshDebugContext(ContextBrowserBase* contextBrowser, IDEModel* model, size_t item, size_t param)
{
- PathString path(*model->projectModel.paths.configPath);
+ projectController.refreshDebugContext(contextBrowser, item, param);
- bool result = doCloseAll(dialog, model);
- if (result) {
- saveConfig(model, *path);
- }
+ _notifier->notifySelection(NOTIFY_REFRESH, model->ideScheme.debugWatch);
+}
- return result;
+bool IDEController :: onClose(FileDialogBase& dialog, MessageDialogBase& mssgDialog, IDEModel* model)
+{
+ return doCloseAll(dialog, mssgDialog, model);
+}
+
+void IDEController :: onDebuggerHook(IDEModel* model)
+{
+ projectController.loadBreakpoints(model->projectModel);
}
void IDEController :: onDebuggerStop(IDEModel* model)
@@ -1023,3 +1195,21 @@ void IDEController :: onDebuggerStop(IDEModel* model)
model->status = IDEStatus::DebuggerStopped;
_notifier->notify(NOTIFY_IDE_CHANGE, IDE_STATUS_CHANGED | FRAME_CHANGED);
}
+
+void IDEController :: onProgramStop(IDEModel* model)
+{
+ PathString path(*model->projectModel.paths.configPath);
+
+ saveConfig(model, *path);
+}
+
+void IDEController :: onStatusChange(IDEModel* model, IDEStatus newStatus)
+{
+ model->status = newStatus;
+ _notifier->notify(NOTIFY_IDE_CHANGE, IDE_STATUS_CHANGED);
+}
+
+void IDEController :: toggleBreakpoint(IDEModel* model, int row)
+{
+ projectController.toggleBreakpoint(model->projectModel, model->sourceViewModel, row);
+}
diff --git a/elenasrc3/ide/idecontroller.h b/elenasrc3/ide/idecontroller.h
index 08dac49092..0ef47e9bdb 100644
--- a/elenasrc3/ide/idecontroller.h
+++ b/elenasrc3/ide/idecontroller.h
@@ -18,7 +18,7 @@ namespace elena_lang
class SourceViewController : public TextViewController
{
public:
- void newSource(TextViewModelBase* model, ustr_t name, bool autoSelect);
+ void newSource(TextViewModelBase* model, ustr_t name, bool autoSelect, NotificationStatus& status);
bool openSource(TextViewModelBase* model, ustr_t name, path_t sourcePath,
FileEncoding encoding, bool autoSelect, NotificationStatus& status);
void closeSource(TextViewModelBase* model, int index, bool autoSelect, NotificationStatus& status);
@@ -55,7 +55,7 @@ namespace elena_lang
void loadConfig(ProjectModel& model, ConfigFile& config, ConfigFile::Node platformRoot);
- path_t retrieveSourceName(ProjectModel* model, path_t sourcePath, ReferenceName& retVal);
+ path_t retrieveSourceName(ProjectModel* model, path_t sourcePath, NamespaceString& retVal);
bool onDebugAction(ProjectModel& model, DebugAction action);
bool isOutaged(bool noWarning);
@@ -74,12 +74,13 @@ namespace elena_lang
}
NotificationStatus openSingleFileProject(ProjectModel& model, path_t singleProjectFile);
+ NotificationStatus newProject(ProjectModel& model);
NotificationStatus openProject(ProjectModel& model, path_t projectFile);
NotificationStatus closeProject(ProjectModel& model);
path_t getSourceByIndex(ProjectModel& model, int index);
- void defineSourceName(ProjectModel* model, path_t path, ReferenceName& retVal);
+ void defineSourceName(ProjectModel* model, path_t path, NamespaceString& retVal);
void defineFullPath(ProjectModel& model, ustr_t ns, path_t path, PathString& fullPath);
@@ -90,6 +91,11 @@ namespace elena_lang
void runToCursor(ProjectModel& model, SourceViewModel& sourceModel);
void refreshDebugContext(ContextBrowserBase* contextBrowser);
+ void refreshDebugContext(ContextBrowserBase* contextBrowser, size_t param, addr_t address);
+
+ void toggleBreakpoint(ProjectModel& model, SourceViewModel& sourceModel, int row);
+
+ void loadBreakpoints(ProjectModel& model);
void setNotifier(NotifierBase* notifier)
{
@@ -110,13 +116,17 @@ namespace elena_lang
{
if (_notifier)
_notifier->notifyCompletion(id, param);
-
+ }
+ void notifyTreeItem(int id, size_t item, size_t param) override
+ {
+ if (_notifier)
+ _notifier->notifyTreeItem(id, item, param);
}
ProjectController(ProcessBase* outputProcess, DebugProcessBase* debugProcess, ProjectModel* model, SourceViewModel* sourceModel,
DebugSourceController* sourceController, PlatformType platform)
: _outputProcess(outputProcess), _debugController(debugProcess, model, sourceModel, this, sourceController),
- _autoWatch({ nullptr, 0 })
+ _autoWatch({ nullptr, 0 })
{
//_notifier = nullptr;
_platform = platform;
@@ -131,10 +141,13 @@ namespace elena_lang
bool openFile(SourceViewModel* model, ProjectModel* projectModel, path_t sourceFile, NotificationStatus& status);
bool openFile(IDEModel* model, path_t sourceFile, NotificationStatus& status);
bool openProject(IDEModel* model, path_t projectFile, NotificationStatus& status);
- bool closeProject(DialogBase& dialog, IDEModel* model, NotificationStatus& status);
+ bool closeProject(FileDialogBase& dialog, MessageDialogBase& mssgDialog, IDEModel* model,
+ NotificationStatus& status);
- bool closeFile(DialogBase& dialog, IDEModel* model, int index, NotificationStatus& status);
- bool closeAll(DialogBase& dialog, IDEModel* model, NotificationStatus& status);
+ bool closeFile(FileDialogBase& dialog, MessageDialogBase& mssgDialog, IDEModel* model,
+ int index, NotificationStatus& status);
+ bool closeAll(FileDialogBase& dialog, MessageDialogBase& mssgDialog, IDEModel* model,
+ NotificationStatus& status);
void displayErrors(IDEModel* model, text_str output, ErrorLogBase* log);
@@ -148,6 +161,8 @@ namespace elena_lang
SourceViewController sourceController;
ProjectController projectController;
+ void loadSystemConfig(IDEModel* model, path_t configPath, ustr_t typeXPath, ustr_t platformXPath);
+
bool loadConfig(IDEModel* model, path_t configPath);
void saveConfig(IDEModel* model, path_t configPath);
@@ -169,33 +184,43 @@ namespace elena_lang
void highlightError(IDEModel* model, int row, int column, path_t path);
void doNewFile(IDEModel* model);
- void doOpenFile(DialogBase& dialog, IDEModel* model);
- bool doSaveFile(DialogBase& dialog, IDEModel* model, bool saveAsMode, bool forcedSave);
- bool doCloseFile(DialogBase& dialog, IDEModel* model);
- bool doCloseAll(DialogBase& dialog, IDEModel* model);
- bool doOpenProject(DialogBase& dialog, IDEModel* model);
- bool doCloseProject(DialogBase& dialog, IDEModel* model);
- bool doSaveProject(DialogBase& dialog, IDEModel* model, bool forcedMode);
-
- bool doCompileProject(DialogBase& dialog, IDEModel* model);
+ void doOpenFile(FileDialogBase& dialog, IDEModel* model);
+ bool doSaveFile(FileDialogBase& dialog, IDEModel* model, bool saveAsMode, bool forcedSave);
+ bool doCloseFile(FileDialogBase& dialog, MessageDialogBase& mssgDialog, IDEModel* model);
+ bool doCloseAll(FileDialogBase& dialog, MessageDialogBase& mssgDialog, IDEModel* model);
+ void doNewProject(FileDialogBase& dialog, MessageDialogBase& mssgDialog, ProjectSettingsBase& prjDialog,
+ IDEModel* model);
+ bool doOpenProject(FileDialogBase& dialog, MessageDialogBase& mssgDialog, IDEModel* model);
+ bool doCloseProject(FileDialogBase& dialog, MessageDialogBase& mssgDialog, IDEModel* model);
+ bool doSaveProject(FileDialogBase& dialog, IDEModel* model, bool forcedMode);
+
+ bool doCompileProject(FileDialogBase& dialog, IDEModel* model);
+ void doChangeProject(ProjectSettingsBase& prjDialog, IDEModel* model);
void doDebugAction(IDEModel* model, DebugAction action);
void doDebugStop(IDEModel* model);
void refreshDebugContext(ContextBrowserBase* contextBrowser, IDEModel* model);
+ void refreshDebugContext(ContextBrowserBase* contextBrowser, IDEModel* model, size_t item, size_t param);
+
+ void toggleBreakpoint(IDEModel* model, int row);
void doSelectNextWindow(IDEModel* model);
void doSelectPrevWindow(IDEModel* model);
void onCompilationCompletion(IDEModel* model, int exitCode,
text_str output, ErrorLogBase* log);
+ void onDebuggerHook(IDEModel* model);
void onDebuggerStop(IDEModel* model);
+ void onStatusChange(IDEModel* model, IDEStatus newStatus);
- bool doExit(DialogBase& dialog, IDEModel* model);
+ bool doExit(FileDialogBase& dialog, MessageDialogBase& mssgDialog, IDEModel* model);
- bool onClose(DialogBase& dialog, IDEModel* model);
+ bool onClose(FileDialogBase& dialog, MessageDialogBase& mssgDialog, IDEModel* model);
void init(IDEModel* model);
+ void onProgramStop(IDEModel* model);
+
IDEController(ProcessBase* outputProcess, DebugProcessBase* process, IDEModel* model,
TextViewSettings& textViewSettings, PlatformType platform
) :
diff --git a/elenasrc3/ide/ideproject.cpp b/elenasrc3/ide/ideproject.cpp
index 5c714d9a95..9a768def0c 100644
--- a/elenasrc3/ide/ideproject.cpp
+++ b/elenasrc3/ide/ideproject.cpp
@@ -1,7 +1,7 @@
//---------------------------------------------------------------------------
// E L E N A P r o j e c t: ELENA IDE
// IDE Project Model implementation File
-// (C)2021-2022, by Aleksey Rakov
+// (C)2021-2023, by Aleksey Rakov
//---------------------------------------------------------------------------
#include "ideproject.h"
@@ -11,7 +11,8 @@ using namespace elena_lang;
// --- ProjectModel ---
ProjectModel :: ProjectModel(IDEStatus* status)
- : lastOpenFiles(nullptr), sources(nullptr)
+ : lastOpenFiles(nullptr), sources(nullptr),
+ breakpoints({}), projectTypeList(nullptr)
{
this->status = status;
@@ -19,6 +20,7 @@ ProjectModel :: ProjectModel(IDEStatus* status)
this->empty = true;
this->started = false;
+ this->notSaved = false;
#ifdef _M_IX86
this->paths.libraryRoot.copy("C:\\Alex\\ELENA\\lib60\\"); // !! temporal
diff --git a/elenasrc3/ide/ideproject.h b/elenasrc3/ide/ideproject.h
index f7f3be5ab3..73bbf409ca 100644
--- a/elenasrc3/ide/ideproject.h
+++ b/elenasrc3/ide/ideproject.h
@@ -21,7 +21,9 @@ namespace elena_lang
constexpr auto RECENTFILE_SETTINGS = "configuration/recent_files/path";
// --- Map types ---
- typedef List ProjectPaths;
+ typedef List ProjectPaths;
+ typedef List Breakpoints;
+ typedef List StringList;
// --- ProjectModel ---
struct ProjectModel
@@ -44,18 +46,26 @@ namespace elena_lang
bool autoRecompile;
bool empty;
bool started;
+ bool notSaved;
PathString name;
PathString projectFile;
PathString projectPath;
PathString outputPath;
+ PathString debugArguments;
IdentifierString package;
IdentifierString target;
+ IdentifierString templateName;
+ IdentifierString options;
ProjectPaths sources;
ProjectPaths lastOpenFiles;
+ Breakpoints breakpoints;
+
+ StringList projectTypeList;
+
ustr_t getTarget();
ustr_t getArguments();
diff --git a/elenasrc3/ide/ideview.h b/elenasrc3/ide/ideview.h
index 0836640e19..20cb436b57 100644
--- a/elenasrc3/ide/ideview.h
+++ b/elenasrc3/ide/ideview.h
@@ -25,6 +25,7 @@ struct IDEScheme
int debugWatch;
int menu;
int statusBar;
+ int debugContextMenu;
Map captions;
@@ -37,6 +38,7 @@ struct IDEScheme
debugWatch(-1),
menu(-1),
statusBar(-1),
+ debugContextMenu(-1),
captions(nullptr)
{
}
diff --git a/elenasrc3/ide/windows/Resource.h b/elenasrc3/ide/windows/Resource.h
index d5e88b78b5..18dc5191da 100644
--- a/elenasrc3/ide/windows/Resource.h
+++ b/elenasrc3/ide/windows/Resource.h
@@ -14,6 +14,7 @@
#define IDM_FILE_CLOSEALL 406
#define IDM_PROJECT_OPEN 407
#define IDM_PROJECT_CLOSE 408
+#define IDM_PROJECT_NEW 409
#define IDM_EDIT_UNDO 501
#define IDM_EDIT_REDO 502
@@ -31,12 +32,18 @@
#define IDM_VIEW_MESSAGES 604
#define IDM_PROJECT_COMPILE 701
+#define IDM_PROJECT_OPTION 702
#define IDM_DEBUG_RUN 801
#define IDM_DEBUG_STEPOVER 802
#define IDM_DEBUG_STEPINTO 803
#define IDM_DEBUG_RUNTO 804
#define IDM_DEBUG_STOP 805
+#define IDM_DEBUG_BREAKPOINT 806
+#define IDM_DEBUG_CLEARBREAKPOINT 807
+
+#define IDM_DEBUG_INSPECT 810
+#define IDM_DEBUG_SWITCHHEXVIEW 811
#define IDM_WINDOW_NEXT 901
#define IDM_WINDOW_PREVIOUS 902
@@ -53,9 +60,19 @@
#define IDC_COMPILER_MESSAGES 114
#define IDC_COMPILER_WATCH 115
+#define IDD_SETTINGS 800
+#define IDC_SETTINGS_TEPMPLATE 801
+#define IDC_SETTINGS_PACKAGE 802
+#define IDC_SETTINGS_OPTIONS 803
+#define IDC_SETTINGS_TARGET 804
+#define IDC_SETTINGS_OUTPUT 805
+#define IDC_SETTINGS_DEBUG 806
+#define IDC_SETTINGS_ARGUMENT 807
+
#ifndef IDC_STATIC
#define IDC_STATIC -1
#endif
+
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
diff --git a/elenasrc3/ide/windows/elide.rc b/elenasrc3/ide/windows/elide.rc
index 8b6cb68405..2603164030 100644
Binary files a/elenasrc3/ide/windows/elide.rc and b/elenasrc3/ide/windows/elide.rc differ
diff --git a/elenasrc3/ide/windows/factory.cpp b/elenasrc3/ide/windows/factory.cpp
index 1041ff408d..8c47ad088c 100644
--- a/elenasrc3/ide/windows/factory.cpp
+++ b/elenasrc3/ide/windows/factory.cpp
@@ -42,7 +42,10 @@ WCHAR szHSplitter[MAX_LOADSTRING]; // the hsplitter class name
WCHAR szVSplitter[MAX_LOADSTRING]; // the vsplitter window class name
WCHAR szCompilerOutput[MAX_LOADSTRING]; // the compiler output caption
WCHAR szErrorList[MAX_LOADSTRING]; // the compiler output caption
-WCHAR szWatch[MAX_LOADSTRING]; // the compiler output caption
+WCHAR szWatch[MAX_LOADSTRING]; // the compiler output caption
+
+#define CONTEXT_MENU_INSPECT _T("Inspect\tCtrl+I")
+#define CONTEXT_MENU_SHOWHEX _T("Show as hexadecimal")
// !! temporally
#define IDE_CHARSET_ANSI ANSI_CHARSET
@@ -55,6 +58,7 @@ StyleInfo defaultStyles[STYLE_MAX + 1] = {
{Color(0), Color(0xC0, 0xC0, 0xC0), _T("Courier New"), IDE_CHARSET_ANSI, 10, false, false},
{Color(0x60, 0x60, 0x60), Color(0x0, 0xFF, 0xFF), _T("Courier New"), IDE_CHARSET_ANSI, 10, true, false},
{Color(0xFF, 0xFF, 0xFF), Color(0xFF, 0x0, 0x0), _T("Courier New"), IDE_CHARSET_ANSI, 10, false, false},
+ {Color(0xFF, 0xFF, 0xFF), Color(0xFF, 0x0, 0x0), _T("Courier New"), IDE_CHARSET_ANSI, 10, false, false},
//{Color(0xFF, 0x80, 0x40), Color(0xFF, 0xFF, 0xFF), _T("Courier New"), IDE_CHARSET_ANSI, 10, false, false},
//{Colour(0, 0, 0xFF), Colour(0xFF, 0xFF, 0xFF), _T("Courier New"), IDE_CHARSET_ANSI, 10, false, false},
//{Colour(0, 0x80, 0), Colour(0xFF, 0xFF, 0xFF), _T("Courier New"), IDE_CHARSET_ANSI, 10, false, false},
@@ -65,7 +69,6 @@ StyleInfo defaultStyles[STYLE_MAX + 1] = {
//{Colour(0xFF, 0xFF, 0xFF), Colour(0xFF, 0x0, 0x0), TEXT("Courier New"), IDE_CHARSET_ANSI, 10, false, false},
//{Colour(0), Colour(0x0, 0xFF, 0xFF), TEXT("Courier New"), IDE_CHARSET_ANSI, 10, false, false},
//{Colour(0x60, 0x60, 0x60), Colour(0x0, 0xFF, 0xFF), TEXT("Courier New"), IDE_CHARSET_ANSI, 10, true, false},
- //{Colour(0xFF, 0xFF, 0xFF), Colour(0xFF, 0x0, 0x0), TEXT("Courier New"), IDE_CHARSET_ANSI, 10, false, false},
//{Colour(0), Colour(0xFF, 0xFF, 0xFF), _T("Courier New"), IDE_CHARSET_ANSI, 10, true, false}
};
@@ -90,6 +93,13 @@ StyleInfo classicStyles[STYLE_MAX + 1] = {
constexpr auto STYLE_SCHEME_COUNT = 2;
+MenuInfo browserContextMenuInfo[3] = {
+ {IDM_DEBUG_INSPECT, CONTEXT_MENU_INSPECT},
+ {0, nullptr},
+ {IDM_DEBUG_SWITCHHEXVIEW, CONTEXT_MENU_SHOWHEX}
+};
+
+
// --- IDEFactory ---
IDEFactory :: IDEFactory(HINSTANCE instance, IDEModel* ideModel,
@@ -212,7 +222,7 @@ ControlBase* IDEFactory :: createProjectView(ControlBase* owner, NotifierBase* n
ControlBase* IDEFactory :: createDebugBrowser(ControlBase* owner, NotifierBase* notifier)
{
- ContextBrowser* browser = new ContextBrowser(300, 50, notifier);
+ ContextBrowser* browser = new ContextBrowser(300, 50, notifier, NOTIFY_DEBUG_CONTEXT_EXPANDED);
browser->createControl(_instance, owner);
browser->hide();
@@ -226,8 +236,17 @@ GUIControlBase* IDEFactory :: createMenu(ControlBase* owner)
return menu;
}
+GUIControlBase* IDEFactory :: createDebugContextMenu(ControlBase* owner)
+{
+ ContextMenu* menu = new ContextMenu();
+
+ menu->create(3, browserContextMenuInfo);
+
+ return menu;
+}
+
void IDEFactory :: initializeScheme(int frameTextIndex, int tabBar, int compilerOutput, int errorList,
- int projectView, int contextBrowser, int menu, int statusBar)
+ int projectView, int contextBrowser, int menu, int statusBar, int debugContextMenu)
{
LoadStringW(_instance, IDC_COMPILER_OUTPUT, szCompilerOutput, MAX_LOADSTRING);
LoadStringW(_instance, IDC_COMPILER_MESSAGES, szErrorList, MAX_LOADSTRING);
@@ -241,6 +260,7 @@ void IDEFactory :: initializeScheme(int frameTextIndex, int tabBar, int compiler
_model->ideScheme.debugWatch = contextBrowser;
_model->ideScheme.menu = menu;
_model->ideScheme.statusBar = statusBar;
+ _model->ideScheme.debugContextMenu = debugContextMenu;
_model->ideScheme.captions.add(compilerOutput, szCompilerOutput);
_model->ideScheme.captions.add(errorList, szErrorList);
@@ -258,7 +278,7 @@ GUIApp* IDEFactory :: createApp()
GUIControlBase* IDEFactory :: createMainWindow(NotifierBase* notifier, ProcessBase* outputProcess)
{
- GUIControlBase* children[11];
+ GUIControlBase* children[12];
int counter = 0;
int textIndex = counter++;
@@ -272,6 +292,7 @@ GUIControlBase* IDEFactory :: createMainWindow(NotifierBase* notifier, ProcessBa
int hsplitter = counter++;
int browser = counter++;
int menu = counter++;
+ int debugContextMenu = counter++;
SDIWindow* sdi = new IDEWindow(szTitle, _controller, _model, _instance);
sdi->create(_instance, szSDI, nullptr);
@@ -291,6 +312,7 @@ GUIControlBase* IDEFactory :: createMainWindow(NotifierBase* notifier, ProcessBa
children[hsplitter] = createSplitter(sdi, (ControlBase*)children[projectView], true, notifier,
NOTIFY_IDE_CHANGE, IDE_LAYOUT_CHANGED);
children[menu] = createMenu(sdi);
+ children[debugContextMenu] = createDebugContextMenu(sdi);
vb->append(children[vsplitter]);
vb->append(children[statusBarIndex]);
@@ -298,7 +320,8 @@ GUIControlBase* IDEFactory :: createMainWindow(NotifierBase* notifier, ProcessBa
sdi->populate(counter, children);
sdi->setLayout(textIndex, -1, bottomBox, -1, hsplitter);
- initializeScheme(textIndex, tabBar, compilerOutput, errorList, projectView, browser, menu, statusBarIndex);
+ initializeScheme(textIndex, tabBar, compilerOutput, errorList, projectView, browser, menu, statusBarIndex,
+ debugContextMenu);
return sdi;
}
diff --git a/elenasrc3/ide/windows/factory.h b/elenasrc3/ide/windows/factory.h
index 6f0e92466c..19db6ffe3a 100644
--- a/elenasrc3/ide/windows/factory.h
+++ b/elenasrc3/ide/windows/factory.h
@@ -43,9 +43,10 @@ namespace elena_lang
ControlBase* createProjectView(ControlBase* owner, NotifierBase* notifier);
ControlBase* createDebugBrowser(ControlBase* owner, NotifierBase* notifier);
GUIControlBase* createMenu(ControlBase* owner);
+ GUIControlBase* createDebugContextMenu(ControlBase* owner);
void initializeScheme(int frameTextIndex, int tabBar, int compilerOutput, int errorList,
- int projectView, int contextBrowser, int menu, int statusBar);
+ int projectView, int contextBrowser, int menu, int statusBar, int debugContextMenu);
public:
GUIApp* createApp() override;
diff --git a/elenasrc3/ide/windows/main.cpp b/elenasrc3/ide/windows/main.cpp
index 839bbe1f7f..0b006d8f0c 100644
--- a/elenasrc3/ide/windows/main.cpp
+++ b/elenasrc3/ide/windows/main.cpp
@@ -21,12 +21,18 @@ using namespace elena_lang;
constexpr auto CURRENT_PLATFORM = PlatformType::Win_x86;
+constexpr auto TARGET_XPATH = "Win_x86";
+
#elif _M_X64
constexpr auto CURRENT_PLATFORM = PlatformType::Win_x86_64;
+constexpr auto TARGET_XPATH = "Win_x64";
+
#endif
+constexpr auto TEMPLATE_XPATH = "templates/*";
+
typedef Win32DebugProcess DebugProcess;
// Forward declarations of functions included in this code module:
@@ -59,6 +65,10 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
configPath.combine(_T("ide60.cfg"));
ideController.loadConfig(&ideModel, *configPath);
+ PathString sysConfigPath(ideModel.projectModel.paths.appPath);
+ sysConfigPath.combine(_T("elc60.cfg"));
+ ideController.loadSystemConfig(&ideModel, *sysConfigPath, TEMPLATE_XPATH, TARGET_XPATH);
+
GUIApp* app = factory.createApp();
GUIControlBase* ideWindow = factory.createMainWindow(app, &outputProcess);
@@ -66,6 +76,8 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
int retVal = app->run(ideWindow, ideModel.appMaximized, NOTIFY_ONSTART, IDE_ONSTART);
+ ideController.onProgramStop(&ideModel);
+
delete app;
return retVal;
diff --git a/elenasrc3/ide/windows/win32debugprocess.cpp b/elenasrc3/ide/windows/win32debugprocess.cpp
index 184684ff00..7143ca262b 100644
--- a/elenasrc3/ide/windows/win32debugprocess.cpp
+++ b/elenasrc3/ide/windows/win32debugprocess.cpp
@@ -238,6 +238,14 @@ Win32BreakpointContext :: Win32BreakpointContext()
}
+void Win32BreakpointContext :: addBreakpoint(addr_t address, Win32ThreadContext* context, bool started)
+{
+ if (started) {
+ breakpoints.add(address, context->setSoftwareBreakpoint(address));
+ }
+ else breakpoints.add(address, 0);
+}
+
void Win32BreakpointContext :: setSoftwareBreakpoints(Win32ThreadContext* context)
{
Map::Iterator breakpoint = breakpoints.start();
@@ -611,6 +619,11 @@ void Win32DebugProcess :: setBreakpoint(addr_t address, bool withStackLevelContr
_breakpoints.setHardwareBreakpoint(address, _current, withStackLevelControl);
}
+void Win32DebugProcess :: addBreakpoint(addr_t address)
+{
+ _breakpoints.addBreakpoint(address, _current, started);
+}
+
void Win32DebugProcess :: setStepMode()
{
// !! temporal
diff --git a/elenasrc3/ide/windows/win32debugprocess.h b/elenasrc3/ide/windows/win32debugprocess.h
index 6f7bbc878b..6102392099 100644
--- a/elenasrc3/ide/windows/win32debugprocess.h
+++ b/elenasrc3/ide/windows/win32debugprocess.h
@@ -97,7 +97,7 @@ namespace elena_lang
{
Map breakpoints;
- //void addBreakpoint(size_t address, Win32ThreadContext* context, bool started);
+ void addBreakpoint(addr_t address, Win32ThreadContext* context, bool started);
//void removeBreakpoint(size_t address, Win32ThreadContext* context, bool started);
void setSoftwareBreakpoints(Win32ThreadContext* context);
void setHardwareBreakpoint(addr_t address, Win32ThreadContext* context, bool withStackLevelControl);
@@ -240,6 +240,7 @@ namespace elena_lang
size_t getArrayLength(addr_t address) override;
void setBreakpoint(addr_t address, bool withStackLevelControl) override;
+ void addBreakpoint(addr_t address) override;
void addStep(addr_t address, void* current) override;
diff --git a/elenasrc3/ide/windows/wincontextbrowser.cpp b/elenasrc3/ide/windows/wincontextbrowser.cpp
index a196a43a66..d18466703d 100644
--- a/elenasrc3/ide/windows/wincontextbrowser.cpp
+++ b/elenasrc3/ide/windows/wincontextbrowser.cpp
@@ -17,9 +17,10 @@ typedef String CaptrionString;
// --- ContextBrowser --
-ContextBrowser :: ContextBrowser(int width, int height, NotifierBase* notifier)
+ContextBrowser :: ContextBrowser(int width, int height, NotifierBase* notifier, int expandNotificationId)
: TreeView(width, height, notifier, 0, false, false)
{
+ _expandNotificationId = expandNotificationId;
}
HWND ContextBrowser :: createControl(HINSTANCE instance, ControlBase* owner)
@@ -122,12 +123,17 @@ void ContextBrowser :: populateNode(void* item, ustr_t value)
}
-void ContextBrowser::expandRootNode()
+void ContextBrowser :: expandRootNode()
{
expand(_rootItem);
}
-void ContextBrowser::removeUnused(WatchItems& refreshedItems)
+void ContextBrowser :: clearRootNode()
+{
+ clearNode(_rootItem);
+}
+
+void ContextBrowser :: removeUnused(WatchItems& refreshedItems)
{
TreeViewItem current = getChild(_rootItem);
while (current != nullptr) {
@@ -146,4 +152,22 @@ void ContextBrowser::removeUnused(WatchItems& refreshedItems)
}
else current = getNext(current);
}
-}
\ No newline at end of file
+}
+
+void ContextBrowser :: onItemExpand(TreeViewItem item)
+{
+ _notifier->notifyTreeItem(_expandNotificationId, (size_t)item, getParam(item));
+}
+
+void ContextBrowser :: expandNode(size_t param)
+{
+ expand((TreeViewItem)param);
+}
+
+void ContextBrowser :: refreshCurrentNode()
+{
+ TreeViewItem current = getCurrent();
+
+ _notifier->notifyTreeItem(_expandNotificationId, (size_t)current, getParam(current));
+}
+
diff --git a/elenasrc3/ide/windows/wincontextbrowser.h b/elenasrc3/ide/windows/wincontextbrowser.h
index 837fcc6541..5fcfbe8fbe 100644
--- a/elenasrc3/ide/windows/wincontextbrowser.h
+++ b/elenasrc3/ide/windows/wincontextbrowser.h
@@ -1,7 +1,7 @@
//---------------------------------------------------------------------------
// E L E N A P r o j e c t: ELENA IDE
// WinAPI IDE Debug Context Browser Header File
-// (C)2022, by Aleksey Rakov
+// (C)2022-2023, by Aleksey Rakov
//---------------------------------------------------------------------------
#ifndef WINCONTEXTBROWSER_H
@@ -15,6 +15,7 @@ namespace elena_lang
class ContextBrowser : public TreeView, public ContextBrowserBase
{
TreeViewItem _rootItem;
+ int _expandNotificationId;
void* findWatchNodeStartingWith(WatchContext* root, ustr_t name) override;
@@ -27,11 +28,18 @@ namespace elena_lang
public:
HWND createControl(HINSTANCE instance, ControlBase* owner) override;
+ void onItemExpand(TreeViewItem item) override;
+
void expandRootNode() override;
+ void clearRootNode() override;
+
+ void expandNode(size_t param) override;
+
+ void refreshCurrentNode() override;
void removeUnused(WatchItems& refreshedItems) override;
- ContextBrowser(int width, int height, NotifierBase* notifier);
+ ContextBrowser(int width, int height, NotifierBase* notifier, int expandNotificationId);
};
}
diff --git a/elenasrc3/ide/windows/windialogs.cpp b/elenasrc3/ide/windows/windialogs.cpp
index 9a270318b0..22a4e6d816 100644
--- a/elenasrc3/ide/windows/windialogs.cpp
+++ b/elenasrc3/ide/windows/windialogs.cpp
@@ -1,12 +1,14 @@
//---------------------------------------------------------------------------
// E L E N A P r o j e c t: ELENA IDE
// WinAPI: Static dialog implementations
-// (C)2021-2022, by Aleksey Rakov
+// (C)2021-2023, by Aleksey Rakov
//---------------------------------------------------------------------------
#include
#include "windialogs.h"
+
+#include "Resource.h"
#include "eng/messages.h"
using namespace elena_lang;
@@ -25,10 +27,10 @@ int MsgBox :: showQuestion(HWND owner, const wchar_t* message)
// --- FileDialog ---
-const wchar_t* Dialog::ProjectFilter = _T("ELENA Project file\0*.prj\0All types\0*.*\0\0");
-const wchar_t* Dialog::SourceFilter = _T("ELENA source file\0*.l\0All types\0*.*\0\0");
+const wchar_t* FileDialog::ProjectFilter = _T("ELENA Project file\0*.prj\0All types\0*.*\0\0");
+const wchar_t* FileDialog::SourceFilter = _T("ELENA source file\0*.l\0All types\0*.*\0\0");
-Dialog :: Dialog(HINSTANCE instance, WindowBase* owner, const wchar_t* filter, const wchar_t* caption,
+FileDialog :: FileDialog(HINSTANCE instance, WindowBase* owner, const wchar_t* filter, const wchar_t* caption,
const wchar_t* initialDir)
{
ZeroMemory(&_struct, sizeof(_struct));
@@ -59,7 +61,7 @@ Dialog :: Dialog(HINSTANCE instance, WindowBase* owner, const wchar_t* filter, c
_owner = owner;
}
-bool Dialog :: openFile(PathString& path)
+bool FileDialog :: openFile(PathString& path)
{
_struct.Flags = _defaultFlags;
if (::GetOpenFileName(&_struct)) {
@@ -71,7 +73,7 @@ bool Dialog :: openFile(PathString& path)
else return false;
}
-bool Dialog :: openFiles(List& files)
+bool FileDialog :: openFiles(List& files)
{
_struct.Flags = _defaultFlags | OFN_FILEMUSTEXIST | OFN_ALLOWMULTISELECT;
if (::GetOpenFileName(&_struct)) {
@@ -99,7 +101,7 @@ bool Dialog :: openFiles(List& files)
return false;
}
-bool Dialog :: saveFile(path_t ext, PathString& path)
+bool FileDialog :: saveFile(path_t ext, PathString& path)
{
_struct.Flags = _defaultFlags | OFN_PATHMUSTEXIST;
_struct.lpstrDefExt = ext;
@@ -112,7 +114,7 @@ bool Dialog :: saveFile(path_t ext, PathString& path)
else return false;
}
-DialogBase::Answer Dialog :: question(text_str message, text_str param)
+MessageDialogBase::Answer MessageDialog :: question(text_str message, text_str param)
{
WideMessage wideMessage(message);
wideMessage.append(param);
@@ -126,4 +128,190 @@ DialogBase::Answer Dialog :: question(text_str message, text_str param)
return Answer::Cancel;
}
else return Answer::No;
-}
\ No newline at end of file
+}
+
+MessageDialogBase::Answer MessageDialog :: question(text_str message)
+{
+ int result = MsgBox::show(_owner->handle(), message, MB_YESNOCANCEL | MB_ICONQUESTION);
+
+ if (MsgBox::isYes(result)) {
+ return Answer::Yes;
+ }
+ else if (MsgBox::isCancel(result)) {
+ return Answer::Cancel;
+ }
+ else return Answer::No;
+}
+
+// --- WinDialog ---
+
+BOOL CALLBACK WinDialog::DialogProc(HWND hWnd, size_t message, WPARAM wParam, LPARAM lParam)
+{
+ WinDialog* dialog = (WinDialog*)::GetWindowLongPtr(hWnd, GWLP_USERDATA);
+ switch (message) {
+ case WM_INITDIALOG:
+ dialog = (WinDialog*)lParam;
+ dialog->_handle = hWnd;
+ ::SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)lParam);
+
+ dialog->onCreate();
+
+ return 0;
+ case WM_COMMAND:
+ dialog->doCommand(LOWORD(wParam), HIWORD(wParam));
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
+void WinDialog :: doCommand(int id, int command)
+{
+ switch (id) {
+ case IDOK:
+ onOK();
+ ::EndDialog(_handle, -1);
+ break;
+ case IDCANCEL:
+ ::EndDialog(_handle, 0);
+ break;
+ }
+}
+
+int WinDialog :: show()
+{
+ return (int)::DialogBoxParam(_instance, MAKEINTRESOURCE(_dialogId),
+ _owner->handle(), (DLGPROC)DialogProc, (LPARAM)this);
+}
+
+void WinDialog :: addComboBoxItem(int id, const wchar_t* text)
+{
+ ::SendDlgItemMessage(_handle, id, CB_ADDSTRING, 0, (LPARAM)text);
+}
+
+void WinDialog :: setComboBoxIndex(int id, int index)
+{
+ ::SendDlgItemMessage(_handle, id, CB_SETCURSEL, index, 0);
+}
+
+int WinDialog :: getComboBoxIndex(int id)
+{
+ return (int)::SendDlgItemMessage(_handle, id, CB_GETCURSEL, 0, 0);
+}
+
+void WinDialog :: setText(int id, const wchar_t* text)
+{
+ ::SendDlgItemMessage(_handle, id, WM_SETTEXT, 0, (LPARAM)text);
+}
+
+void WinDialog :: setTextLimit(int id, int maxLength)
+{
+ ::SendDlgItemMessage(_handle, id, EM_SETLIMITTEXT, maxLength, 0);
+}
+
+void WinDialog :: getText(int id, wchar_t** text, int length)
+{
+ ::SendDlgItemMessage(_handle, id, WM_GETTEXT, length, (LPARAM)text);
+}
+
+// --- ProjectSettings ---
+
+ProjectSettings :: ProjectSettings(HINSTANCE instance, WindowBase* owner, ProjectModel* model)
+ : WinDialog(instance, owner)
+{
+ _dialogId = IDD_SETTINGS;
+ _model = model;
+}
+
+void ProjectSettings :: loadTemplateList()
+{
+ int selected = 0;
+ int current = 0;
+ for (auto it = _model->projectTypeList.start(); !it.eof(); ++it) {
+ ustr_t key = *it;
+ if (_model->templateName.compare(key)) {
+ selected = current;
+ }
+
+ WideMessage caption(key);
+ addComboBoxItem(IDC_SETTINGS_TEPMPLATE, *caption);
+ current++;
+ }
+
+ setComboBoxIndex(IDC_SETTINGS_TEPMPLATE, selected);
+}
+
+void ProjectSettings :: onCreate()
+{
+ setTextLimit(IDC_SETTINGS_PACKAGE, IDENTIFIER_LEN);
+
+ WideMessage caption(*_model->package);
+ setText(IDC_SETTINGS_PACKAGE, caption.str());
+
+ WideMessage optionCaption(*_model->options);
+ setText(IDC_SETTINGS_OPTIONS, optionCaption.str());
+
+ WideMessage targetCaption(*_model->target);
+ setText(IDC_SETTINGS_TARGET, targetCaption.str());
+
+ setText(IDC_SETTINGS_OUTPUT, *_model->outputPath);
+
+ setText(IDC_SETTINGS_ARGUMENT, *_model->debugArguments);
+
+ addComboBoxItem(IDC_SETTINGS_DEBUG, _T("Disabled"));
+ addComboBoxItem(IDC_SETTINGS_DEBUG, _T("Enabled"));
+
+ //int mode = _project->getDebugMode();
+ //if (mode != 0) {
+ setComboBoxIndex(IDC_SETTINGS_DEBUG, 1);
+ //}
+ //else setComboBoxIndex(IDC_SETTINGS_DEBUG, 0);
+
+ loadTemplateList();
+}
+
+void ProjectSettings :: onOK()
+{
+ wchar_t name[IDENTIFIER_LEN + 1];
+
+ if (getComboBoxIndex(IDC_SETTINGS_TEPMPLATE) != -1) {
+ getText(IDC_SETTINGS_TEPMPLATE, (wchar_t**)(&name), IDENTIFIER_LEN);
+
+ IdentifierString value(name);
+ _model->templateName.copy(*value);
+ }
+
+ getText(IDC_SETTINGS_PACKAGE, (wchar_t**)(&name), IDENTIFIER_LEN);
+ if (getlength(name) > 0) {
+ IdentifierString value(name);
+ _model->package.copy(*value);
+ }
+ else _model->package.clear();
+
+ getText(IDC_SETTINGS_OPTIONS, (wchar_t**)(&name), IDENTIFIER_LEN);
+ if (getlength(name) > 0) {
+ IdentifierString value(name);
+ _model->options.copy(*value);
+ }
+ else _model->options.clear();
+
+ getText(IDC_SETTINGS_TARGET, (wchar_t**)(&name), IDENTIFIER_LEN);
+ if (getlength(name) > 0) {
+ IdentifierString value(name);
+ _model->target.copy(*value);
+ }
+ else _model->target.clear();
+
+ getText(IDC_SETTINGS_OUTPUT, (wchar_t**)(&name), IDENTIFIER_LEN);
+ _model->outputPath.copy(name);
+
+ getText(IDC_SETTINGS_ARGUMENT, (wchar_t**)(&name), IDENTIFIER_LEN);
+ _model->debugArguments.copy(name);
+
+ _model->notSaved = true;
+}
+
+bool ProjectSettings :: showModal()
+{
+ return show() == IDOK;
+}
diff --git a/elenasrc3/ide/windows/windialogs.h b/elenasrc3/ide/windows/windialogs.h
index c47d527496..e3bf6e9fe1 100644
--- a/elenasrc3/ide/windows/windialogs.h
+++ b/elenasrc3/ide/windows/windialogs.h
@@ -1,7 +1,7 @@
//---------------------------------------------------------------------------
// E L E N A P r o j e c t: ELENA IDE
// Win32: Static dialogs header
-// (C)2021-2022, by Aleksey Rakov
+// (C)2021-2023, by Aleksey Rakov
//---------------------------------------------------------------------------
#ifndef WINDIALOGS_H
@@ -9,6 +9,7 @@
#include "controller.h"
#include "editcontrol.h"
+#include "ideproject.h"
namespace elena_lang
{
@@ -24,8 +25,8 @@ namespace elena_lang
static bool isNo(int result) { return result == IDNO; }
};
- // --- Dialog ---
- class Dialog : public DialogBase
+ // --- FileDialog ---
+ class FileDialog : public FileDialogBase
{
WindowBase* _owner;
@@ -41,10 +42,71 @@ namespace elena_lang
bool openFiles(List& files) override;
bool saveFile(path_t ext, PathString& path) override;
+ FileDialog(HINSTANCE instance, WindowBase* owner, const wchar_t* filter, const wchar_t* caption,
+ const wchar_t* initialDir = nullptr);
+ };
+
+ class MessageDialog : public MessageDialogBase
+ {
+ WindowBase* _owner;
+
+ public:
Answer question(text_str message, text_str param) override;
+ Answer question(text_str message) override;
- Dialog(HINSTANCE instance, WindowBase* owner, const wchar_t* filter, const wchar_t* caption,
- const wchar_t* initialDir = nullptr);
+ MessageDialog(WindowBase* owner)
+ {
+ _owner = owner;
+ }
+ };
+
+ class WinDialog
+ {
+ protected:
+ HINSTANCE _instance;
+ HWND _handle;
+
+ WindowBase* _owner;
+ int _dialogId;
+
+ virtual void onCreate() = 0;
+ virtual void onOK() = 0;
+
+ virtual void doCommand(int id, int command);
+
+ void addComboBoxItem(int id, const wchar_t* text);
+ void setComboBoxIndex(int id, int index);
+ int getComboBoxIndex(int id);
+
+ void setText(int id, const wchar_t* text);
+ void getText(int id, wchar_t** text, int length);
+ void setTextLimit(int id, int maxLength);
+
+ public:
+ static BOOL CALLBACK DialogProc(HWND hwnd, size_t message, WPARAM wParam, LPARAM lParam);
+
+ int show();
+
+ WinDialog(HINSTANCE instance, WindowBase* owner)
+ {
+ _instance = instance;
+ _owner = owner;
+ }
+ };
+
+ class ProjectSettings : public WinDialog, public ProjectSettingsBase
+ {
+ ProjectModel* _model;
+
+ void loadTemplateList();
+
+ void onCreate() override;
+ void onOK() override;
+
+ public:
+ bool showModal() override;
+
+ ProjectSettings(HINSTANCE instance, WindowBase* owner, ProjectModel* model);
};
}
diff --git a/elenasrc3/ide/windows/winide.cpp b/elenasrc3/ide/windows/winide.cpp
index 20c00f929d..fd5a04a84d 100644
--- a/elenasrc3/ide/windows/winide.cpp
+++ b/elenasrc3/ide/windows/winide.cpp
@@ -107,13 +107,15 @@ void Clipboard :: pasteFromClipboard(DocumentChangeStatus& status, DocumentView*
IDEWindow :: IDEWindow(wstr_t title, IDEController* controller, IDEModel* model, HINSTANCE instance) :
SDIWindow(title),
fileDialog(instance,
- this, Dialog::SourceFilter,
+ this, FileDialog::SourceFilter,
OPEN_FILE_CAPTION,
*model->projectModel.paths.lastPath),
projectDialog(instance,
- this, Dialog::ProjectFilter,
+ this, FileDialog::ProjectFilter,
OPEN_PROJECT_CAPTION,
*model->projectModel.paths.lastPath),
+ messageDialog(this),
+ projectSettingsDialog(instance, this, &model->projectModel),
clipboard(this)
{
this->_instance = instance;
@@ -135,6 +137,11 @@ void IDEWindow :: newFile()
_controller->doNewFile(_model);
}
+void IDEWindow :: newProject()
+{
+ _controller->doNewProject(fileDialog, messageDialog, projectSettingsDialog, _model);
+}
+
void IDEWindow :: openFile()
{
_controller->doOpenFile(fileDialog, _model);
@@ -147,29 +154,29 @@ void IDEWindow :: saveFile()
void IDEWindow :: closeFile()
{
- _controller->doCloseFile(fileDialog, _model);
+ _controller->doCloseFile(fileDialog, messageDialog, _model);
}
void IDEWindow :: closeAll()
{
- _controller->doCloseAll(fileDialog, _model);
+ _controller->doCloseAll(fileDialog, messageDialog, _model);
}
void IDEWindow :: openProject()
{
- _controller->doOpenProject(projectDialog, _model);
+ _controller->doOpenProject(projectDialog, messageDialog, _model);
}
void IDEWindow :: closeProject()
{
- _controller->doCloseProject(projectDialog, _model);
+ _controller->doCloseProject(projectDialog, messageDialog, _model);
//_controller->onLayoutchange();
}
void IDEWindow :: exit()
{
- if(_controller->doExit(fileDialog, _model)) {
+ if(_controller->doExit(fileDialog, messageDialog, _model)) {
SDIWindow::exit();
}
}
@@ -304,6 +311,14 @@ void IDEWindow :: onDebugWatch()
contextBrowser->expandRootNode();
}
+void IDEWindow :: onDebugWatchBrowse(size_t item, size_t param)
+{
+ if (param) {
+ ContextBrowserBase* contextBrowser = dynamic_cast(_children[_model->ideScheme.debugWatch]);
+ _controller->refreshDebugContext(contextBrowser, _model, item, param);
+ }
+}
+
void IDEWindow :: onProjectChange(bool empty)
{
TreeView* projectTree = dynamic_cast(_children[_model->ideScheme.projectView]);
@@ -452,6 +467,9 @@ bool IDEWindow :: onCommand(int command)
case IDM_FILE_NEW:
newFile();
break;
+ case IDM_PROJECT_NEW:
+ newProject();
+ break;
case IDM_FILE_OPEN:
openFile();
break;
@@ -504,6 +522,9 @@ bool IDEWindow :: onCommand(int command)
case IDM_PROJECT_COMPILE:
_controller->doCompileProject(projectDialog, _model);
break;
+ case IDM_PROJECT_OPTION:
+ _controller->doChangeProject(projectSettingsDialog, _model);
+ break;
case IDM_DEBUG_RUN:
_controller->doDebugAction(_model, DebugAction::Run);
break;
@@ -519,6 +540,9 @@ bool IDEWindow :: onCommand(int command)
case IDM_DEBUG_STOP:
_controller->doDebugStop(_model);
break;
+ case IDM_DEBUG_BREAKPOINT:
+ _controller->toggleBreakpoint(_model, -1);
+ break;
case IDM_WINDOW_NEXT:
_controller->doSelectNextWindow(_model);
break;
@@ -540,6 +564,9 @@ bool IDEWindow :: onCommand(int command)
case IDM_HELP_API:
openHelp();
break;
+ case IDM_DEBUG_INSPECT:
+ refreshDebugNode();
+ break;
default:
return false;
}
@@ -547,6 +574,11 @@ bool IDEWindow :: onCommand(int command)
return true;
}
+void IDEWindow :: refreshDebugNode()
+{
+ dynamic_cast(_children[_model->ideScheme.debugWatch])->refreshCurrentNode();
+}
+
void IDEWindow :: onStatusChange(StatusNMHDR* rec)
{
switch (rec->code) {
@@ -556,6 +588,12 @@ void IDEWindow :: onStatusChange(StatusNMHDR* rec)
case NOTIFY_IDE_CHANGE:
onIDEChange(rec->status);
break;
+ case NOTIFY_DEBUG_START:
+ onDebuggerStart();
+ break;
+ case NOTIFY_DEBUG_LOAD:
+ onDebuggerHook();
+ break;
case NOTIFY_DEBUG_CHANGE:
onDebuggerUpdate(rec);
break;
@@ -633,6 +671,16 @@ void IDEWindow :: onTreeSelChanged(HWND wnd)
}
}
+void IDEWindow :: onTreeItemExpanded(NMTREEVIEWW* rec)
+{
+ for (size_t i = 0; i < _childCounter; i++) {
+ if (_children[i]->checkHandle(rec->hdr.hwndFrom)) {
+ ((TreeView*)_children[i])->onItemExpand(rec->itemNew.hItem);
+ break;
+ }
+ }
+}
+
void IDEWindow :: onDoubleClick(NMHDR* hdr)
{
for (size_t i = 0; i < _childCounter; i++) {
@@ -643,6 +691,37 @@ void IDEWindow :: onDoubleClick(NMHDR* hdr)
}
}
+void IDEWindow :: onDebugWatchRClick(int controlIndex)
+{
+ DWORD dwpos = ::GetMessagePos();
+ Point p(LOWORD(dwpos), HIWORD(dwpos));
+
+ TreeView* treeView = ((TreeView*)_children[controlIndex]);
+
+ HTREEITEM item = treeView->hitTest(p.x, p.x);
+ if (item) {
+ treeView->select(item);
+ }
+
+ ContextMenu* menu = static_cast(_children[_model->ideScheme.debugContextMenu]);
+
+ menu->show(_handle, p);
+
+ //treeView->showContextMenu(LOWORD(dwpos), HIWORD(dwpos));
+}
+
+void IDEWindow :: onRClick(NMHDR* hdr)
+{
+ for (size_t i = 0; i < _childCounter; i++) {
+ if (_children[i]->checkHandle(hdr->hwndFrom)) {
+ if (i == _model->ideScheme.debugWatch) {
+ onDebugWatchRClick(i);
+ }
+ break;
+ }
+ }
+}
+
void IDEWindow :: onSelection(SelectionNMHDR* rec)
{
switch (rec->code) {
@@ -666,6 +745,17 @@ void IDEWindow :: onSelection(SelectionNMHDR* rec)
}
}
+void IDEWindow :: onTreeItem(TreeItemNMHDR* rec)
+{
+ switch (rec->code) {
+ case NOTIFY_DEBUG_CONTEXT_EXPANDED:
+ onDebugWatchBrowse(rec->item, rec->param);
+ break;
+ default:
+ break;
+ }
+}
+
void IDEWindow :: onDebugResult(int code)
{
switch (code) {
@@ -710,6 +800,9 @@ void IDEWindow :: onNotify(NMHDR* hdr)
case STATUS_SELECTION:
onSelection((SelectionNMHDR*)hdr);
break;
+ case STATUS_TREEITEM:
+ onTreeItem((TreeItemNMHDR*)hdr);
+ break;
case STATUS_COMPLETION:
onComplition((CompletionNMHDR*)hdr);
break;
@@ -722,11 +815,29 @@ void IDEWindow :: onNotify(NMHDR* hdr)
case TVN_SELCHANGED:
onTreeSelChanged(hdr->hwndFrom);
break;
+ case TVN_ITEMEXPANDING:
+ onTreeItemExpanded((NMTREEVIEW*)hdr);
+ break;
+ case NM_RCLICK:
+ onRClick(hdr);
+ break;
default:
break;
}
}
+void IDEWindow :: onDebuggerStart()
+{
+ ContextBrowserBase* contextBrowser = dynamic_cast(_children[_model->ideScheme.debugWatch]);
+
+ contextBrowser->clearRootNode();
+}
+
+void IDEWindow :: onDebuggerHook()
+{
+ _controller->onDebuggerHook(_model);
+}
+
void IDEWindow :: onDebuggerUpdate(StatusNMHDR* rec)
{
MenuBase* menu = dynamic_cast(_children[_model->ideScheme.menu]);
@@ -793,7 +904,7 @@ void IDEWindow :: onDebuggerUpdate(StatusNMHDR* rec)
bool IDEWindow :: onClose()
{
- if (!_controller->onClose(fileDialog, _model))
+ if (!_controller->onClose(fileDialog, messageDialog, _model))
return false;
return WindowBase::onClose();
@@ -832,4 +943,8 @@ void IDEWindow :: onDocumentUpdate(DocumentChangeStatus& changeStatus)
menu->enableMenuItemById(IDM_EDIT_UNDO, docInfo->canUndo());
menu->enableMenuItemById(IDM_EDIT_REDO, docInfo->canRedo());
}
+
+ if (changeStatus.textChanged || changeStatus.caretChanged) {
+ _controller->onStatusChange(_model, IDEStatus::Ready);
+ }
}
diff --git a/elenasrc3/ide/windows/winide.h b/elenasrc3/ide/windows/winide.h
index b87058bbf7..ab15b6b4e1 100644
--- a/elenasrc3/ide/windows/winide.h
+++ b/elenasrc3/ide/windows/winide.h
@@ -39,17 +39,20 @@ namespace elena_lang
// --- IDEWindow ---
class IDEWindow : public SDIWindow, DocumentNotifier
{
- Dialog fileDialog;
- Dialog projectDialog;
- Clipboard clipboard;
+ FileDialog fileDialog;
+ FileDialog projectDialog;
+ MessageDialog messageDialog;
+ ProjectSettings projectSettingsDialog;
+ Clipboard clipboard;
- HINSTANCE _instance;
+ HINSTANCE _instance;
- IDEModel* _model;
- IDEController* _controller;
+ IDEModel* _model;
+ IDEController* _controller;
void onStatusChange(StatusNMHDR* rec);
void onSelection(SelectionNMHDR* rec);
+ void onTreeItem(TreeItemNMHDR* rec);
void onComplition(CompletionNMHDR* rec);
//void onModelChange(ExtNMHDR* hdr);
//void onNotifyMessage(ExtNMHDR* hdr);
@@ -57,10 +60,13 @@ namespace elena_lang
void onDebugWatch();
void onDoubleClick(NMHDR* hdr);
+ void onRClick(NMHDR* hdr);
+ void onDebugWatchRClick(int index);
void onTabSelChanged(HWND wnd);
void onTreeSelChanged(HWND wnd);
void onChildRefresh(int controlId);
+ void onTreeItemExpanded(NMTREEVIEW* rec);
void onLayoutChange(NotificationStatus status);
void onIDEChange(NotificationStatus status);
@@ -75,6 +81,7 @@ namespace elena_lang
void onCompilationEnd(int exitCode);
void onErrorHighlight(int index);
void onDebugResult(int code);
+ void onDebugWatchBrowse(size_t item, size_t param);
void onProjectChange(bool empty);
void onProjectViewSel(size_t index);
@@ -91,6 +98,7 @@ namespace elena_lang
void saveFile();
void closeFile();
void closeAll();
+ void newProject();
void openProject();
void closeProject();
void exit() override;
@@ -106,7 +114,11 @@ namespace elena_lang
void openHelp();
+ void refreshDebugNode();
+
void onIDEViewUpdate(bool forced);
+ void onDebuggerStart();
+ void onDebuggerHook();
void onDebuggerUpdate(StatusNMHDR* rec);
void onDocumentUpdate(DocumentChangeStatus& changeStatus) override;
diff --git a/elenasrc3/tools/asmc/armassembler.cpp b/elenasrc3/tools/asmc/armassembler.cpp
index f1334ec4f6..a681b62da1 100644
--- a/elenasrc3/tools/asmc/armassembler.cpp
+++ b/elenasrc3/tools/asmc/armassembler.cpp
@@ -625,6 +625,11 @@ JumpType Arm64Assembler :: readCond(ScriptToken& tokenInfo)
return JumpType::LT;
}
+ else if (tokenInfo.compare("cc")) {
+ read(tokenInfo);
+
+ return JumpType::CC;
+ }
else throw SyntaxError(ASM_INVALID_TARGET, tokenInfo.lineInfo);
}
@@ -859,6 +864,17 @@ bool Arm64Assembler :: compileEORShifted(ScriptToken& tokenInfo, ARMOperand rd,
return true;
}
+bool Arm64Assembler :: compileFABS(ARMOperand rd, ARMOperand rn, MemoryWriter& writer)
+{
+ if (rd.isDR() && rn.isDR()) {
+ writer.writeDWord(ARMHelper::makeRMode3Opcode(0, 0, 0x1E, 1, 1, 0, 1, 0x10,
+ rn.type, rd.type));
+ }
+ else return false;
+
+ return true;
+}
+
bool Arm64Assembler::compileFADD(ScriptToken& tokenInfo, ARMOperand rd, ARMOperand rn, ARMOperand rm,
MemoryWriter& writer)
{
@@ -925,6 +941,17 @@ bool Arm64Assembler :: compileFRINTZ(ARMOperand rd, ARMOperand rn, MemoryWriter&
return true;
}
+bool Arm64Assembler :: compileFRINTN(ARMOperand rd, ARMOperand rn, MemoryWriter& writer)
+{
+ if (rd.isDR() && rn.isDR()) {
+ writer.writeDWord(ARMHelper::makeRMode2Opcode(0, 0, 0x1E, 1, 1, 1, 0, 0x10,
+ rn.type, rd.type));
+ }
+ else return false;
+
+ return true;
+}
+
bool Arm64Assembler :: compileFRINTX(ARMOperand rd, ARMOperand rn, MemoryWriter& writer)
{
if (rd.isDR() && rn.isDR()) {
@@ -958,6 +985,17 @@ bool Arm64Assembler :: compileFRINT64Z(ARMOperand rd, ARMOperand rn, MemoryWrite
return true;
}
+bool Arm64Assembler :: compileFSQRT(ARMOperand rd, ARMOperand rn, MemoryWriter& writer)
+{
+ if (rd.isDR() && rn.isDR()) {
+ writer.writeDWord(ARMHelper::makeRMode3Opcode(0, 0, 0x1E, 1, 1, 0, 3, 0x10,
+ rn.type, rd.type));
+ }
+ else return false;
+
+ return true;
+}
+
bool Arm64Assembler :: compileFSUB(ScriptToken& tokenInfo, ARMOperand rd, ARMOperand rn, ARMOperand rm,
MemoryWriter& writer)
{
@@ -1223,6 +1261,16 @@ bool Arm64Assembler :: compileSDIV(ARMOperand rd, ARMOperand rn, ARMOperand rm,
return true;
}
+bool Arm64Assembler :: compileUDIV(ARMOperand rd, ARMOperand rn, ARMOperand rm, MemoryWriter& writer)
+{
+ if (rm.isXR() && rn.isXR() && rd.isXR()) {
+ writer.writeDWord(ARMHelper::makeOpcode(1, 0, 0, 0xD6, rm.type, 1, 0, rn.type, rd.type));
+ }
+ else return false;
+
+ return true;
+}
+
bool Arm64Assembler :: compileSTP(ARMOperand t1, ARMOperand t2, ARMOperand ptr, MemoryWriter& writer)
{
if (t1.isXR() && t2.isXR() && ptr.isPreindex()) {
@@ -1585,6 +1633,20 @@ void Arm64Assembler :: compileEOR(ScriptToken& tokenInfo, MemoryWriter& writer)
throw SyntaxError(ASM_INVALID_COMMAND, tokenInfo.lineInfo);
}
+void Arm64Assembler :: compileFABS(ScriptToken& tokenInfo, MemoryWriter& writer)
+{
+ ARMOperand rd = readOperand(tokenInfo, ASM_INVALID_SOURCE);
+
+ checkComma(tokenInfo);
+
+ ARMOperand rn = readOperand(tokenInfo, ASM_INVALID_TARGET);
+
+ bool valid = compileFABS(rd, rn, writer);
+
+ if (!valid)
+ throw SyntaxError(ASM_INVALID_COMMAND, tokenInfo.lineInfo);
+}
+
void Arm64Assembler :: compileFADD(ScriptToken& tokenInfo, MemoryWriter& writer)
{
ARMOperand rd = readOperand(tokenInfo, ASM_INVALID_SOURCE);
@@ -1684,6 +1746,20 @@ void Arm64Assembler :: compileFRINTZ(ScriptToken& tokenInfo, MemoryWriter& write
throw SyntaxError(ASM_INVALID_COMMAND, tokenInfo.lineInfo);
}
+void Arm64Assembler :: compileFRINTN(ScriptToken& tokenInfo, MemoryWriter& writer)
+{
+ ARMOperand rd = readOperand(tokenInfo, ASM_INVALID_SOURCE);
+
+ checkComma(tokenInfo);
+
+ ARMOperand rn = readOperand(tokenInfo, ASM_INVALID_TARGET);
+
+ bool valid = compileFRINTN(rd, rn, writer);
+
+ if (!valid)
+ throw SyntaxError(ASM_INVALID_COMMAND, tokenInfo.lineInfo);
+}
+
void Arm64Assembler :: compileFRINTX(ScriptToken& tokenInfo, MemoryWriter& writer)
{
ARMOperand rd = readOperand(tokenInfo, ASM_INVALID_SOURCE);
@@ -1726,6 +1802,20 @@ void Arm64Assembler :: compileFRINT64Z(ScriptToken& tokenInfo, MemoryWriter& wri
throw SyntaxError(ASM_INVALID_COMMAND, tokenInfo.lineInfo);
}
+void Arm64Assembler :: compileFSQRT(ScriptToken& tokenInfo, MemoryWriter& writer)
+{
+ ARMOperand rd = readOperand(tokenInfo, ASM_INVALID_SOURCE);
+
+ checkComma(tokenInfo);
+
+ ARMOperand rn = readOperand(tokenInfo, ASM_INVALID_TARGET);
+
+ bool valid = compileFSQRT(rd, rn, writer);
+
+ if (!valid)
+ throw SyntaxError(ASM_INVALID_COMMAND, tokenInfo.lineInfo);
+}
+
void Arm64Assembler :: compileFSUB(ScriptToken& tokenInfo, MemoryWriter& writer)
{
ARMOperand rd = readOperand(tokenInfo, ASM_INVALID_SOURCE);
@@ -2121,6 +2211,24 @@ void Arm64Assembler :: compileSDIV(ScriptToken& tokenInfo, MemoryWriter& writer)
throw SyntaxError(ASM_INVALID_COMMAND, tokenInfo.lineInfo);
}
+void Arm64Assembler :: compileUDIV(ScriptToken& tokenInfo, MemoryWriter& writer)
+{
+ ARMOperand rd = readOperand(tokenInfo, ASM_INVALID_SOURCE);
+
+ checkComma(tokenInfo);
+
+ ARMOperand rn = readOperand(tokenInfo, ASM_INVALID_TARGET);
+
+ checkComma(tokenInfo);
+
+ ARMOperand rm = readOperand(tokenInfo, ASM_INVALID_TARGET);
+
+ bool isValid = compileUDIV(rd, rn, rm, writer);
+
+ if (!isValid)
+ throw SyntaxError(ASM_INVALID_COMMAND, tokenInfo.lineInfo);
+}
+
void Arm64Assembler :: compileSTP(ScriptToken& tokenInfo, MemoryWriter& writer)
{
ARMOperand t1 = readOperand(tokenInfo, ASM_INVALID_SOURCE);
@@ -2400,7 +2508,10 @@ bool Arm64Assembler :: compileEOpCode(ScriptToken& tokenInfo, MemoryWriter& writ
bool Arm64Assembler :: compileFOpCode(ScriptToken& tokenInfo, MemoryWriter& writer)
{
- if (tokenInfo.compare("fadd")) {
+ if (tokenInfo.compare("fabs")) {
+ compileFABS(tokenInfo, writer);
+ }
+ else if (tokenInfo.compare("fadd")) {
compileFADD(tokenInfo, writer);
}
else if (tokenInfo.compare("fcmp")) {
@@ -2415,6 +2526,9 @@ bool Arm64Assembler :: compileFOpCode(ScriptToken& tokenInfo, MemoryWriter& writ
else if (tokenInfo.compare("fmul")) {
compileFMUL(tokenInfo, writer);
}
+ else if (tokenInfo.compare("frintn")) {
+ compileFRINTN(tokenInfo, writer);
+ }
else if (tokenInfo.compare("frintz")) {
compileFRINTZ(tokenInfo, writer);
}
@@ -2427,6 +2541,9 @@ bool Arm64Assembler :: compileFOpCode(ScriptToken& tokenInfo, MemoryWriter& writ
else if (tokenInfo.compare("frint64z")) {
compileFRINT64Z(tokenInfo, writer);
}
+ else if (tokenInfo.compare("fsqrt")) {
+ compileFSQRT(tokenInfo, writer);
+ }
else if (tokenInfo.compare("fsub")) {
compileFSUB(tokenInfo, writer);
}
@@ -2577,6 +2694,16 @@ bool Arm64Assembler :: compileTOpCode(ScriptToken& tokenInfo, MemoryWriter& writ
return true;
}
+bool Arm64Assembler :: compileUOpCode(ScriptToken& tokenInfo, MemoryWriter& writer)
+{
+ if (tokenInfo.compare("udiv")) {
+ compileUDIV(tokenInfo, writer);
+ }
+ else return false;
+
+ return true;
+}
+
bool Arm64Assembler::compileXOpCode(ScriptToken& tokenInfo, MemoryWriter& writer)
{
return false;
diff --git a/elenasrc3/tools/asmc/armassembler.h b/elenasrc3/tools/asmc/armassembler.h
index 1619743885..956554c572 100644
--- a/elenasrc3/tools/asmc/armassembler.h
+++ b/elenasrc3/tools/asmc/armassembler.h
@@ -51,15 +51,18 @@ namespace elena_lang
virtual bool compileCSINC(ARMOperand rd, ARMOperand rn, ARMOperand rm, JumpType cond, MemoryWriter& writer);
virtual bool compileEORShifted(ScriptToken& tokenInfo, ARMOperand rt, ARMOperand rx, ARMOperand ry,
int shift, int ampount, MemoryWriter& writer);
+ virtual bool compileFABS(ARMOperand rd, ARMOperand rn, MemoryWriter& writer);
virtual bool compileFADD(ScriptToken& tokenInfo, ARMOperand rd, ARMOperand rn, ARMOperand rm, MemoryWriter& writer);
virtual bool compileFCMP(ARMOperand rd, ARMOperand rn, MemoryWriter& writer);
virtual bool compileFDIV(ScriptToken& tokenInfo, ARMOperand rd, ARMOperand rn, ARMOperand rm, MemoryWriter& writer);
virtual bool compileFCVTZS(ARMOperand rd, ARMOperand rn, MemoryWriter& writer);
virtual bool compileFMUL(ScriptToken& tokenInfo, ARMOperand rd, ARMOperand rn, ARMOperand rm, MemoryWriter& writer);
virtual bool compileFRINTZ(ARMOperand rd, ARMOperand rn, MemoryWriter& writer);
+ virtual bool compileFRINTN(ARMOperand rd, ARMOperand rn, MemoryWriter& writer);
virtual bool compileFRINTX(ARMOperand rd, ARMOperand rn, MemoryWriter& writer);
virtual bool compileFRINT32Z(ARMOperand rd, ARMOperand rn, MemoryWriter& writer);
virtual bool compileFRINT64Z(ARMOperand rd, ARMOperand rn, MemoryWriter& writer);
+ virtual bool compileFSQRT(ARMOperand rd, ARMOperand rn, MemoryWriter& writer);
virtual bool compileFSUB(ScriptToken& tokenInfo, ARMOperand rd, ARMOperand rn, ARMOperand rm, MemoryWriter& writer);
virtual bool compileLDP(ARMOperand rt, ARMOperand rx, ARMOperand n1, ARMOperand n2, MemoryWriter& writer);
virtual bool compileLDR(ScriptToken& tokenInfo, ARMOperand rt, ARMOperand ptr, MemoryWriter& writer);
@@ -96,6 +99,7 @@ namespace elena_lang
virtual bool compileSUBSShifted(ScriptToken& tokenInfo, ARMOperand rd, ARMOperand rn, ARMOperand rt,
int shift, int ampount, MemoryWriter& writer);
virtual bool compileUBFM(ARMOperand rd, ARMOperand rn, ARMOperand immr, ARMOperand imms, MemoryWriter& writer);
+ virtual bool compileUDIV(ARMOperand rd, ARMOperand rn, ARMOperand rm, MemoryWriter& writer);
void compileADD(ScriptToken& tokenInfo, MemoryWriter& writer);
void compileADRP(ScriptToken& tokenInfo, MemoryWriter& writer);
@@ -109,15 +113,18 @@ namespace elena_lang
void compileCSINC(ScriptToken& tokenInfo, MemoryWriter& writer);
void compileCMP(ScriptToken& tokenInfo, MemoryWriter& writer);
void compileEOR(ScriptToken& tokenInfo, MemoryWriter& writer);
+ void compileFABS(ScriptToken& tokenInfo, MemoryWriter& writer);
void compileFADD(ScriptToken& tokenInfo, MemoryWriter& writer);
void compileFCMP(ScriptToken& tokenInfo, MemoryWriter& writer);
void compileFCVTZS(ScriptToken& tokenInfo, MemoryWriter& writer);
void compileFDIV(ScriptToken& tokenInfo, MemoryWriter& writer);
void compileFMUL(ScriptToken& tokenInfo, MemoryWriter& writer);
void compileFRINTZ(ScriptToken& tokenInfo, MemoryWriter& writer);
+ void compileFRINTN(ScriptToken& tokenInfo, MemoryWriter& writer);
void compileFRINTX(ScriptToken& tokenInfo, MemoryWriter& writer);
void compileFRINT32Z(ScriptToken& tokenInfo, MemoryWriter& writer);
void compileFRINT64Z(ScriptToken& tokenInfo, MemoryWriter& writer);
+ void compileFSQRT(ScriptToken& tokenInfo, MemoryWriter& writer);
void compileFSUB(ScriptToken& tokenInfo, MemoryWriter& writer);
void compileLDP(ScriptToken& tokenInfo, MemoryWriter& writer);
void compileLDR(ScriptToken& tokenInfo, MemoryWriter& writer);
@@ -145,6 +152,7 @@ namespace elena_lang
void compileSXTH(ScriptToken& tokenInfo, MemoryWriter& writer);
void compileSXTW(ScriptToken& tokenInfo, MemoryWriter& writer);
void compileTST(ScriptToken& tokenInfo, MemoryWriter& writer);
+ void compileUDIV(ScriptToken& tokenInfo, MemoryWriter& writer);
bool compileAOpCode(ScriptToken& tokenInfo, MemoryWriter& writer) override;
bool compileBOpCode(ScriptToken& tokenInfo, MemoryWriter& writer, LabelScope& labelScope) override;
@@ -162,6 +170,7 @@ namespace elena_lang
bool compileROpCode(ScriptToken& tokenInfo, MemoryWriter& writer) override;
bool compileSOpCode(ScriptToken& tokenInfo, MemoryWriter& writer) override;
bool compileTOpCode(ScriptToken& tokenInfo, MemoryWriter& writer) override;
+ bool compileUOpCode(ScriptToken& tokenInfo, MemoryWriter& writer) override;
bool compileXOpCode(ScriptToken& tokenInfo, MemoryWriter& writer) override;
void compileDBField(ScriptToken& tokenInfo, MemoryWriter& writer) override;
diff --git a/elenasrc3/tools/asmc/asmc.cpp b/elenasrc3/tools/asmc/asmc.cpp
index b12af79a8c..a39554640e 100644
--- a/elenasrc3/tools/asmc/asmc.cpp
+++ b/elenasrc3/tools/asmc/asmc.cpp
@@ -3,7 +3,7 @@
//
// Asm2BinX main file
//
-// (C)2021, by Aleksey Rakov
+// (C)2021-2023, by Aleksey Rakov
//---------------------------------------------------------------------------
#include
@@ -94,7 +94,7 @@ template void compileAssembly(path_t source, path_t target)
void compileByteCode(path_t source, path_t target, bool mode64, int rawDataAlignment)
{
FileNameString sourceName(source, true);
- ReferenceName name;
+ NamespaceString name;
name.pathToName(sourceName.str());
@@ -143,6 +143,9 @@ int main(int argc, char* argv[])
else if (arg.compare(ASM_ARM64_MODE)) {
mode = CompileMode::arm64;
}
+ else if (arg.compare(ASM_AARCH64_MODE)) {
+ mode = CompileMode::arm64;
+ }
else if (arg.compare(BC_32_MODE)) {
mode = CompileMode::bc32;
}
diff --git a/elenasrc3/tools/asmc/asmconst.h b/elenasrc3/tools/asmc/asmconst.h
index 1ae8ee2ed9..5c1b6178fd 100644
--- a/elenasrc3/tools/asmc/asmconst.h
+++ b/elenasrc3/tools/asmc/asmconst.h
@@ -12,7 +12,7 @@
namespace elena_lang
{
- #define ASM_REVISION_NUMBER 0x00A4
+ #define ASM_REVISION_NUMBER 0x00AE
constexpr auto N_ARGUMENT1 = "__n_1";
constexpr auto N_ARGUMENT2 = "__n_2";
@@ -69,6 +69,7 @@ namespace elena_lang
constexpr auto ASM_AMD64_MODE = "amd64";
constexpr auto ASM_PPC64le_MODE = "ppc64le";
constexpr auto ASM_ARM64_MODE = "arm64";
+ constexpr auto ASM_AARCH64_MODE = "aarch64";
constexpr auto BC_32_MODE = "bc32";
constexpr auto BC_64_MODE = "bc64";
diff --git a/elenasrc3/tools/asmc/assembler.cpp b/elenasrc3/tools/asmc/assembler.cpp
index 2b652b6e48..d49d469d15 100644
--- a/elenasrc3/tools/asmc/assembler.cpp
+++ b/elenasrc3/tools/asmc/assembler.cpp
@@ -375,6 +375,8 @@ bool AssemblerBase::compileOpCode(ScriptToken& tokenInfo, MemoryWriter& writer,
return compileSOpCode(tokenInfo, writer);
case 't':
return compileTOpCode(tokenInfo, writer);
+ case 'u':
+ return compileUOpCode(tokenInfo, writer);
case 'x':
return compileXOpCode(tokenInfo, writer);
default:
diff --git a/elenasrc3/tools/asmc/assembler.h b/elenasrc3/tools/asmc/assembler.h
index b4dd4f2813..df5c9d7d69 100644
--- a/elenasrc3/tools/asmc/assembler.h
+++ b/elenasrc3/tools/asmc/assembler.h
@@ -128,6 +128,7 @@ namespace elena_lang
virtual bool compileROpCode(ScriptToken& tokenInfo, MemoryWriter& writer) = 0;
virtual bool compileSOpCode(ScriptToken& tokenInfo, MemoryWriter& writer) = 0;
virtual bool compileTOpCode(ScriptToken& tokenInfo, MemoryWriter& writer) = 0;
+ virtual bool compileUOpCode(ScriptToken& tokenInfo, MemoryWriter& writer) = 0;
virtual bool compileXOpCode(ScriptToken& tokenInfo, MemoryWriter& writer) = 0;
virtual bool compileOpCode(ScriptToken& tokenInfo, MemoryWriter& writer, LabelScope& labelScope);
diff --git a/elenasrc3/tools/asmc/bcassembler.cpp b/elenasrc3/tools/asmc/bcassembler.cpp
index 9b04d4e85c..de868f0ea4 100644
--- a/elenasrc3/tools/asmc/bcassembler.cpp
+++ b/elenasrc3/tools/asmc/bcassembler.cpp
@@ -133,6 +133,13 @@ ref_t ByteCodeAssembler :: readReference(ScriptToken& tokenInfo, bool skipRead)
mask = mskTypeListRef;
}
+ else if (tokenInfo.compare("array")) {
+ read(tokenInfo, ":", ASM_DOUBLECOLON_EXPECTED);
+
+ _reader.read(tokenInfo);
+
+ mask = mskConstArray;
+ }
else if (tokenInfo.compare("pstr")) {
read(tokenInfo, ":", ASM_DOUBLECOLON_EXPECTED);
@@ -374,6 +381,14 @@ ByteCodeAssembler::Operand ByteCodeAssembler :: compileArg(ScriptToken& tokenInf
return arg;
}
+ else if (tokenInfo.compare("symbol")) {
+ read(tokenInfo, ":", ASM_DOUBLECOLON_EXPECTED);
+
+ arg.type = Operand::Type::R;
+ arg.reference = readReference(tokenInfo) | mskSymbolRef;
+
+ return arg;
+ }
else if (parameters.exist(*tokenInfo.token)) {
arg.type = Operand::Type::Variable;
arg.reference = parameters.get(*tokenInfo.token);
@@ -936,6 +951,7 @@ bool ByteCodeAssembler :: compileByteCode(ScriptToken& tokenInfo, MemoryWriter&
case ByteCode::CmpFI:
case ByteCode::PeekFI:
case ByteCode::SetFP:
+ case ByteCode::XSetFP:
return compileOpFrameI(tokenInfo, writer, opCommand, parameters, locals, true);
case ByteCode::PeekSI:
case ByteCode::StoreSI:
@@ -945,6 +961,7 @@ bool ByteCodeAssembler :: compileByteCode(ScriptToken& tokenInfo, MemoryWriter&
case ByteCode::SwapSI:
case ByteCode::XRefreshSI:
case ByteCode::XLoadArgSI:
+ case ByteCode::SaveSI:
return compileOpStackI(tokenInfo, writer, opCommand, true);
case ByteCode::SaveDP:
case ByteCode::LSaveDP:
@@ -952,14 +969,25 @@ bool ByteCodeAssembler :: compileByteCode(ScriptToken& tokenInfo, MemoryWriter&
case ByteCode::LoadDP:
case ByteCode::XCmpDP:
case ByteCode::FTruncDP:
+ case ByteCode::FRoundDP:
+ case ByteCode::FAbsDP:
+ case ByteCode::FSqrtDP:
+ case ByteCode::FExpDP:
+ case ByteCode::FLnDP:
+ case ByteCode::FSinDP:
+ case ByteCode::FCosDP:
+ case ByteCode::FArctanDP:
+ case ByteCode::FPiDP:
case ByteCode::NConvFDP:
case ByteCode::LLoadDP:
+ case ByteCode::XAddDP:
return compileDDisp(tokenInfo, writer, opCommand, dataLocals, true);
case ByteCode::TstM:
case ByteCode::MovM:
return compileOpM(tokenInfo, writer, opCommand, false);
case ByteCode::AssignI:
case ByteCode::GetI:
+ case ByteCode::AllocI:
return compileOpI(tokenInfo, writer, opCommand, false);
case ByteCode::XHookDPR:
return compileDDispR(tokenInfo, writer, opCommand, dataLocals, true);
@@ -970,6 +998,7 @@ bool ByteCodeAssembler :: compileByteCode(ScriptToken& tokenInfo, MemoryWriter&
return compileMR(tokenInfo, writer, opCommand, false);
case ByteCode::SelEqRR:
case ByteCode::SelLtRR:
+ case ByteCode::SelULtRR:
return compileRR(tokenInfo, writer, opCommand, true);
case ByteCode::ICmpN:
case ByteCode::TstN:
@@ -977,6 +1006,7 @@ bool ByteCodeAssembler :: compileByteCode(ScriptToken& tokenInfo, MemoryWriter&
case ByteCode::ReadN:
case ByteCode::WriteN:
case ByteCode::System:
+ case ByteCode::DCopy:
return compileOpN(tokenInfo, writer, opCommand, constants, true);
case ByteCode::MovN:
case ByteCode::AndN:
@@ -994,7 +1024,9 @@ bool ByteCodeAssembler :: compileByteCode(ScriptToken& tokenInfo, MemoryWriter&
case ByteCode::Jne:
case ByteCode::Jlt:
case ByteCode::Jge:
+ case ByteCode::Jle:
case ByteCode::Jump:
+ case ByteCode::Jgr:
return compileJcc(tokenInfo, writer, opCommand, lh);
case ByteCode::SetR:
case ByteCode::CmpR:
@@ -1006,6 +1038,10 @@ bool ByteCodeAssembler :: compileByteCode(ScriptToken& tokenInfo, MemoryWriter&
case ByteCode::NAddDPN:
case ByteCode::CopyDPN:
case ByteCode::IAddDPN:
+ case ByteCode::ISubDPN:
+ case ByteCode::IMulDPN:
+ case ByteCode::IDivDPN:
+ case ByteCode::UDivDPN:
return compileDDispN(tokenInfo, writer, opCommand, dataLocals, constants, true);
default:
return false;
diff --git a/elenasrc3/tools/asmc/bcassembler.h b/elenasrc3/tools/asmc/bcassembler.h
index 3c4789e066..a06e641e38 100644
--- a/elenasrc3/tools/asmc/bcassembler.h
+++ b/elenasrc3/tools/asmc/bcassembler.h
@@ -3,7 +3,7 @@
//
// This header contains Byte-code Assembler declarations
//
-// (C)2021-2022, by Aleksey Rakov
+// (C)2021-2023, by Aleksey Rakov
//---------------------------------------------------------------------------
#ifndef BCASSEMBLER_H
@@ -43,6 +43,12 @@ namespace elena_lang
void writeJgeBack(pos_t label, MemoryWriter& writer) override {}
void writeJgeForward(pos_t label, MemoryWriter& writer, int byteCodeOffset) override {}
+ void writeJleBack(pos_t label, MemoryWriter& writer) override {}
+ void writeJleForward(pos_t label, MemoryWriter& writer, int byteCodeOffset) override {}
+
+ void writeJgrBack(pos_t label, MemoryWriter& writer) override {}
+ void writeJgrForward(pos_t label, MemoryWriter& writer, int byteCodeOffset) override {}
+
ref_t getLabel(ustr_t labelName)
{
return labelNames.get(labelName);
diff --git a/elenasrc3/tools/asmc/ppc64assembler.cpp b/elenasrc3/tools/asmc/ppc64assembler.cpp
index 93382f10a1..9c154cbc6d 100644
--- a/elenasrc3/tools/asmc/ppc64assembler.cpp
+++ b/elenasrc3/tools/asmc/ppc64assembler.cpp
@@ -661,6 +661,14 @@ void PPC64Assembler :: compileCMP(ScriptToken& tokenInfo, int bf, int l, PPCOper
else throw SyntaxError(ASM_INVALID_COMMAND, tokenInfo.lineInfo);
}
+void PPC64Assembler :: compileCMPL(ScriptToken& tokenInfo, int bf, int l, PPCOperand ra, PPCOperand rb, MemoryWriter& writer)
+{
+ if (ra.isGPR() && rb.isGPR()) {
+ writer.writeDWord(PPCHelper::makeXCommand(31, bf, l, ra.type, rb.type, 32));
+ }
+ else throw SyntaxError(ASM_INVALID_COMMAND, tokenInfo.lineInfo);
+}
+
void PPC64Assembler :: compileCMPI(ScriptToken& tokenInfo, int bf, int l, PPCOperand ra, int i, ref_t reference, MemoryWriter& writer)
{
if (ra.isGPR()) {
@@ -888,6 +896,13 @@ void PPC64Assembler :: compileBGE(ScriptToken& tokenInfo, MemoryWriter& writer,
read(tokenInfo);
}
+void PPC64Assembler :: compileBSO(ScriptToken& tokenInfo, MemoryWriter& writer, LabelScope& labelScope)
+{
+ compileBCxx(tokenInfo, 12, 3, writer, labelScope);
+
+ read(tokenInfo);
+}
+
void PPC64Assembler :: compileBLR(ScriptToken& tokenInfo, MemoryWriter& writer)
{
compileBCLR(20, 0, 0, writer);
@@ -895,7 +910,6 @@ void PPC64Assembler :: compileBLR(ScriptToken& tokenInfo, MemoryWriter& writer)
read(tokenInfo);
}
-
void PPC64Assembler::compileBCTR(ScriptToken& tokenInfo, MemoryWriter& writer)
{
compileBCCTR(20, 0, 0, writer);
@@ -952,6 +966,20 @@ void PPC64Assembler :: compileEXTRDI(ScriptToken& tokenInfo, MemoryWriter& write
else throw SyntaxError(ASM_INVALID_COMMAND, tokenInfo.lineInfo);
}
+void PPC64Assembler :: compileFABS(ScriptToken& tokenInfo, MemoryWriter& writer)
+{
+ PPCOperand frt = readRegister(tokenInfo, ASM_INVALID_SOURCE);
+
+ checkComma(tokenInfo);
+
+ PPCOperand frb = readRegister(tokenInfo, ASM_INVALID_SOURCE);
+
+ if (frt.isFPR() && frb.isFPR()) {
+ writer.writeDWord(PPCHelper::makeXCommand(63, frt.type,
+ frb.type, 264, 0));
+ }
+}
+
void PPC64Assembler :: compileFCFID(ScriptToken& tokenInfo, MemoryWriter& writer)
{
PPCOperand frt = readRegister(tokenInfo, ASM_INVALID_SOURCE);
@@ -980,6 +1008,34 @@ void PPC64Assembler :: compileFRIZ(ScriptToken& tokenInfo, MemoryWriter& writer)
}
}
+void PPC64Assembler :: compileFRIN(ScriptToken& tokenInfo, MemoryWriter& writer)
+{
+ PPCOperand frt = readRegister(tokenInfo, ASM_INVALID_SOURCE);
+
+ checkComma(tokenInfo);
+
+ PPCOperand frb = readRegister(tokenInfo, ASM_INVALID_SOURCE);
+
+ if (frt.isFPR() && frb.isFPR()) {
+ writer.writeDWord(PPCHelper::makeXCommand(63, frt.type,
+ frb.type, 392, 0));
+ }
+}
+
+void PPC64Assembler :: compileFSQRT(ScriptToken& tokenInfo, MemoryWriter& writer)
+{
+ PPCOperand frt = readRegister(tokenInfo, ASM_INVALID_SOURCE);
+
+ checkComma(tokenInfo);
+
+ PPCOperand frb = readRegister(tokenInfo, ASM_INVALID_SOURCE);
+
+ if (frt.isFPR() && frb.isFPR()) {
+ writer.writeDWord(PPCHelper::makeXCommand(63, frt.type,
+ frb.type, 22, 0));
+ }
+}
+
void PPC64Assembler :: compileCMP(ScriptToken& tokenInfo, MemoryWriter& writer)
{
PPCOperand ra = readRegister(tokenInfo, ASM_INVALID_SOURCE);
@@ -991,6 +1047,17 @@ void PPC64Assembler :: compileCMP(ScriptToken& tokenInfo, MemoryWriter& writer)
compileCMP(tokenInfo, 0, 0, ra, rb, writer);
}
+void PPC64Assembler :: compileCMPL(ScriptToken& tokenInfo, MemoryWriter& writer)
+{
+ PPCOperand ra = readRegister(tokenInfo, ASM_INVALID_SOURCE);
+
+ checkComma(tokenInfo);
+
+ PPCOperand rb = readRegister(tokenInfo, ASM_INVALID_TARGET);
+
+ compileCMPL(tokenInfo, 0, 0, ra, rb, writer);
+}
+
void PPC64Assembler :: compileFCMPU(ScriptToken& tokenInfo, MemoryWriter& writer)
{
PPCOperand ra = readRegister(tokenInfo, ASM_INVALID_SOURCE);
@@ -1080,6 +1147,25 @@ void PPC64Assembler :: compileDIVW(ScriptToken& tokenInfo, MemoryWriter& writer)
else throw SyntaxError(ASM_INVALID_COMMAND, tokenInfo.lineInfo);
}
+void PPC64Assembler :: compileDIVWU(ScriptToken& tokenInfo, MemoryWriter& writer)
+{
+ PPCOperand rx = readRegister(tokenInfo, ASM_INVALID_SOURCE);
+
+ checkComma(tokenInfo);
+
+ PPCOperand ry = readRegister(tokenInfo, ASM_INVALID_SOURCE);
+
+ checkComma(tokenInfo);
+
+ PPCOperand rz = readRegister(tokenInfo, ASM_INVALID_SOURCE);
+
+ if (rx.isGPR() && ry.isGPR() && rz.isGPR()) {
+ writer.writeDWord(PPCHelper::makeXOCommand(31, rx.type, ry.type,
+ rz.type, 0, 459, 0));
+ }
+ else throw SyntaxError(ASM_INVALID_COMMAND, tokenInfo.lineInfo);
+}
+
void PPC64Assembler :: compileFADD(ScriptToken& tokenInfo, MemoryWriter& writer)
{
PPCOperand rt = readRegister(tokenInfo, ASM_INVALID_SOURCE);
@@ -1334,7 +1420,6 @@ void PPC64Assembler :: compileISELLT(ScriptToken& tokenInfo, MemoryWriter& write
if (!compileISEL(rx, ry, rz, 0, writer))
throw SyntaxError(ASM_INVALID_COMMAND, tokenInfo.lineInfo);
-
}
void PPC64Assembler :: compileLIS(ScriptToken& tokenInfo, MemoryWriter& writer)
@@ -1837,6 +1922,9 @@ bool PPC64Assembler :: compileBOpCode(ScriptToken& tokenInfo, MemoryWriter& writ
else if (tokenInfo.compare("bge")) {
compileBGE(tokenInfo, writer, labelScope);
}
+ else if (tokenInfo.compare("bso")) {
+ compileBSO(tokenInfo, writer, labelScope);
+ }
else return false;
return true;
@@ -1847,6 +1935,9 @@ bool PPC64Assembler :: compileCOpCode(ScriptToken& tokenInfo, MemoryWriter& writ
if (tokenInfo.compare("cmp")) {
compileCMP(tokenInfo, writer);
}
+ else if (tokenInfo.compare("cmpl")) {
+ compileCMPL(tokenInfo, writer);
+ }
else if (tokenInfo.compare("cmpwi")) {
compileCMPWI(tokenInfo, writer);
}
@@ -1866,6 +1957,9 @@ bool PPC64Assembler :: compileDOpCode(ScriptToken& tokenInfo, MemoryWriter& writ
else if (tokenInfo.compare("divw")) {
compileDIVW(tokenInfo, writer);
}
+ else if (tokenInfo.compare("divwu")) {
+ compileDIVWU(tokenInfo, writer);
+ }
else return false;
return true;
@@ -1886,7 +1980,10 @@ bool PPC64Assembler :: compileEOpCode(ScriptToken& tokenInfo, MemoryWriter& writ
bool PPC64Assembler::compileFOpCode(ScriptToken& tokenInfo, MemoryWriter& writer)
{
- if (tokenInfo.compare("fadd")) {
+ if (tokenInfo.compare("fabs")) {
+ compileFABS(tokenInfo, writer);
+ }
+ else if (tokenInfo.compare("fadd")) {
compileFADD(tokenInfo, writer);
}
else if (tokenInfo.compare("fcfid")) {
@@ -1904,9 +2001,15 @@ bool PPC64Assembler::compileFOpCode(ScriptToken& tokenInfo, MemoryWriter& writer
else if (tokenInfo.compare("fmul")) {
compileFMUL(tokenInfo, writer);
}
+ else if (tokenInfo.compare("frin")) {
+ compileFRIN(tokenInfo, writer);
+ }
else if (tokenInfo.compare("friz")) {
compileFRIZ(tokenInfo, writer);
}
+ else if (tokenInfo.compare("fsqrt")) {
+ compileFSQRT(tokenInfo, writer);
+ }
else if (tokenInfo.compare("fsub")) {
compileFSUB(tokenInfo, writer);
}
@@ -2082,6 +2185,11 @@ bool PPC64Assembler :: compileTOpCode(ScriptToken& tokenInfo, MemoryWriter& writ
return false;
}
+bool PPC64Assembler::compileUOpCode(ScriptToken& tokenInfo, MemoryWriter& writer)
+{
+ return false;
+}
+
bool PPC64Assembler :: compileXOpCode(ScriptToken& tokenInfo, MemoryWriter& writer)
{
if (tokenInfo.compare("xor")) {
diff --git a/elenasrc3/tools/asmc/ppc64assembler.h b/elenasrc3/tools/asmc/ppc64assembler.h
index 41d059071e..1ee5b8ba58 100644
--- a/elenasrc3/tools/asmc/ppc64assembler.h
+++ b/elenasrc3/tools/asmc/ppc64assembler.h
@@ -51,6 +51,8 @@ namespace elena_lang
void compileBCxx(ScriptToken& tokenInfo, int aa, int lk, MemoryWriter& writer, LabelScope& labelScope);
void compileCMP(ScriptToken& tokenInfo, int bf, int l, PPCOperand ra, PPCOperand rb,
MemoryWriter& writer);
+ void compileCMPL(ScriptToken& tokenInfo, int bf, int l, PPCOperand ra, PPCOperand rb,
+ MemoryWriter& writer);
void compileCMPI(ScriptToken& tokenInfo, int bf, int l, PPCOperand ra, int i, ref_t reference,
MemoryWriter& writer);
void compileFCMPU(ScriptToken& tokenInfo, int bf, PPCOperand fra, PPCOperand frb,
@@ -80,21 +82,27 @@ namespace elena_lang
void compileBNE(ScriptToken& tokenInfo, MemoryWriter& writer, LabelScope& labelScope);
void compileBLT(ScriptToken& tokenInfo, MemoryWriter& writer, LabelScope& labelScope);
void compileBGE(ScriptToken& tokenInfo, MemoryWriter& writer, LabelScope& labelScope);
+ void compileBSO(ScriptToken& tokenInfo, MemoryWriter& writer, LabelScope& labelScope);
void compileCMP(ScriptToken& tokenInfo, MemoryWriter& writer);
+ void compileCMPL(ScriptToken& tokenInfo, MemoryWriter& writer);
void compileCMPWI(ScriptToken& tokenInfo, MemoryWriter& writer);
void compileCMPDI(ScriptToken& tokenInfo, MemoryWriter& writer);
void compileFCTIW(ScriptToken& tokenInfo, MemoryWriter& writer);
void compileDIVD(ScriptToken& tokenInfo, MemoryWriter& writer);
void compileDIVW(ScriptToken& tokenInfo, MemoryWriter& writer);
+ void compileDIVWU(ScriptToken& tokenInfo, MemoryWriter& writer);
void compileEXTRDI(ScriptToken& tokenInfo, MemoryWriter& writer);
void compileEXTSW(ScriptToken& tokenInfo, MemoryWriter& writer);
+ void compileFABS(ScriptToken& tokenInfo, MemoryWriter& writer);
void compileFADD(ScriptToken& tokenInfo, MemoryWriter& writer);
void compileFSUB(ScriptToken& tokenInfo, MemoryWriter& writer);
void compileFCFID(ScriptToken& tokenInfo, MemoryWriter& writer);
void compileFCMPU(ScriptToken& tokenInfo, MemoryWriter& writer);
void compileFDIV(ScriptToken& tokenInfo, MemoryWriter& writer);
void compileFMUL(ScriptToken& tokenInfo, MemoryWriter& writer);
+ void compileFRIN(ScriptToken& tokenInfo, MemoryWriter& writer);
void compileFRIZ(ScriptToken& tokenInfo, MemoryWriter& writer);
+ void compileFSQRT(ScriptToken& tokenInfo, MemoryWriter& writer);
void compileISELEQ(ScriptToken& tokenInfo, MemoryWriter& writer);
void compileISELLT(ScriptToken& tokenInfo, MemoryWriter& writer);
void compileOR(ScriptToken& tokenInfo, MemoryWriter& writer);
@@ -153,6 +161,7 @@ namespace elena_lang
bool compileROpCode(ScriptToken& tokenInfo, MemoryWriter& writer) override;
bool compileSOpCode(ScriptToken& tokenInfo, MemoryWriter& writer) override;
bool compileTOpCode(ScriptToken& tokenInfo, MemoryWriter& writer) override;
+ bool compileUOpCode(ScriptToken& tokenInfo, MemoryWriter& writer) override;
bool compileXOpCode(ScriptToken& tokenInfo, MemoryWriter& writer) override;
void compileProcedure(ScriptToken& tokenInfo) override;
diff --git a/elenasrc3/tools/asmc/x86assembler.cpp b/elenasrc3/tools/asmc/x86assembler.cpp
index 234cfc3bd8..7d5043962c 100644
--- a/elenasrc3/tools/asmc/x86assembler.cpp
+++ b/elenasrc3/tools/asmc/x86assembler.cpp
@@ -664,9 +664,17 @@ void X86Assembler :: compileDiv(ScriptToken& tokenInfo, MemoryWriter& writer)
void X86Assembler :: compileFadd(ScriptToken& tokenInfo, MemoryWriter& writer)
{
+ bool valid = false;
X86Operand sour = compileOperand(tokenInfo, nullptr);
- bool valid = compileFadd(sour, writer);
+ if (sour.type == X86OperandType::ST) {
+ checkComma(tokenInfo);
+
+ X86Operand dest = compileOperand(tokenInfo, ASM_INVALID_DESTINATION);
+
+ valid = compileFadd(sour, dest, writer);
+ }
+ else valid = compileFadd(sour, writer);
if (!valid)
throw SyntaxError(ASM_INVALID_COMMAND, tokenInfo.lineInfo);
@@ -807,11 +815,131 @@ void X86Assembler :: compileFrndint(ScriptToken& tokenInfo, MemoryWriter& writer
writer.writeWord(0xFCD9);
}
+void X86Assembler :: compileFprem(ScriptToken& tokenInfo, MemoryWriter& writer)
+{
+ read(tokenInfo);
+
+ writer.writeWord(0xF8D9);
+}
+
+void X86Assembler :: compileFscale(ScriptToken& tokenInfo, MemoryWriter& writer)
+{
+ read(tokenInfo);
+
+ writer.writeWord(0xFDD9);
+}
+
+void X86Assembler :: compileFsin(ScriptToken& tokenInfo, MemoryWriter& writer)
+{
+ read(tokenInfo);
+
+ writer.writeWord(0xFED9);
+}
+
+void X86Assembler :: compileFcos(ScriptToken& tokenInfo, MemoryWriter& writer)
+{
+ read(tokenInfo);
+
+ writer.writeWord(0xFFD9);
+}
+
+void X86Assembler :: compileFpatan(ScriptToken& tokenInfo, MemoryWriter& writer)
+{
+ read(tokenInfo);
+
+ writer.writeWord(0xF3D9);
+}
+
+void X86Assembler :: compileF2xm1(ScriptToken& tokenInfo, MemoryWriter& writer)
+{
+ read(tokenInfo);
+
+ writer.writeWord(0xF0D9);
+}
+
+void X86Assembler :: compileFld1(ScriptToken& tokenInfo, MemoryWriter& writer)
+{
+ read(tokenInfo);
+
+ writer.writeWord(0xE8D9);
+}
+
+void X86Assembler :: compileFxch(ScriptToken& tokenInfo, MemoryWriter& writer)
+{
+ read(tokenInfo);
+
+ writer.writeWord(0xC9D9);
+}
+
+void X86Assembler :: compileFmulp(ScriptToken& tokenInfo, MemoryWriter& writer)
+{
+ read(tokenInfo);
+
+ writer.writeWord(0xC9DE);
+}
+
+void X86Assembler :: compileFldl2e(ScriptToken& tokenInfo, MemoryWriter& writer)
+{
+ read(tokenInfo);
+
+ writer.writeWord(0xEAD9);
+}
+
+void X86Assembler :: compileFldln2(ScriptToken& tokenInfo, MemoryWriter& writer)
+{
+ read(tokenInfo);
+
+ writer.writeWord(0xEDD9);
+}
+
+void X86Assembler :: compileFldpi(ScriptToken& tokenInfo, MemoryWriter& writer)
+{
+ read(tokenInfo);
+
+ writer.writeWord(0xEBD9);
+}
+
+void X86Assembler :: compileFyl2x(ScriptToken& tokenInfo, MemoryWriter& writer)
+{
+ read(tokenInfo);
+
+ writer.writeWord(0xF1D9);
+}
+
+void X86Assembler :: compileFaddp(ScriptToken& tokenInfo, MemoryWriter& writer)
+{
+ read(tokenInfo);
+
+ writer.writeWord(0xC1DE);
+}
+
+void X86Assembler :: compileFsqrt(ScriptToken& tokenInfo, MemoryWriter& writer)
+{
+ read(tokenInfo);
+
+ writer.writeWord(0xFAD9);
+}
+
+void X86Assembler :: compileFabs(ScriptToken& tokenInfo, MemoryWriter& writer)
+{
+ read(tokenInfo);
+
+ writer.writeWord(0xE1D9);
+}
+
void X86Assembler :: compileFsub(ScriptToken& tokenInfo, MemoryWriter& writer)
{
+ bool valid = false;
+
X86Operand sour = compileOperand(tokenInfo, nullptr);
+ if (sour.type == X86OperandType::ST) {
+ checkComma(tokenInfo);
- bool valid = compileFsub(sour, writer);
+ X86Operand dest = compileOperand(tokenInfo, ASM_INVALID_DESTINATION);
+
+ valid = compileFsub(sour, dest, writer);
+ }
+ else valid = compileFsub(sour, writer);
if (!valid)
throw SyntaxError(ASM_INVALID_COMMAND, tokenInfo.lineInfo);
@@ -1275,6 +1403,12 @@ bool X86Assembler :: compileAnd(X86Operand source, X86Operand target, MemoryWrit
writer.writeByte(0x21);
X86Helper::writeModRM(writer, target, source);
}
+ else if (source.isR16() && target.type == X86OperandType::DD) {
+ writer.writeByte(0x66);
+ writer.writeByte(0x81);
+ X86Helper::writeModRM(writer, { X86OperandType::R32 + 4 }, source);
+ writer.writeWord(target.offset);
+ }
else return false;
return true;
@@ -1394,6 +1528,21 @@ bool X86Assembler :: compileFadd(X86Operand source, MemoryWriter& writer)
}
+bool X86Assembler::compileFadd(X86Operand source, X86Operand target, MemoryWriter& writer)
+{
+ if (source.type == X86OperandType::ST && source.offset == 0 && target.type == X86OperandType::ST) {
+ writer.writeByte(0xD8);
+ writer.writeByte(0xC0 + target.offset);
+ }
+ else if (source.type == X86OperandType::ST && target.type == X86OperandType::ST && target.offset == 0) {
+ writer.writeByte(0xDC);
+ writer.writeByte(0xC0 + target.offset);
+ }
+ else return false;
+
+ return true;
+}
+
bool X86Assembler :: compileFcomip(X86Operand source, X86Operand target, MemoryWriter& writer)
{
if (source.type == X86OperandType::ST && source.offset == 0 && target.type == X86OperandType::ST) {
@@ -1554,6 +1703,21 @@ bool X86Assembler :: compileFsub(X86Operand source, MemoryWriter& writer)
return true;
}
+bool X86Assembler :: compileFsub(X86Operand source, X86Operand target, MemoryWriter& writer)
+{
+ if (source.type == X86OperandType::ST && source.offset == 0 && target.type == X86OperandType::ST) {
+ writer.writeByte(0xD8);
+ writer.writeByte(0xE0 + target.offset);
+ }
+ else if (source.type == X86OperandType::ST && target.type == X86OperandType::ST && target.offset == 0) {
+ writer.writeByte(0xDC);
+ writer.writeByte(0xE8 + target.offset);
+ }
+ else return false;
+
+ return true;
+}
+
bool X86Assembler :: compileIDiv(X86Operand source, MemoryWriter& writer)
{
if (source.isR32_M32()) {
@@ -1916,6 +2080,12 @@ bool X86Assembler :: compileSar(X86Operand source, X86Operand target, MemoryWrit
return true;
}
+void X86Assembler :: compileSahf(ScriptToken& tokenInfo, MemoryWriter& writer)
+{
+ writer.writeByte(0x9E);
+ read(tokenInfo);
+}
+
bool X86Assembler :: compileSbb(X86Operand source, X86Operand target, MemoryWriter& writer)
{
if (source.isR32_M32() && target.isR32()) {
@@ -2156,12 +2326,15 @@ bool X86Assembler :: compileCOpCode(ScriptToken& tokenInfo, MemoryWriter& writer
else if (tokenInfo.compare("cmp")) {
compileCmp(tokenInfo, writer);
}
- else if (tokenInfo.compare("cmovz")) {
- compileCMovcc(tokenInfo, writer, X86JumpType::JZ);
+ else if (tokenInfo.compare("cmovb")) {
+ compileCMovcc(tokenInfo, writer, X86JumpType::JB);
}
else if (tokenInfo.compare("cmovl")) {
compileCMovcc(tokenInfo, writer, X86JumpType::JL);
}
+ else if (tokenInfo.compare("cmovz")) {
+ compileCMovcc(tokenInfo, writer, X86JumpType::JZ);
+ }
else if (tokenInfo.compare("cwde")) {
compileCWDE(tokenInfo, writer);
}
@@ -2193,9 +2366,18 @@ bool X86Assembler :: compileEOpCode(ScriptToken& tokenInfo, MemoryWriter& writer
bool X86Assembler :: compileFOpCode(ScriptToken& tokenInfo, MemoryWriter& writer)
{
- if (tokenInfo.compare("fadd")) {
+ if (tokenInfo.compare("f2xm1")) {
+ compileF2xm1(tokenInfo, writer);
+ }
+ else if (tokenInfo.compare("fabs")) {
+ compileFabs(tokenInfo, writer);
+ }
+ else if (tokenInfo.compare("fadd")) {
compileFadd(tokenInfo, writer);
}
+ else if (tokenInfo.compare("faddp")) {
+ compileFaddp(tokenInfo, writer);
+ }
else if (tokenInfo.compare("fcomip")) {
compileFcomip(tokenInfo, writer);
}
@@ -2220,18 +2402,51 @@ bool X86Assembler :: compileFOpCode(ScriptToken& tokenInfo, MemoryWriter& writer
else if (tokenInfo.compare("fld")) {
compileFld(tokenInfo, writer);
}
+ else if (tokenInfo.compare("fld1")) {
+ compileFld1(tokenInfo, writer);
+ }
+ else if (tokenInfo.compare("fldl2e")) {
+ compileFldl2e(tokenInfo, writer);
+ }
else if (tokenInfo.compare("fldcw")) {
compileFldcw(tokenInfo, writer);
}
+ else if (tokenInfo.compare("fldln2")) {
+ compileFldln2(tokenInfo, writer);
+ }
+ else if (tokenInfo.compare("fldpi")) {
+ compileFldpi(tokenInfo, writer);
+ }
else if (tokenInfo.compare("fmul")) {
compileFmul(tokenInfo, writer);
}
+ else if (tokenInfo.compare("fmulp")) {
+ compileFmulp(tokenInfo, writer);
+ }
+ else if (tokenInfo.compare("fprem")) {
+ compileFprem(tokenInfo, writer);
+ }
else if (tokenInfo.compare("frndint")) {
compileFrndint(tokenInfo, writer);
}
+ else if (tokenInfo.compare("fscale")) {
+ compileFscale(tokenInfo, writer);
+ }
+ else if (tokenInfo.compare("fsin")) {
+ compileFsin(tokenInfo, writer);
+ }
+ else if (tokenInfo.compare("fcos")) {
+ compileFcos(tokenInfo, writer);
+ }
+ else if (tokenInfo.compare("fpatan")) {
+ compileFpatan(tokenInfo, writer);
+ }
else if (tokenInfo.compare("fstcw")) {
compileFstcw(tokenInfo, writer);
}
+ else if (tokenInfo.compare("fsqrt")) {
+ compileFsqrt(tokenInfo, writer);
+ }
else if (tokenInfo.compare("fstp")) {
compileFstp(tokenInfo, writer);
}
@@ -2241,6 +2456,12 @@ bool X86Assembler :: compileFOpCode(ScriptToken& tokenInfo, MemoryWriter& writer
else if (tokenInfo.compare("fsub")) {
compileFsub(tokenInfo, writer);
}
+ else if (tokenInfo.compare("fxch")) {
+ compileFxch(tokenInfo, writer);
+ }
+ else if (tokenInfo.compare("fyl2x")) {
+ compileFyl2x(tokenInfo, writer);
+ }
else return false;
return true;
@@ -2288,6 +2509,9 @@ bool X86Assembler :: compileJOpCode(ScriptToken& tokenInfo, MemoryWriter& writer
else if (tokenInfo.compare("jc")) {
compileJcc(tokenInfo, writer, X86JumpType::JB, labelScope);
}
+ else if (tokenInfo.compare("jpe")) {
+ compileJcc(tokenInfo, writer, X86JumpType::JP, labelScope);
+ }
else return false;
return true;
@@ -2409,6 +2633,9 @@ bool X86Assembler::compileSOpCode(ScriptToken& tokenInfo, MemoryWriter& writer)
else if (tokenInfo.compare("shr")) {
compileShr(tokenInfo, writer);
}
+ else if (tokenInfo.compare("sahf")) {
+ compileSahf(tokenInfo, writer);
+ }
else if (tokenInfo.compare("shl")) {
compileShl(tokenInfo, writer);
}
@@ -2439,6 +2666,11 @@ bool X86Assembler :: compileTOpCode(ScriptToken& tokenInfo, MemoryWriter& writer
return true;
}
+bool X86Assembler :: compileUOpCode(ScriptToken& tokenInfo, MemoryWriter& writer)
+{
+ return false;
+}
+
bool X86Assembler :: compileXOpCode(ScriptToken& tokenInfo, MemoryWriter& writer)
{
if (tokenInfo.compare("xor")) {
diff --git a/elenasrc3/tools/asmc/x86assembler.h b/elenasrc3/tools/asmc/x86assembler.h
index c62f0d8c8e..7763856429 100644
--- a/elenasrc3/tools/asmc/x86assembler.h
+++ b/elenasrc3/tools/asmc/x86assembler.h
@@ -3,7 +3,7 @@
//
// This header contains x86 and x86-64 Assembler declarations
//
-// (C)2021, by Aleksey Rakov
+// (C)2021-2023, by Aleksey Rakov
//---------------------------------------------------------------------------
#ifndef X86ASSEMBLER_H
@@ -70,6 +70,7 @@ namespace elena_lang
virtual bool compileDec(X86Operand source, MemoryWriter& writer);
virtual bool compileDiv(X86Operand source, MemoryWriter& writer);
virtual bool compileFadd(X86Operand source, MemoryWriter& writer);
+ virtual bool compileFadd(X86Operand source, X86Operand target, MemoryWriter& writer);
virtual bool compileFcomip(X86Operand source, X86Operand target, MemoryWriter& writer);
virtual bool compileFdiv(X86Operand source, MemoryWriter& writer);
virtual bool compileFfree(X86Operand source, MemoryWriter& writer);
@@ -83,6 +84,7 @@ namespace elena_lang
virtual bool compileFstp(X86Operand source, MemoryWriter& writer);
virtual bool compileFstsw(X86Operand source, MemoryWriter& writer);
virtual bool compileFsub(X86Operand source, MemoryWriter& writer);
+ virtual bool compileFsub(X86Operand source, X86Operand target, MemoryWriter& writer);
virtual bool compileIDiv(X86Operand source, MemoryWriter& writer);
virtual bool compileIMul(X86Operand source, MemoryWriter& writer);
virtual bool compileIMul(X86Operand source, X86Operand target, MemoryWriter& writer);
@@ -122,6 +124,7 @@ namespace elena_lang
void compileCWDE(ScriptToken& tokenInfo, MemoryWriter& writer);
void compileDec(ScriptToken& tokenInfo, MemoryWriter& writer);
void compileDiv(ScriptToken& tokenInfo, MemoryWriter& writer);
+ void compileFabs(ScriptToken& tokenInfo, MemoryWriter& writer);
void compileFadd(ScriptToken& tokenInfo, MemoryWriter& writer);
void compileFinit(ScriptToken& tokenInfo, MemoryWriter& writer);
void compileFcomip(ScriptToken& tokenInfo, MemoryWriter& writer);
@@ -134,10 +137,25 @@ namespace elena_lang
void compileFldcw(ScriptToken& tokenInfo, MemoryWriter& writer);
void compileFmul(ScriptToken& tokenInfo, MemoryWriter& writer);
void compileFrndint(ScriptToken& tokenInfo, MemoryWriter& writer);
+ void compileFprem(ScriptToken& tokenInfo, MemoryWriter& writer);
+ void compileF2xm1(ScriptToken& tokenInfo, MemoryWriter& writer);
+ void compileFld1(ScriptToken& tokenInfo, MemoryWriter& writer);
+ void compileFaddp(ScriptToken& tokenInfo, MemoryWriter& writer);
+ void compileFscale(ScriptToken& tokenInfo, MemoryWriter& writer);
+ void compileFsin(ScriptToken& tokenInfo, MemoryWriter& writer);
+ void compileFcos(ScriptToken& tokenInfo, MemoryWriter& writer);
+ void compileFpatan(ScriptToken& tokenInfo, MemoryWriter& writer);
+ void compileFldl2e(ScriptToken& tokenInfo, MemoryWriter& writer);
+ void compileFldln2(ScriptToken& tokenInfo, MemoryWriter& writer);
+ void compileFldpi(ScriptToken& tokenInfo, MemoryWriter& writer);
+ void compileFmulp(ScriptToken& tokenInfo, MemoryWriter& writer);
+ void compileFsqrt(ScriptToken& tokenInfo, MemoryWriter& writer);
void compileFstcw(ScriptToken& tokenInfo, MemoryWriter& writer);
void compileFstp(ScriptToken& tokenInfo, MemoryWriter& writer);
void compileFstsw(ScriptToken& tokenInfo, MemoryWriter& writer);
void compileFsub(ScriptToken& tokenInfo, MemoryWriter& writer);
+ void compileFxch(ScriptToken& tokenInfo, MemoryWriter& writer);
+ void compileFyl2x(ScriptToken& tokenInfo, MemoryWriter& writer);
void compileIDiv(ScriptToken& tokenInfo, MemoryWriter& writer);
void compileIMul(ScriptToken& tokenInfo, MemoryWriter& writer);
void compileJcc(ScriptToken& tokenInfo, MemoryWriter& writer, X86JumpType type, LabelScope& labelScope);
@@ -163,6 +181,7 @@ namespace elena_lang
void compileShl(ScriptToken& tokenInfo, MemoryWriter& writer);
void compileShld(ScriptToken& tokenInfo, MemoryWriter& writer);
void compileShrd(ScriptToken& tokenInfo, MemoryWriter& writer);
+ void compileSahf(ScriptToken& tokenInfo, MemoryWriter& writer);
virtual void compileStos(ScriptToken& tokenInfo, MemoryWriter& writer)
{
compileStosd(tokenInfo, writer);
@@ -193,6 +212,7 @@ namespace elena_lang
bool compileROpCode(ScriptToken& tokenInfo, MemoryWriter& writer) override;
bool compileSOpCode(ScriptToken& tokenInfo, MemoryWriter& writer) override;
bool compileTOpCode(ScriptToken& tokenInfo, MemoryWriter& writer) override;
+ bool compileUOpCode(ScriptToken& tokenInfo, MemoryWriter& writer) override;
bool compileXOpCode(ScriptToken& tokenInfo, MemoryWriter& writer) override;
void compileProcedure(ScriptToken& tokenInfo) override;
diff --git a/elenasrc3/tools/ecv/ecvconst.h b/elenasrc3/tools/ecv/ecvconst.h
index 6b1abdfb17..c12447aed7 100644
--- a/elenasrc3/tools/ecv/ecvconst.h
+++ b/elenasrc3/tools/ecv/ecvconst.h
@@ -11,7 +11,7 @@
namespace elena_lang
{
- #define ECV_REVISION_NUMBER 0x0041
+ #define ECV_REVISION_NUMBER 0x0042
constexpr auto ECV_GREETING = "ELENA command line ByteCode Viewer %d.%d.%d (C)2021-23 by Aleksey Rakov\n";
diff --git a/elenasrc3/tools/ecv/ecviewer.cpp b/elenasrc3/tools/ecv/ecviewer.cpp
index 1e3ae7da2b..c6294efb76 100644
--- a/elenasrc3/tools/ecv/ecviewer.cpp
+++ b/elenasrc3/tools/ecv/ecviewer.cpp
@@ -189,6 +189,7 @@ void ByteCodeViewer :: addRArg(arg_t arg, IdentifierString& commandStr)
switch (mask) {
case mskMssgLiteralRef:
case mskExtMssgLiteralRef:
+ case mskMssgNameLiteralRef:
referenceName = arg ? _module->resolveConstant(arg & ~mskAnyRef) : nullptr;
break;
default:
@@ -243,6 +244,9 @@ void ByteCodeViewer :: addRArg(arg_t arg, IdentifierString& commandStr)
case mskExtMssgLiteralRef:
commandStr.append("mssgconst:");
break;
+ case mskMssgNameLiteralRef:
+ commandStr.append("mssgnameconst:");
+ break;
default:
commandStr.append(":");
break;
@@ -373,6 +377,8 @@ void ByteCodeViewer :: addCommandArguments(ByteCommand& command, IdentifierStrin
case ByteCode::Jne:
case ByteCode::Jlt:
case ByteCode::Jge:
+ case ByteCode::Jgr:
+ case ByteCode::Jle:
addLabel(command.arg1 + commandPosition + 5, commandStr, labels);
break;
case ByteCode::AssignI:
@@ -416,6 +422,7 @@ void ByteCodeViewer :: addCommandArguments(ByteCommand& command, IdentifierStrin
break;
case ByteCode::SelEqRR:
case ByteCode::SelLtRR:
+ case ByteCode::SelULtRR:
addRArg(command.arg1, commandStr);
addSecondRArg(command.arg2, commandStr, labels);
break;
@@ -540,6 +547,14 @@ void ByteCodeViewer :: printMethodInfo(MethodInfo& info)
{
IdentifierString flags(" @hints:");
flags.appendHex(info.hints);
+ if (test(info.hints, (ref_t)MethodHint::Abstract))
+ flags.append(" @Abstract");
+ if (test(info.hints, (ref_t)MethodHint::Constant))
+ flags.append(" @Constant");
+ if (test(info.hints, (ref_t)MethodHint::Conversion))
+ flags.append(" @Conversion");
+ if (test(info.hints, (ref_t)MethodHint::Extension))
+ flags.append(" @Extension");
printLine(*flags);
}
@@ -788,7 +803,11 @@ void ByteCodeViewer::printMethod(ustr_t name, bool fullInfo)
if (_showMethodInfo)
printMethodInfo(methodInfo);
- printByteCodes(code, entry.codeOffset, 4, _pageSize);
+ if (test(methodInfo.hints, (ref_t)MethodHint::Abstract)) {
+ printLine(" ");
+ }
+ else printByteCodes(code, entry.codeOffset, 4, _pageSize);
+
printLine("@end");
break;
diff --git a/elenasrc3/tools/ldoc/ldoc.cpp b/elenasrc3/tools/ldoc/ldoc.cpp
index 88327422e9..efa4b8bf5b 100644
--- a/elenasrc3/tools/ldoc/ldoc.cpp
+++ b/elenasrc3/tools/ldoc/ldoc.cpp
@@ -1393,6 +1393,9 @@ void DocGenerator :: loadMember(ApiModuleInfoList& modules, ref_t reference)
ReferenceProperName properName(referenceName);
ReferenceName fullName(*_rootNs, referenceName + 1);
+ if (referenceName.findStr("Tuple") != NOTFOUND_POS)
+ classClassRef = classClassRef + 0;;
+
// HOTFIX : skip internal class
if (properName[0] == '$')
return;
diff --git a/examples60/console/replace/replace.l b/examples60/console/replace/replace.l
new file mode 100644
index 0000000000..0ffa06bea3
--- /dev/null
+++ b/examples60/console/replace/replace.l
@@ -0,0 +1,22 @@
+import extensions;
+import extensions'text;
+
+// --- Program ---
+
+public program()
+{
+ var text := console.print:"Enter the text:".loadLineTo(new StringWriter());
+ var searchText := console.print:"Enter the phrase to be found:".readLine();
+ var replaceText := console.print:"Enter the phrase to replace with:".readLine();
+
+ var bm := new StringBookmark(text);
+
+ while (bm.find(searchText))
+ {
+ bm.delete(searchText).insert(replaceText)
+ };
+
+ console
+ .printLine("The resulting text:",bm)
+ .readChar() // wait for any key
+}
diff --git a/examples60/rosetta/amb/amb.l b/examples60/rosetta/amb/amb.l
new file mode 100644
index 0000000000..b5f5c5e102
--- /dev/null
+++ b/examples60/rosetta/amb/amb.l
@@ -0,0 +1,108 @@
+import system'routines;
+import extensions;
+import extensions'routines;
+
+// --- Joinable --
+
+joinable(former,later) = (former[former.Length - 1] == later[0]);
+
+dispatcher = new
+{
+ eval(object a, Func2 f)
+ {
+ ^ f(a[0],a[1])
+ }
+
+ eval(object a, Func3 f)
+ {
+ ^ f(a[0], a[1],a[2])
+ }
+
+ eval(object a, Func4 f)
+ {
+ ^ f(a[0],a[1],a[2],a[3])
+ }
+
+ eval(object a, Func5 f)
+ {
+ ^ f(a[0],a[1],a[2],a[3],a[4])
+ }
+};
+
+// --- AmbValueCollection ---
+
+class AmbValueCollection
+{
+ object _combinator;
+
+ constructor new(params object[] args)
+ {
+ _combinator := SequentialEnumerator.new(params args)
+ }
+
+ seek(cond)
+ {
+ _combinator.reset();
+
+ _combinator.seekEach:(v => dispatcher.eval(v,cond))
+ }
+
+ do(f)
+ {
+ var result := *_combinator;
+ if (nil != result)
+ {
+ dispatcher.eval(result,f)
+ }
+ else
+ {
+ InvalidArgumentException.raise()
+ }
+ }
+}
+
+// --- ambOperator ---
+
+singleton ambOperator
+{
+ for(params object[] args)
+ = AmbValueCollection.new(params args);
+}
+
+// --- Program ---
+
+public program1()
+{
+ try
+ {
+ ambOperator.for(new object[]{1,2,4}, new object[]{4,5,6}).seek:(a,b => a * b == 8).do:
+ (a,b){ console.printLine(a," * ",b," = 8") };
+ }
+ catch(Exception e)
+ {
+ console.printLine:"AMB is angry"
+ };
+
+ console.readChar()
+}
+
+public program()
+{
+ try
+ {
+ ambOperator
+ .for(
+ new object[]{"the","that","a"},
+ new object[]{"frog", "elephant", "thing"},
+ new object[]{"walked", "treaded", "grows"},
+ new object[]{"slowly", "quickly"})
+ .seek:(a,b,c,d => joinable(a,b) && joinable(b,c) && joinable(c,d) )
+ .do:(a,b,c,d) { console.printLine(a," ",b," ",c," ",d) }
+ }
+ catch(Exception e)
+ {
+ console.printLine:"AMB is angry"
+ };
+
+ console.readChar()
+}
diff --git a/examples60/rosetta/combinations/combinations.l b/examples60/rosetta/combinations/combinations.l
new file mode 100644
index 0000000000..e4193c291f
--- /dev/null
+++ b/examples60/rosetta/combinations/combinations.l
@@ -0,0 +1,26 @@
+import system'routines;
+import extensions;
+import extensions'routines;
+
+const int M = 3;
+const int N = 5;
+
+// --- Numbers ---
+
+Numbers(n)
+{
+ ^ Array.allocate(n).populate:(int n => n)
+}
+
+// --- Program ---
+
+public program()
+{
+ var numbers := Numbers(N);
+ Combinator.new(M, numbers).forEach:(row)
+ {
+ console.printLine(row.toString())
+ };
+
+ console.readChar()
+}
\ No newline at end of file
diff --git a/examples60/rosetta/doors/doors.l b/examples60/rosetta/doors/doors.l
new file mode 100644
index 0000000000..009df35440
--- /dev/null
+++ b/examples60/rosetta/doors/doors.l
@@ -0,0 +1,21 @@
+import system'routines;
+import extensions;
+
+public program()
+{
+ var Doors := Array.allocate(100).populate:(n=>false);
+ for(int i := 0, i < 100, i := i + 1)
+ {
+ for(int j := i, j < 100, j := j + i + 1)
+ {
+ Doors[j] := Doors[j].Inverted
+ }
+ };
+
+ for(int i := 0, i < 100, i := i + 1)
+ {
+ console.printLine("Door #",i + 1," :",Doors[i].iif("Open","Closed"))
+ };
+
+ console.readChar()
+}
diff --git a/examples60/rosetta/evolutionary/evolutionary.l b/examples60/rosetta/evolutionary/evolutionary.l
new file mode 100644
index 0000000000..856138fe71
--- /dev/null
+++ b/examples60/rosetta/evolutionary/evolutionary.l
@@ -0,0 +1,76 @@
+import system'routines;
+import extensions;
+import extensions'text;
+
+const string Target = "METHINKS IT IS LIKE A WEASEL";
+const string AllowedCharacters = " ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
+const int C = 100;
+const real P = 0.05r;
+
+rnd = randomGenerator;
+
+randomChar
+ = AllowedCharacters[rnd.nextInt(AllowedCharacters.Length)];
+
+extension evoHelper
+{
+ randomString()
+ = 0.repeatTill(self).selectBy:(x => randomChar).summarize(new StringWriter());
+
+ fitnessOf(s)
+ = self.zipBy(s, (a,b => a==b ? 1 : 0)).summarize(new Integer()).toInt();
+
+ mutate(p)
+ = self.selectBy:(ch => rnd.nextReal() <= p ? randomChar : ch).summarize(new StringWriter());
+}
+
+class EvoAlgorithm : Enumerator
+{
+ object _target;
+ object _current;
+ object _variantCount;
+
+ constructor new(s,count)
+ {
+ _target := s;
+ _variantCount := count.toInt();
+ }
+
+ get Value() = _current;
+
+ bool next()
+ {
+ if (nil == _current)
+ { _current := _target.Length.randomString(); ^ true };
+
+ if (_target == _current)
+ { ^ false };
+
+ auto variants := Array.allocate(_variantCount).populate:(x => _current.mutate:P );
+
+ _current := variants.sort:(a,b => a.fitnessOf:Target > b.fitnessOf:Target ).at:0;
+
+ ^ true
+ }
+
+ reset()
+ {
+ _current := nil
+ }
+
+ enumerable() => _target;
+}
+
+public program()
+{
+ var attempt := new Integer();
+ EvoAlgorithm.new(Target,C).forEach:(current)
+ {
+ console
+ .printPaddingLeft(10,"#",attempt.append(1))
+ .printLine(" ",current," fitness: ",current.fitnessOf(Target))
+ };
+
+ console.readChar()
+}
\ No newline at end of file
diff --git a/examples60/rosetta/firstclass/firstclass.l b/examples60/rosetta/firstclass/firstclass.l
new file mode 100644
index 0000000000..9a518a1aa6
--- /dev/null
+++ b/examples60/rosetta/firstclass/firstclass.l
@@ -0,0 +1,25 @@
+// Write a program to create an ordered collection A of functions of a real number. At least one function should be built-in and
+// at least one should be user-defined; try using the sine, cosine, and cubing functions.
+// Fill another collection B with the inverse of each function in A.
+// Implement function composition as in Functional Composition. Finally, demonstrate that the result of applying the composition
+// of each function in A and its inverse in B to a value, is the original value
+
+import system'routines;
+import system'math;
+import extensions'routines;
+import extensions'math;
+
+extension op
+{
+ compose(f,g)
+ = f(g(self));
+}
+
+public program()
+{
+ var fs := new object[]{ mssgconst sin[1], mssgconst cos[1], (x => power(x, 3.0r)) };
+ var gs := new object[]{ mssgconst arcsin[1], mssgconst arccos[1], (x => power(x, 1.0r / 3)) };
+
+ fs.zipBy(gs, (f,g => 0.5r.compose(f,g)))
+ .forEach:printingLn
+}
\ No newline at end of file
diff --git a/examples60/rosetta/loop_multiple_arrays/loopma.l b/examples60/rosetta/loop_multiple_arrays/loopma.l
new file mode 100644
index 0000000000..8b917c0600
--- /dev/null
+++ b/examples60/rosetta/loop_multiple_arrays/loopma.l
@@ -0,0 +1,35 @@
+// Loop over multiple arrays (or lists or tuples or whatever they're called in your language) and display the th element of each.
+
+import system'routines;
+import extensions;
+
+public program()
+{
+ var a1 := new string[]{"a","b","c"};
+ var a2 := new string[]{"A","B","C"};
+ var a3 := new int[]{1,2,3};
+
+ for(int i := 0, i < a1.Length, i += 1)
+ {
+ console.printLine(a1[i], a2[i], a3[i])
+ };
+
+ console.readChar()
+}
+
+// To build the program to use 'programUsingZip' symbol, just change
+// the forward to use programUsingZip as entry point
+// --
+// program=loopma'programUsingZip
+// --
+public programUsingZip()
+{
+ var a1 := new string[]{"a","b","c"};
+ var a2 := new string[]{"A","B","C"};
+ var a3 := new int[]{1,2,3};
+ var zipped := a1.zipBy(a2,(first,second => first + second.toString() ))
+ .zipBy(a3, (first,second => first + second.toString() ));
+
+ zipped.forEach:(e)
+ { console.writeLine:e };
+}
\ No newline at end of file
diff --git a/examples60/rosetta/median/median.l b/examples60/rosetta/median/median.l
new file mode 100644
index 0000000000..ec893fcd2d
--- /dev/null
+++ b/examples60/rosetta/median/median.l
@@ -0,0 +1,40 @@
+import system'routines;
+import system'math;
+import extensions;
+
+extension op
+{
+ get Median()
+ {
+ var sorted := self.ascendant();
+
+ var len := sorted.Length;
+ if (len == 0)
+ {
+ ^ nil
+ }
+ else
+ {
+ var middleIndex := len / 2;
+ if (len.mod:2 == 0)
+ {
+ ^ (sorted[middleIndex - 1] + sorted[middleIndex]) / 2
+ }
+ else
+ {
+ ^ sorted[middleIndex]
+ }
+ }
+ }
+}
+
+public program()
+{
+ var a1 := new real[]{4.1r, 5.6r, 7.2r, 1.7r, 9.3r, 4.4r, 3.2r};
+ var a2 := new real[]{4.1r, 7.2r, 1.7r, 9.3r, 4.4r, 3.2r};
+
+ console.printLine("median of (",a1.asEnumerable(),") is ",a1.Median);
+ console.printLine("median of (",a2.asEnumerable(),") is ",a2.Median);
+
+ console.readChar()
+}
\ No newline at end of file
diff --git a/examples60/rosetta/ninetynine/ninetynine.l b/examples60/rosetta/ninetynine/ninetynine.l
new file mode 100644
index 0000000000..a50dd5188d
--- /dev/null
+++ b/examples60/rosetta/ninetynine/ninetynine.l
@@ -0,0 +1,35 @@
+import system'routines;
+import extensions;
+import extensions'routines;
+import extensions'text;
+
+extension bottleOp
+{
+ bottleDescription()
+ = self.toPrintable() + (self != 1).iif(" bottles"," bottle");
+
+ bottleEnumerator() = new Variable(self).doWith:(n)
+ {
+ ^ new Enumerator
+ {
+ bool next() = n > 0;
+
+ get Value() = new StringWriter()
+ .printLine(n.bottleDescription()," of beer on the wall")
+ .printLine(n.bottleDescription()," of beer")
+ .printLine("Take one down, pass it around")
+ .printLine((n.reduce:1).bottleDescription()," of beer on the wall");
+
+ reset() {}
+
+ enumerable() = weak self;
+ }
+ };
+}
+
+public program()
+{
+ var bottles := 99;
+
+ bottles.bottleEnumerator().forEach:printingLn
+}
\ No newline at end of file
diff --git a/examples60/rosetta/reverse_words_in_string/reverse_words.l b/examples60/rosetta/reverse_words_in_string/reverse_words.l
new file mode 100644
index 0000000000..4b0384636e
--- /dev/null
+++ b/examples60/rosetta/reverse_words_in_string/reverse_words.l
@@ -0,0 +1,25 @@
+import extensions;
+import system'routines;
+
+public program()
+{
+ var text := new string[]{"---------- Ice and Fire ------------",
+ "",
+ "fire, in end will world the say Some",
+ "ice. in say Some",
+ "desire of tasted I've what From",
+ "fire. favor who those with hold I",
+ "",
+ "... elided paragraph last ...",
+ "",
+ "Frost Robert -----------------------"};
+
+ text.forEach:(line)
+ {
+ line.splitBy:" ".sequenceReverse().forEach:(word)
+ {
+ console.print(word," ")
+ };
+ console.writeLine()
+ }
+}
\ No newline at end of file
diff --git a/examples60/rosetta/smavg/smavg.l b/examples60/rosetta/smavg/smavg.l
new file mode 100644
index 0000000000..b4d230449a
--- /dev/null
+++ b/examples60/rosetta/smavg/smavg.l
@@ -0,0 +1,56 @@
+import system'routines;
+import system'collections;
+import extensions;
+
+class SMA
+{
+ object thePeriod;
+ object theList;
+
+ constructor new(period)
+ {
+ thePeriod := period;
+ theList :=new List();
+ }
+
+ append(n)
+ {
+ theList.append(n);
+
+ var count := theList.Length;
+ count =>
+ 0 { ^0.0r }
+ : {
+ if (count > thePeriod)
+ {
+ theList.removeAt:0;
+
+ count := thePeriod
+ };
+
+ var sum := theList.summarize(Real.new());
+
+ ^ sum / count
+ }
+ }
+}
+
+// --- Program ---
+
+public program()
+{
+ var SMA3 := SMA.new:3;
+ var SMA5 := SMA.new:5;
+
+ for (int i := 1, i <= 5, i += 1) {
+ console.printPaddingRight(30, "sma3 + ", i, " = ", SMA3.append:i);
+ console.printLine("sma5 + ", i, " = ", SMA5.append:i)
+ };
+
+ for (int i := 5, i >= 1, i -= 1) {
+ console.printPaddingRight(30, "sma3 + ", i, " = ", SMA3.append:i);
+ console.printLine("sma5 + ", i, " = ", SMA5.append:i)
+ };
+
+ console.readChar()
+}
diff --git a/examples60/rosetta/string_append/string_append.l b/examples60/rosetta/string_append/string_append.l
new file mode 100644
index 0000000000..cc38600b55
--- /dev/null
+++ b/examples60/rosetta/string_append/string_append.l
@@ -0,0 +1,9 @@
+import extensions'text;
+
+public program()
+{
+ var s := StringWriter.load("Hello");
+ s.append:" World";
+
+ console.writeLine:s.readChar()
+}
\ No newline at end of file
diff --git a/install/aarch64/build_package_arm64.script b/install/aarch64/build_package_arm64.script
index 7fdf511bb6..bbb16939fb 100755
--- a/install/aarch64/build_package_arm64.script
+++ b/install/aarch64/build_package_arm64.script
@@ -96,7 +96,7 @@ fi
../../bin/elena64-cli ../../src60/system/system.project
ret=$?
- if [ $ret -eq -2 ]
+ if [ $ret -eq 2 ]
then
echo "Failure" >&2
exit 1
@@ -106,7 +106,7 @@ fi
../../bin/elena64-cli ../../src60/extensions/extensions.project
ret=$?
- if [ $ret -eq -2 ]
+ if [ $ret -eq 2 ]
then
echo "Failure" >&2
exit 1
@@ -116,7 +116,7 @@ fi
../../bin/elena64-cli ../../tests60/system_tests/system_tests.project
ret=$?
- if [ $ret -eq -2 ]
+ if [ $ret -eq 2 ]
then
echo "Failure" >&2
exit 1
@@ -126,7 +126,7 @@ fi
../../tests60/system_tests/system_tests
ret=$?
- if [ $ret -eq -2 ]
+ if [ $ret -eq 2 ]
then
echo "Failure" >&2
exit 1
diff --git a/install/amd64/build_package_amd64.script b/install/amd64/build_package_amd64.script
index cb4008181b..10c1c5a666 100755
--- a/install/amd64/build_package_amd64.script
+++ b/install/amd64/build_package_amd64.script
@@ -97,7 +97,7 @@ fi
../../bin/elena64-cli ../../src60/system/system.project
ret=$?
- if [ $ret -eq -2 ]
+ if [ $ret -eq 2 ]
then
echo "Failure" >&2
exit 1
@@ -107,7 +107,7 @@ fi
../../bin/elena64-cli ../../src60/extensions/extensions.project
ret=$?
- if [ $ret -eq -2 ]
+ if [ $ret -eq 2 ]
then
echo "Failure" >&2
exit 1
@@ -117,7 +117,7 @@ fi
../../bin/elena64-cli ../../tests60/system_tests/system_tests.project
ret=$?
- if [ $ret -eq -2 ]
+ if [ $ret -eq 2 ]
then
echo "Failure" >&2
exit 1
@@ -127,7 +127,7 @@ fi
../../tests60/system_tests/system_tests
ret=$?
- if [ $ret -eq -2 ]
+ if [ $ret -eq 2 ]
then
echo "Failure" >&2
exit 1
diff --git a/install/i386/build_package_i386.script b/install/i386/build_package_i386.script
index b65c14b964..7d9251b6f5 100755
--- a/install/i386/build_package_i386.script
+++ b/install/i386/build_package_i386.script
@@ -98,7 +98,7 @@ echo compiling lib60 files
../../bin/elena-cli ../../src60/system/system.project
ret=$?
- if [ $ret -eq -2 ]
+ if [ $ret -eq 2 ]
then
echo "Failure" >&2
exit 1
@@ -108,7 +108,7 @@ echo compiling lib60 files
../../bin/elena-cli ../../src60/extensions/extensions.project
ret=$?
- if [ $ret -eq -2 ]
+ if [ $ret -eq 2 ]
then
echo "Failure" >&2
exit 1
@@ -118,7 +118,7 @@ echo compiling lib60 files
../../bin/elena-cli ../../tests60/system_tests/system_tests.project
ret=$?
- if [ $ret -eq -2 ]
+ if [ $ret -eq 2 ]
then
echo "Failure" >&2
exit 1
@@ -128,7 +128,7 @@ echo compiling lib60 files
../../tests60/system_tests/system_tests
ret=$?
- if [ $ret -eq -2 ]
+ if [ $ret -eq 2 ]
then
echo "Failure" >&2
exit 1
diff --git a/install/ppc64le/build_package_ppc64le.script b/install/ppc64le/build_package_ppc64le.script
index cc95189ae6..4061f21e8a 100755
--- a/install/ppc64le/build_package_ppc64le.script
+++ b/install/ppc64le/build_package_ppc64le.script
@@ -96,7 +96,7 @@ fi
../../bin/elena64-cli ../../src60/system/system.project
ret=$?
- if [ $ret -eq -2 ]
+ if [ $ret -eq 2 ]
then
echo "Failure" >&2
exit 1
@@ -106,7 +106,7 @@ fi
../../bin/elena64-cli ../../src60/extensions/extensions.project
ret=$?
- if [ $ret -eq -2 ]
+ if [ $ret -eq 2 ]
then
echo "Failure" >&2
exit 1
@@ -116,7 +116,7 @@ fi
../../bin/elena64-cli ../../tests60/system_tests/system_tests.project
ret=$?
- if [ $ret -eq -2 ]
+ if [ $ret -eq 2 ]
then
echo "Failure" >&2
exit 1
@@ -126,7 +126,7 @@ fi
../../tests60/system_tests/system_tests
ret=$?
- if [ $ret -eq -2 ]
+ if [ $ret -eq 2 ]
then
echo "Failure" >&2
exit 1
diff --git a/rebuild_lib.bat b/rebuild_lib.bat
deleted file mode 100644
index 42119e42ce..0000000000
--- a/rebuild_lib.bat
+++ /dev/null
@@ -1,156 +0,0 @@
-bin\sg dat\sg\syntax.txt
-move dat\sg\syntax.dat bin
-
-bin\og dat\og\rules.txt
-move dat\og\rules.dat bin
-
-bin\og s dat\og\source_rules.txt
-@echo off
-if %ERRORLEVEL% EQU -1 GOTO Asm2BinError
-@echo on
-move dat\og\source_rules.dat bin
-
-bin\asm2binx src50\core\system.core_routines.esm lib50
-@echo off
-if %ERRORLEVEL% EQU -1 GOTO Asm2BinError
-@echo on
-
-bin\asm2binx -p64 src50\core\system.core_routines.esm lib50_64
-@echo off
-if %ERRORLEVEL% EQU -1 GOTO Asm2BinError
-@echo on
-
-bin\asm2binx asm\x32\core.asm bin\x32
-@echo off
-if %ERRORLEVEL% EQU -1 GOTO Asm2BinError
-@echo on
-
-bin\asm2binx asm\x32\corex.asm bin\x32
-@echo off
-if %ERRORLEVEL% EQU -1 GOTO Asm2BinError
-@echo on
-
-bin\asm2binx asm\x32\coreapi.asm bin\x32
-@echo off
-if %ERRORLEVEL% EQU -1 GOTO Asm2BinError
-@echo on
-
-bin\asm2binx asm\x32\core_win.asm bin\x32
-@echo off
-if %ERRORLEVEL% EQU -1 GOTO Asm2BinError
-@echo on
-
-bin\asm2binx -amd64 asm\amd64\core.asm bin\amd64
-@echo off
-if %ERRORLEVEL% EQU -1 GOTO Asm2BinError
-@echo on
-
-bin\asm2binx -amd64 asm\amd64\core_win.asm bin\amd64
-@echo off
-if %ERRORLEVEL% EQU -1 GOTO Asm2BinError
-@echo on
-
-bin\asm2binx -amd64 asm\amd64\coreapi.asm bin\amd64
-@echo off
-if %ERRORLEVEL% EQU -1 GOTO Asm2BinError
-@echo on
-
-rem bin\asm2binx -ppc64le asm\ppc64le\core.asm bin\ppc64le
-
-bin\elc src50\system\system.prj
-@echo off
-if %ERRORLEVEL% EQU -2 GOTO CompilerError
-@echo on
-
-bin\elc src50\extensions\extensions.prj
-@echo off
-if %ERRORLEVEL% EQU -2 GOTO CompilerError
-@echo on
-
-rem bin\elc src50\net\net.prj
-@echo off
-if %ERRORLEVEL% EQU -2 GOTO CompilerError
-@echo on
-
-rem bin\elc src50\forms\forms.prj
-@echo off
-if %ERRORLEVEL% EQU -2 GOTO CompilerError
-@echo on
-
-rem bin\elc src50\xforms\xforms.prj
-@echo off
-if %ERRORLEVEL% EQU -2 GOTO CompilerError
-@echo on
-
-bin\elc src50\sqlite\sqlite.prj
-@echo off
-if %ERRORLEVEL% EQU -2 GOTO CompilerError
-@echo on
-
-rem bin\elc src50\cellular\cellular.prj
-@echo off
-if %ERRORLEVEL% EQU -2 GOTO CompilerError
-@echo on
-
-rem bin\elc src50\algorithms\algorithms.prj
-@echo off
-if %ERRORLEVEL% EQU -2 GOTO CompilerError
-@echo on
-
-rem bin\elc src50\graphics\graphics.prj
-
-bin\elc src50\system\system_64.prj
-@echo off
-if %ERRORLEVEL% EQU -2 GOTO CompilerError
-@echo on
-
-bin\elc src50\extensions\extensions_64.prj
-@echo off
-if %ERRORLEVEL% EQU -2 GOTO CompilerError
-@echo on
-
-bin\elc tests\system\system_test.prj
-@echo off
-if %ERRORLEVEL% EQU -2 GOTO CompilerError
-@echo on
-
-tests\system\system_test.exe
-@echo off
-if %ERRORLEVEL% EQU -1 GOTO TestError
-@echo on
-
-bin\elc tests\system\system_test64.prj
-@echo off
-if %ERRORLEVEL% EQU -2 GOTO CompilerError
-@echo on
-
-tests\system\system_test64.exe
-@echo off
-if %ERRORLEVEL% EQU -1 GOTO TestError
-@echo on
-
-@echo off
-echo === Done ===
-@echo on
-
-@echo off
-goto:eof
-@echo on
-
-:Asm2BinError
-echo ASM2BINX returns error %ERRORLEVEL%
-@echo off
-goto:eof
-@echo on
-
-:CompilerError
-echo ELC returns error %ERRORLEVEL%
-@echo off
-goto:eof
-@echo on
-
-:TestError
-echo System tests fail %ERRORLEVEL%
-@echo off
-goto:eof
-@echo on
diff --git a/rebuild_lib60.bat b/rebuild_lib60.bat
index f4fbe9b172..520df1f063 100644
--- a/rebuild_lib60.bat
+++ b/rebuild_lib60.bat
@@ -86,13 +86,13 @@ if %ERRORLEVEL% EQU -2 GOTO CompilerError
echo system api test for x86
tests60\system_tests\system_tests.exe
@echo off
-if %ERRORLEVEL% EQU -1 GOTO TestError
+if %ERRORLEVEL% NEQ 0 GOTO TestError
@echo on
echo system api test for amd64
tests60\system_tests\system_tests64.exe
@echo off
-if %ERRORLEVEL% EQU -1 GOTO TestError
+if %ERRORLEVEL% NEQ 0 GOTO TestError
@echo on
@echo off
diff --git a/recompile19.bat b/recompile19.bat
deleted file mode 100644
index 2118b1b7aa..0000000000
--- a/recompile19.bat
+++ /dev/null
@@ -1,40 +0,0 @@
-@echo off
-
-set pre=Microsoft.VisualStudio.Product.
-set ids=%pre%Community %pre%Professional %pre%Enterprise %pre%BuildTools
-for /f "usebackq tokens=1* delims=: " %%i in (`"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere" -latest -products %ids% -requires Microsoft.Component.MSBuild`) do (
- if /i "%%i"=="installationPath" set InstallDir=%%j
-)
-
-IF NOT EXIST %InstallDir%nul goto MissingMSBuildToolsPath
-IF NOT EXIST %InstallDir%\MSBuild\Current\Bin\MSBuild.exe goto MissingMSBuildExe
-
-ECHO =========== Starting Release Compile ==================
-
-ECHO Command line Compiler compiling....
-ECHO -----------------------------------
-REM /m:2 is used to build using parallel compilation
-"%InstallDir%\MSBuild\Current\Bin\MSBuild.exe" elenasrc2\elenasrc2.sln /p:configuration=release /m:2
-IF NOT %ERRORLEVEL%==0 GOTO CompilerError
-
-REM /m:2 is used to build using parallel compilation
-"%InstallDir%\MSBuild\Current\Bin\MSBuild.exe" elenasrc2\elenasrc2_64.sln /p:configuration=release /m:2
-IF NOT %ERRORLEVEL%==0 GOTO CompilerError
-
-ECHO =========== Release Compiled ==================
-
-goto:eof
-::ERRORS
-::---------------------
-:MissingMSBuildRegistry
-echo Cannot obtain path to MSBuild tools from registry
-goto:eof
-:MissingMSBuildToolsPath
-echo The MSBuild tools path from the registry '%InstallDir%' does not exist
-goto:eof
-:MissingMSBuildExe
-echo The MSBuild executable could not be found at '%InstallDir%'
-goto:eof
-:CompilerError
-echo The MSBuild returns error %ERRORLEVEL%
-goto:eof
diff --git a/src50/core/system.core_routines.esm b/src50/core/system.core_routines.esm
index 3da6964e53..e7f2d5b679 100644
--- a/src50/core/system.core_routines.esm
+++ b/src50/core/system.core_routines.esm
@@ -3847,7 +3847,7 @@ procedure __loadString."#dispatch[1]" // -4 - size, -2 - index, -12 - buffer
movr const : system'text'UTF8Encoding
pusha
movm mssgconst : "toString[4]"
- callrm system'text'UTF8Encoding, mssgconst : "toString[4]"
+ callrm system'text'UTF8Encoding, mssgconst : "toString<$system'IntNumber$system'IntNumber$system'system@Array#1&system@ByteNumber>[4]"
freei 4
quit
diff --git a/src60/core/system.core_routines.esm b/src60/core/system.core_routines.esm
index ba3230911d..164dbd63de 100644
--- a/src60/core/system.core_routines.esm
+++ b/src60/core/system.core_routines.esm
@@ -58,6 +58,15 @@ procedure __object_class
end
+procedure __object_instanceOf
+
+ peek sp:0
+ class
+ cmp sp:1
+ seleq class:"system'BoolValue#true", class:"system'BoolValue#false"
+
+end
+
procedure __exception_handler
xflush sp:0
@@ -260,16 +269,16 @@ procedure __str_less (s1, s2)
peek fp:s1
nlen 1
+ sub n:1
save dp:s_len
peek fp:s2
nlen 1
+ sub n:1
set dp:s_len
xcmp
jne labNotLess
- sub n:1
-
nsave dp:index, 0
peek fp:s1
@@ -293,15 +302,20 @@ labCheck:
set dp:ch2
read 1
+ xswap sp:1
load
- xcmp dp:ch
- jge labNotLess
+ xcmp dp:ch
+ jlt labNotLess
nadd dp:index, 1
- xswap sp:1
jump labCheck
labLoopEnd:
+ set dp:ch2
+ load
+ xcmp dp:ch
+ jeq labNotLess
+
set class:"system'BoolValue#true"
jump labEnd
@@ -500,16 +514,16 @@ procedure __wstr_less (s1, s2)
peek fp:s1
nlen 2
+ sub n:1
save dp:s_len
peek fp:s2
nlen 2
+ sub n:1
set dp:s_len
xcmp
jne labNotLess
- sub n:1
-
nsave dp:index, 0
peek fp:s1
@@ -533,15 +547,20 @@ labCheck:
set dp:ch2
read 2
+ xswap sp:1
load
- xcmp dp:ch
- jge labNotLess
+ xcmp dp:ch
+ jlt labNotLess
nadd dp:index, 1
- xswap sp:1
jump labCheck
labLoopEnd:
+ set dp:ch2
+ load
+ xcmp dp:ch
+ jeq labNotLess
+
set class:"system'BoolValue#true"
jump labEnd
@@ -553,7 +572,6 @@ labEnd:
end
-
procedure __wstr_copysubs (self, s1, s2, index, len)
xflush sp:0
@@ -689,6 +707,24 @@ procedure __shortToByte
end
+procedure __intToUInt
+
+ peek sp:1
+ load
+ peek sp:2
+ save
+
+end
+
+procedure __uintToInt
+
+ peek sp:1
+ load
+ peek sp:2
+ save
+
+end
+
procedure __realTrunc (self, r1, r2)
xflush sp:0
@@ -710,6 +746,192 @@ procedure __realTrunc (self, r1, r2)
end
+procedure __realRound (self, r1, r2)
+
+ xflush sp:0
+ xflush sp:1
+
+ open (2),[],[tmp:__realSize]
+
+ peek fp:r1
+ store sp:0
+
+ fround dp:tmp
+
+ set dp:tmp
+ store sp:0
+ peek fp:r2
+ copy __realSize
+
+ close []
+
+end
+
+procedure __realAbs (self, r1, r2)
+
+ xflush sp:0
+ xflush sp:1
+
+ open (2),[],[tmp:__realSize]
+
+ peek fp:r1
+ store sp:0
+
+ fabs dp:tmp
+
+ set dp:tmp
+ store sp:0
+ peek fp:r2
+ copy __realSize
+
+ close []
+
+end
+
+procedure __realSqrt (self, r1, r2)
+
+ xflush sp:0
+ xflush sp:1
+
+ open (2),[],[tmp:__realSize]
+
+ peek fp:r1
+ store sp:0
+
+ fsqrt dp:tmp
+
+ set dp:tmp
+ store sp:0
+ peek fp:r2
+ copy __realSize
+
+ close []
+
+end
+
+procedure __realExp (self, r1, r2)
+
+ xflush sp:0
+ xflush sp:1
+
+ open (2),[],[tmp:__realSize]
+
+ peek fp:r1
+ store sp:0
+
+ fexp dp:tmp
+
+ set dp:tmp
+ store sp:0
+ peek fp:r2
+ copy __realSize
+
+ close []
+
+end
+
+procedure __realLn (self, r1, r2)
+
+ xflush sp:0
+ xflush sp:1
+
+ open (2),[],[tmp:__realSize]
+
+ peek fp:r1
+ store sp:0
+
+ fln dp:tmp
+
+ set dp:tmp
+ store sp:0
+ peek fp:r2
+ copy __realSize
+
+ close []
+
+end
+
+procedure __realSin (self, r1, r2)
+
+ xflush sp:0
+ xflush sp:1
+
+ open (2),[],[tmp:__realSize]
+
+ peek fp:r1
+ store sp:0
+
+ fsin dp:tmp
+
+ set dp:tmp
+ store sp:0
+ peek fp:r2
+ copy __realSize
+
+ close []
+
+end
+
+procedure __realCos (self, r1, r2)
+
+ xflush sp:0
+ xflush sp:1
+
+ open (2),[],[tmp:__realSize]
+
+ peek fp:r1
+ store sp:0
+
+ fcos dp:tmp
+
+ set dp:tmp
+ store sp:0
+ peek fp:r2
+ copy __realSize
+
+ close []
+
+end
+
+procedure __realArctan (self, r1, r2)
+
+ xflush sp:0
+ xflush sp:1
+
+ open (2),[],[tmp:__realSize]
+
+ peek fp:r1
+ store sp:0
+
+ farctan dp:tmp
+
+ set dp:tmp
+ store sp:0
+ peek fp:r2
+ copy __realSize
+
+ close []
+
+end
+
+procedure __realPi (self, r1)
+
+ xflush sp:0
+ xflush sp:1
+
+ open (2),[],[tmp:__realSize]
+
+ fpi dp:tmp
+
+ set dp:tmp
+ store sp:0
+ peek fp:r1
+ copy __realSize
+
+ close []
+
+end
+
procedure __longToByte
peek sp:1
@@ -824,6 +1046,35 @@ procedure __byteToShort
end
+procedure __readIntPtr
+
+ peek sp:1
+ get i:0
+ load
+ peek sp:2
+ save
+
+end
+
+procedure __ptrCopyTo (self, arr, len)
+
+ xflush sp:0
+ xflush sp:1
+
+ open (2),[]
+
+ peek fp:self
+ get i:0
+ store sp:0
+ peek fp:len
+ load
+ peek fp:arr
+ dcopy 1
+
+ close []
+
+end
+
procedure __copySubStr (dest, index, len, sour)
xflush sp:0
@@ -1017,6 +1268,7 @@ procedure __classref_dispatcher
redirect
get i:0
+ store sp:0
jump vt:0
end
@@ -1061,9 +1313,6 @@ procedure __mssgname_dispatcher
jeq labDefault
loadv
- xcmp
- jne labDefault
-
peek sp:0
jump vt:0
@@ -1230,6 +1479,150 @@ procedure __thread_create(self,arg,flags,ptr)
end
+procedure __tape_eval(self, buffer, len)
+
+ xflush sp:0
+ xflush sp:1
+
+ open (4),[],[index,command,size,ptr]
+
+ // ; alloc stack
+ peek fp:buffer
+ load
+ dalloc
+
+ nsave dp:index, 4
+ nsave dp:ptr, -1
+
+ // while (index < len) {
+labNext:
+ peek fp:len
+ load
+ xcmp dp:index
+ jle labEnd
+
+ //command := buffer[index];
+ peek fp:buffer
+ load dp:index
+ xload
+ and n:0FFh
+ save dp:command
+
+ // index += 1;
+ nadd dp:index, 1
+
+ // size := buffer[index];
+ load dp:index
+ xload
+ save dp:size
+
+ // index += 4;
+ nadd dp:index, 4
+
+ // check attribute type
+ load dp:command
+ cmp n:020h
+ jge labSpecial
+
+ // copy arguments
+ xassignsp
+ store sp:0
+ load dp:ptr
+ add n:1
+ xset fp:0
+ swap sp:0
+ load dp:command
+ dtrans
+
+ set dp:command
+ store sp:0
+ iadd dp:ptr, 4
+
+ // loadClass
+ call extern:LoadClassByBufferLA(buffer, *index, *size)
+ cmp n:0
+ jeq labNotFound
+
+ // ; !! NOTE : we taking advantage that the operation with sp:0 does not affect the real stack
+ save sp:0
+ peek sp:0
+ xrefresh sp:0
+
+ mov mssg : "function:#constructor[0]"
+ xadd dp:command
+
+ call vt:0
+
+ // ; store the result
+ load dp:ptr
+ store sp:0
+ set fp:0
+ xassign
+ nadd dp:ptr, -1
+
+ // i += size
+ set dp:size
+ store sp:0
+ iadd dp:index, 4
+
+ jump labNext
+
+labSpecial:
+ peek fp:buffer
+ store sp:3
+ set dp:size
+ store sp:2
+ set dp:index
+ store sp:1
+ set class:"system'text'UTF8Encoding"
+ store sp:0
+ mov mssg:"toString[4]"
+ call mssg:"toString[4]", class:"system'text'UTF8Encoding"
+
+ // ; store the result
+ load dp:ptr
+ store sp:0
+ set fp:0
+ xassign
+ nadd dp:ptr, -1
+
+ // i += size
+ set dp:size
+ store sp:0
+ iadd dp:index, 4
+
+ jump labNext
+
+labNotFound:
+ // UTF8Encoding.toString(index,size,buffer)
+ peek fp:buffer
+ store sp:3
+ set dp:size
+ store sp:2
+ set dp:index
+ store sp:1
+ set class:"system'text'UTF8Encoding"
+ store sp:0
+ mov mssg:"toString[4]"
+ call mssg:"toString[4]", class:"system'text'UTF8Encoding"
+ store sp:1
+ set class : "system'TypeLoaderException"
+ store sp:0
+
+ set mssgconst : "new[2]"
+ throw
+
+labEnd:
+ load dp:ptr
+ add n:1
+ set fp:0
+ xget
+
+ close []
+ quit
+
+end
+
procedure critical_exception_handler
cmp n:EXCEPTION_ACCESS_VIOLATION
@@ -1290,6 +1683,7 @@ labNext:
nadd dp:i, 1
load dp:i
+ set marray:"$forwards'meta$startUpSymbols"
xget
xcall
@@ -1364,7 +1758,7 @@ symbol sta_start
call extern:InitializeSTLA (
*arg1,
- procedure:"system'core_routines'startUpSymbols",
+ symbol:"$auto'startUpSymbol",
procedure:"system'core_routines'critical_exception_handler")
close []
diff --git a/src60/extensions/console.l b/src60/extensions/console.l
index 056cd31060..840b656f3d 100644
--- a/src60/extensions/console.l
+++ b/src60/extensions/console.l
@@ -1,4 +1,5 @@
import system'routines;
+import system'text;
// --- outputOp ---
@@ -53,6 +54,43 @@ public extension outputOp
// }
}
+public extension outputFormatterOp
+{
+ printPaddingRight(int width, params object[] list)
+ {
+ auto buffer := new TextBuilder();
+
+ int len := list.Length;
+ for (int i := 0, i < len, i += 1)
+ {
+ object obj := list[i];
+
+ buffer.write(obj.toString())
+ };
+
+ self.writePaddingRight(buffer.Value, $32, width);
+
+ ^ self
+ }
+
+ printPaddingLeft(int width, params object[] list)
+ {
+ auto buffer := new TextBuilder();
+
+ int len := list.Length;
+ for (int i := 0, i < len, i += 1)
+ {
+ object obj := list[i];
+
+ buffer.write(obj.toString())
+ };
+
+ self.writePaddingLeft(buffer.Value, $32, width);
+
+ ^ self
+ }
+}
+
public extension inputOp
{
loadLineTo(var)
diff --git a/src60/extensions/convertors.l b/src60/extensions/convertors.l
index dc196f10c4..ad36a9d6d7 100644
--- a/src60/extensions/convertors.l
+++ b/src60/extensions/convertors.l
@@ -128,12 +128,35 @@ public extension stringConvertOp
public extension intConvertOp
{
int toInt()
- = intConvertor.convert(self, 10);
+ = intConvertor.convert(self);
int toInt(int radix)
= intConvertor.convert(self, radix);
}
+// --- byteConvertOp ---
+
+public extension byteConvertOp
+{
+ byte toByte()
+ = byteConvertor.convert(self);
+}
+
+// --- shortConvertOp ---
+
+public extension shortConvertOp
+{
+ short toShort()
+ = shortConvertor.convert(self);
+}
+
+// --- longConvertOp ---
+public extension longConvertOp
+{
+ long toLong()
+ = longConvertor.convert(self);
+}
+
// --- realConvertOp ---
public extension realConvertOp
{
diff --git a/src60/extensions/extensions.prj b/src60/extensions/extensions.prj
index bb4f5fa35a..871e6b1ce3 100644
--- a/src60/extensions/extensions.prj
+++ b/src60/extensions/extensions.prj
@@ -25,6 +25,7 @@
app.l
text\strings.l
text\words.l
+ math\functions.l
routines\enumerating.l
diff --git a/src60/extensions/extensions.project b/src60/extensions/extensions.project
index 80d1f1fc8a..6bc7653e38 100644
--- a/src60/extensions/extensions.project
+++ b/src60/extensions/extensions.project
@@ -35,6 +35,7 @@
lnx_args.l
text/strings.l
text/words.l
+ math/functions.l
routines/enumerating.l
diff --git a/src60/extensions/math/functions.l b/src60/extensions/math/functions.l
new file mode 100644
index 0000000000..9ef6ef19ac
--- /dev/null
+++ b/src60/extensions/math/functions.l
@@ -0,0 +1,163 @@
+import system'math;
+
+namespace math
+{
+ public singleton modulo
+ {
+ function(loperand, roperand)
+ = cast int(loperand).mod(roperand);
+
+ int function(int loperand, int roperand)
+ = loperand.mod(roperand);
+
+ byte function(byte loperand, byte roperand)
+ = loperand.mod(roperand);
+
+ short function(short loperand, short roperand)
+ = loperand.mod(roperand);
+
+ uint function(uint loperand, uint roperand)
+ = cast int(loperand).mod(roperand);
+
+ long function(long loperand, long roperand)
+ = loperand.mod(roperand);
+ }
+
+ public singleton abs
+ {
+ real function(real loperand)
+ = loperand.Absolute;
+
+ int function(int loperand)
+ = loperand.Absolute;
+
+ byte function(byte loperand)
+ = loperand.Absolute;
+
+ short function(short loperand)
+ = loperand.Absolute;
+
+ long function(long loperand)
+ = loperand.Absolute;
+ }
+
+ public singleton truncate
+ {
+ real function(real operand, int precision)
+ = operand.truncate(precision);
+ }
+
+ public singleton frac
+ {
+ real function(real operand)
+ = operand.frac();
+ }
+
+ public singleton floor
+ {
+ real function(real operand)
+ = operand.floor();
+ }
+
+ public singleton ceil
+ {
+ real function(real operand)
+ = operand.ceil();
+ }
+
+ public singleton power
+ {
+ function(loperand, roperand)
+ = cast real(loperand).power(roperand);
+
+ real function(real loperand, int roperand)
+ = loperand.power(roperand);
+
+ real function(real loperand, real roperand)
+ = loperand.power(roperand);
+
+ int function(int loperand, int roperand)
+ = loperand.power(roperand);
+
+ byte function(byte loperand, int roperand)
+ = loperand.power(roperand);
+
+ short function(short loperand, int roperand)
+ = loperand.power(roperand);
+
+ long function(long loperand, long roperand)
+ = loperand.power(roperand);
+ }
+
+ public singleton sqr
+ {
+ real function(real operand)
+ = operand.sqr();
+ }
+
+ public singleton sqrt
+ {
+ real function(real operand)
+ = operand.sqrt();
+ }
+
+ public singleton exp
+ {
+ real function(real operand)
+ = operand.exp();
+ }
+
+ public singleton ln
+ {
+ real function(real operand)
+ = operand.ln();
+ }
+
+ public singleton sin
+ {
+ real function(real operand)
+ = operand.sin();
+ }
+
+ public singleton cos
+ {
+ real function(real operand)
+ = operand.cos();
+ }
+
+ public singleton tan
+ {
+ real function(real operand)
+ = operand.tan();
+ }
+
+ public singleton arctan
+ {
+ real function(real operand)
+ = operand.arctan();
+ }
+
+ public singleton arcsin
+ {
+ real function(real operand)
+ = operand.arcsin();
+ }
+
+ public singleton arccos
+ {
+ real function(real operand)
+ = operand.arccos();
+ }
+
+ public singleton log2
+ {
+ real function(real operand)
+ = operand.log2();
+ }
+
+ public singleton log10
+ {
+ real function(real operand)
+ = operand.log10();
+ }
+}
\ No newline at end of file
diff --git a/src60/extensions/random.l b/src60/extensions/random.l
index 7be76b4d35..abe50dd56d 100644
--- a/src60/extensions/random.l
+++ b/src60/extensions/random.l
@@ -19,10 +19,9 @@ sealed struct RandomGenerator
private int eval(int maxValue)
{
- int number := self.eval();
- int middle := maxValue / 2;
+ int number := self.eval().Absolute;
- ^ middle + number.mod(middle);
+ ^ 0 + number.mod(maxValue);
}
private int eval()
diff --git a/src60/extensions/scripting/interpreter.l b/src60/extensions/scripting/interpreter.l
index fed4826098..b195ad34b7 100644
--- a/src60/extensions/scripting/interpreter.l
+++ b/src60/extensions/scripting/interpreter.l
@@ -1,4 +1,5 @@
import system'text;
+import system'dynamic;
// --- IOException ---
@@ -16,13 +17,13 @@ public sealed class ScriptEngine
constructor()
{
- _scopeId := extern elenasm.NewScope()
+ _scopeId := extern elenasm.NewScopeSMLA()
}
internal string lastScriptError()
{
byte buffer[256];
- int length := extern elenasm.GetStatus(buffer, 255);
+ int length := extern elenasm.GetStatusSMLA(buffer, 255);
^ UTF8Encoding.toString(0, length, buffer);
}
@@ -30,7 +31,7 @@ public sealed class ScriptEngine
string evaluateScriptAsText(string script)
{
- pointer tape := extern elenasm.InterpretScopeScript
+ pointer tape := extern elenasm.InterpretScopeScriptSMLA
(_scopeId, script);
if (tape.isUnassigned())
@@ -38,20 +39,44 @@ public sealed class ScriptEngine
auto retVal := cast string(tape);
- extern elenasm.Release(tape);
+ extern elenasm.ReleaseSMLA(tape);
^ retVal
}
private loadScriptFile(string path, int encoding, int autoDetect)
{
- pointer ptr := extern elenasm.InterpretScopeFile
+ pointer ptr := extern elenasm.InterpretScopeFileSMLA
(_scopeId, path, encoding, autoDetect);
if (ptr.isUnassigned())
{ ScriptEngineException.raise(self.lastScriptError()) };
- extern elenasm.Release(ptr)
+ extern elenasm.ReleaseSMLA(ptr)
+ }
+
+ private buildTape(pointer tape)
+ {
+ var retVal := nil;
+ byte temp[1024];
+ int len := extern elenasm.GetLengthSMLA(tape);
+
+ if (len <= 1024) {
+ tape.copyTo(temp, len);
+
+ retVal := StreamTapeInterpreter.build(temp, len)
+ }
+ else {
+ auto dump := new byte[](len);
+
+ tape.copyTo(dump, len);
+
+ retVal := StreamTapeInterpreter.build(dump, len);
+ };
+
+ extern elenasm.ReleaseSMLA(tape);
+
+ ^ retVal
}
string loadScriptAsText(string script)
@@ -61,4 +86,16 @@ public sealed class ScriptEngine
{
self.loadScriptFile(path, 0, -1);
}
+
+ buildScript(string script)
+ {
+ pointer tape := extern elenasm.InterpretScopeScriptSMLA
+ (_scopeId, script);
+
+ if (tape.isUnassigned())
+ { ScriptEngineException.raise(self.lastScriptError()) };
+
+
+ ^ self.buildTape(tape)
+ }
}
\ No newline at end of file
diff --git a/src60/system/app.l b/src60/system/app.l
index 3a95fcd43c..375fd302eb 100644
--- a/src60/system/app.l
+++ b/src60/system/app.l
@@ -11,10 +11,3 @@ entry()
private entrySymbol
= entry();
-
-// --- startUpSymbols ---
-#new __string startUpSymbols;
-
-// #let startUpSymbols += distributed preloadedSymbols;
-#let startUpSymbols += entrySymbol;
-
diff --git a/src60/system/base.l b/src60/system/base.l
index b0c635ddd4..f59edd78ab 100644
--- a/src60/system/base.l
+++ b/src60/system/base.l
@@ -14,6 +14,15 @@ public inline info(descr)
#let super descriptions[$name __decl] := descr;
}
+// --- preloaded ---
+
+public inline preloaded()
+{
+ #new __string preloadedSymbols;
+
+ #let preloadedSymbols += __decl;
+}
+
// --- prop ---
public field prop
@@ -39,6 +48,8 @@ public field rprop
}
}
+// --- interface ---
+
public interface
{
T cast() = new T
diff --git a/src60/system/basic.l b/src60/system/basic.l
index 0cdbbdec5f..990d7e67c1 100644
--- a/src60/system/basic.l
+++ b/src60/system/basic.l
@@ -801,7 +801,7 @@ public const struct IntNumber : IntBaseNumber,
constructor(uint n)
: info("Creates the object with specified value")
- = n;
+ = intConvertor.convert(n);
constructor(byte b)
= b;
@@ -1083,26 +1083,26 @@ public const struct IntNumber : IntBaseNumber,
public sealed const struct UIntNumber : IntBaseNumber,
info("A unsigned 32 bit integer")
{
- embeddable __int theValue[4];
+ embeddable __uint _value[4];
constructor(byte b)
{
- theValue := b;
+ _value := uintConvertor.convert(b);
}
constructor(short s)
{
- theValue := s;
+ _value := uintConvertor.convert(s);
}
constructor(int n)
{
- theValue := n
+ _value := uintConvertor.convert(n);
}
constructor(uint n)
{
- theValue := n
+ _value := n
}
constructor()
@@ -1110,12 +1110,12 @@ public sealed const struct UIntNumber : IntBaseNumber,
cast u(string s)
{
- theValue := uintConvertor.convert(s);
+ _value := uintConvertor.convert(s);
}
cast H(string s)
{
- theValue := uintConvertor.convert(s, 16);
+ _value := uintConvertor.convert(s, 16);
}
static uint MinValue
@@ -1128,7 +1128,7 @@ public sealed const struct UIntNumber : IntBaseNumber,
string toPrintable()
: info("Returns the literal presentation")
- = stringConvertor.convert(self, 10);
+ = stringConvertor.convert(self, 16);
short cast()
: info("Returns the value as a short integer")
@@ -1163,15 +1163,15 @@ public sealed const struct UIntNumber : IntBaseNumber,
bool equal(uint n)
: info("Compares the value")
- = theValue == n;
+ = _value == n;
bool less(uint n)
: info("Compares the value")
- = theValue < n;
+ = _value < n;
bool equal(int n)
: info("Compares the value")
- = theValue == n;
+ <= equal(cast uint(n));
bool less(int n)
: info("Compares the value")
@@ -1231,35 +1231,35 @@ public sealed const struct UIntNumber : IntBaseNumber,
uint add(uint n)
: info("Returns the sum")
- = theValue + n;
+ = _value + n;
uint subtract(uint n)
: info("Returns the difference")
- = theValue - n;
+ = _value - n;
uint multiply(uint n)
: info("Returns the product")
- = theValue * n;
+ = _value * n;
uint divide(uint n)
: info("Returns the result of integer division")
- = theValue / n;
+ = _value / n;
int add(int n)
: info("Returns the sum")
- = theValue + n;
+ <= add(cast uint(n));
int subtract(int n)
: info("Returns the difference")
- = theValue - n;
+ <= subtract(cast uint(n));
int multiply(int n)
: info("Returns the product")
- = theValue * n;
+ <= multiply(cast uint(n));
int divide(int n)
: info("Returns the result of integer division")
- = theValue / n;
+ <= divide(cast uint(n));
int add(byte n)
: info("Returns the sum")
@@ -1328,27 +1328,27 @@ public sealed const struct UIntNumber : IntBaseNumber,
uint band(uint n)
: info("Returns the result of bitwise AND operation")
- = theValue & n;
+ = _value & n;
uint bor(uint n)
: info("Returns the result of bitwise OR operation")
- = theValue | n;
+ = _value | n;
uint bxor(uint n)
: info("Returns the result of bitwise XOR operation")
- = theValue ^ n;
+ = _value ^ n;
int band(int n)
: info("Returns the result of bitwise AND operation")
- = theValue & n;
+ <= band(cast uint(n));
int bor(int n)
: info("Returns the result of bitwise OR operation")
- = theValue | n;
+ <= bor(cast uint(n));
int bxor(int n)
: info("Returns the result of bitwise XOR operation")
- = theValue ^ n;
+ <= bxor(cast uint(n));
uint band(short n)
: info("Returns the result of bitwise AND operation")
@@ -1386,15 +1386,21 @@ public sealed const struct UIntNumber : IntBaseNumber,
: info("Returns the result of bitwise XOR operation")
= new LongNumber(n).bxor(n);
+ uint shiftLeft(uint val)
+ = _value $shl val;
+
uint shiftLeft(int val)
- = theValue $shl val;
+ <= shiftLeft(cast uint(val));
+
+ uint shiftRight(uint val)
+ = _value $shr val;
uint shiftRight(int val)
- = theValue $shr val;
+ <= shiftRight(cast uint(val));
get uint BInverted()
: info("Bitwise inversion")
- = ~theValue;
+ = ~_value;
uint clone()
= new UIntNumber(self);
@@ -1493,7 +1499,7 @@ public sealed const struct LongNumber : IntBaseNumber,
<= less(cast long(s));
bool equal(int n)
- <= equal(cast int(n));
+ <= equal(cast long(n));
bool less(int n)
<= less(cast long(n));
@@ -1513,6 +1519,9 @@ public sealed const struct LongNumber : IntBaseNumber,
multiply(n)
<= multiply(cast long(n));
+ divide(n)
+ <= divide(cast long(n));
+
long add(long n)
= theValue + n;
@@ -1529,49 +1538,49 @@ public sealed const struct LongNumber : IntBaseNumber,
<= add(cast long(n));
long subtract(byte n)
- <= add(cast long(n));
+ <= subtract(cast long(n));
long multiply(byte n)
- <= add(cast long(n));
+ <= multiply(cast long(n));
long divide(byte n)
- <= add(cast long(n));
+ <= divide(cast long(n));
long add(short n)
<= add(cast long(n));
long subtract(short n)
- <= add(cast long(n));
+ <= subtract(cast long(n));
long multiply(short n)
- <= add(cast long(n));
+ <= multiply(cast long(n));
long divide(short n)
- <= add(cast long(n));
+ <= divide(cast long(n));
long add(int n)
<= add(cast long(n));
long subtract(int n)
- <= add(cast long(n));
+ <= subtract(cast long(n));
long multiply(int n)
- <= add(cast long(n));
+ <= multiply(cast long(n));
long divide(int n)
- <= add(cast long(n));
+ <= divide(cast long(n));
long add(uint n)
<= add(cast long(n));
long subtract(uint n)
- <= add(cast long(n));
+ <= subtract(cast long(n));
long multiply(uint n)
- <= add(cast long(n));
+ <= multiply(cast long(n));
long divide(uint n)
- <= add(cast long(n));
+ <= divide(cast long(n));
real add(real n)
= new RealNumber(self).add(n);
@@ -1607,37 +1616,37 @@ public sealed const struct LongNumber : IntBaseNumber,
<= band(cast long(n));
long bor(byte n)
- <= band(cast long(n));
+ <= bor(cast long(n));
long bxor(byte n)
- <= band(cast long(n));
+ <= bxor(cast long(n));
long band(short n)
<= band(cast long(n));
long bor(short n)
- <= band(cast long(n));
+ <= bor(cast long(n));
long bxor(short n)
- <= band(cast long(n));
+ <= bxor(cast long(n));
long band(int n)
<= band(cast long(n));
long bor(int n)
- <= band(cast long(n));
+ <= bor(cast long(n));
long bxor(int n)
- <= band(cast long(n));
+ <= bxor(cast long(n));
long band(uint n)
<= band(cast long(n));
long bor(uint n)
- <= band(cast long(n));
+ <= bor(cast long(n));
long bxor(uint n)
- <= band(cast long(n));
+ <= bxor(cast long(n));
long shiftLeft(int val)
= theValue $shl val;
@@ -1674,17 +1683,20 @@ public sealed const struct RealNumber : BaseNumber,
: info("Returns the maximal value")
= 1.7976931348623157e+308r;
- static real NegativeInfinity
+ static real NegativeInfinity
: info("Returns the negative infinity")
- = -1.0 / 0.0;
+ = -1.0 / 0.0;
- static real PositiveInfinity
+ static real PositiveInfinity
: info("Returns the positive infinity")
- = 1.0 / 0.0;
+ = 1.0 / 0.0;
- static real NaN
+ static real NaN
: info("Returns the positive infinity")
- = 0.0 / 0.0;
+ = 0.0 / 0.0;
+
+ static real Pi
+ = Pi_value;
constructor(int n)
= realConvertor.convert(n);
@@ -1869,6 +1881,8 @@ public sealed const struct RealNumber : BaseNumber,
= 0.0 - theValue;
}
+public real Pi_value = PrimitiveRealOperations.getPi();
+
// --- CharValue ---
public const struct CharValue : BaseValue,
@@ -2053,4 +2067,6 @@ public sealed class KeyValue
dispatch() : info("Redirects the incoming messages to the object")
=> value;
-}
\ No newline at end of file
+}
+
+//public real symbol Pi_value = PrimitiveRealOperations.getPi();
\ No newline at end of file
diff --git a/src60/system/calendar/win_datetime.l b/src60/system/calendar/win_datetime.l
index a71ec09690..f7fdd4f323 100644
--- a/src60/system/calendar/win_datetime.l
+++ b/src60/system/calendar/win_datetime.l
@@ -1,7 +1,7 @@
namespace calendar
{
- const int DATE_SHORTDATE = 00000001h;
- const int DATE_LONGDATE = 00000002h;
+ const IntNumber DATE_SHORTDATE = 00000001h;
+ const IntNumber DATE_LONGDATE = 00000002h;
// --- SystemTime ---
public sealed const struct SystemTime : BaseValue
diff --git a/src60/system/collections/template_tests.l b/src60/system/collections/template_tests.l
index 27a8f4ca9d..2f97c76479 100644
--- a/src60/system/collections/template_tests.l
+++ b/src60/system/collections/template_tests.l
@@ -11,12 +11,12 @@ namespace collections
collections_template_test()
{
List o1;
- Map o2;
Tuple t1;
Tuple t2;
Tuple t3;
Tuple t4;
Tuple t5;
Tuple t6;
+ Map o2;
}
}
diff --git a/src60/system/collections/tuples.l b/src60/system/collections/tuples.l
index 5e4c9df065..47e18c0881 100644
--- a/src60/system/collections/tuples.l
+++ b/src60/system/collections/tuples.l
@@ -11,7 +11,14 @@ namespace collections
Item1 := o1
}
- T1 Item1 : prop;
+ T1 Item1 : rprop;
+
+ at(int index)
+ {
+ index =>
+ 0 { ^ Item1 }
+ : { OutOfRangeException.raise() }
+ }
}
public sealed Tuple
@@ -31,8 +38,16 @@ namespace collections
Item1 := o1
}
- T1 Item1 : prop;
- T2 Item2 : prop;
+ T1 Item1 : rprop;
+ T2 Item2 : rprop;
+
+ at(int index)
+ {
+ index =>
+ 0 { ^ Item1 }
+ 1 { ^ Item2 }
+ : { OutOfRangeException.raise() }
+ }
}
public sealed Tuple
@@ -48,9 +63,18 @@ namespace collections
Item3 := o3
}
- T1 Item1 : prop;
- T2 Item2 : prop;
- T3 Item3 : prop;
+ T1 Item1 : rprop;
+ T2 Item2 : rprop;
+ T3 Item3 : rprop;
+
+ at(int index)
+ {
+ index =>
+ 0 { ^ Item1 }
+ 1 { ^ Item2 }
+ 2 { ^ Item3 }
+ : { OutOfRangeException.raise() }
+ }
}
public sealed Tuple
@@ -67,10 +91,20 @@ namespace collections
Item4 := o4
}
- T1 Item1 : prop;
- T2 Item2 : prop;
- T3 Item3 : prop;
- T4 Item4 : prop;
+ T1 Item1 : rprop;
+ T2 Item2 : rprop;
+ T3 Item3 : rprop;
+ T4 Item4 : rprop;
+
+ at(int index)
+ {
+ index =>
+ 0 { ^ Item1 }
+ 1 { ^ Item2 }
+ 2 { ^ Item3 }
+ 3 { ^ Item4 }
+ : { OutOfRangeException.raise() }
+ }
}
public sealed Tuple
@@ -88,11 +122,22 @@ namespace collections
Item5 := o5;
}
- T1 Item1 : prop;
- T2 Item2 : prop;
- T3 Item3 : prop;
- T4 Item4 : prop;
- T5 Item5 : prop;
+ T1 Item1 : rprop;
+ T2 Item2 : rprop;
+ T3 Item3 : rprop;
+ T4 Item4 : rprop;
+ T5 Item5 : rprop;
+
+ at(int index)
+ {
+ index =>
+ 0 { ^ Item1 }
+ 1 { ^ Item2 }
+ 2 { ^ Item3 }
+ 3 { ^ Item4 }
+ 4 { ^ Item5 }
+ : { OutOfRangeException.raise() }
+ }
}
public sealed Tuple
@@ -111,12 +156,24 @@ namespace collections
Item6 := o6;
}
- T1 Item1 : prop;
- T2 Item2 : prop;
- T3 Item3 : prop;
- T4 Item4 : prop;
- T5 Item5 : prop;
- T6 Item6 : prop;
+ T1 Item1 : rprop;
+ T2 Item2 : rprop;
+ T3 Item3 : rprop;
+ T4 Item4 : rprop;
+ T5 Item5 : rprop;
+ T6 Item6 : rprop;
+
+ at(int index)
+ {
+ index =>
+ 0 { ^ Item1 }
+ 1 { ^ Item2 }
+ 2 { ^ Item3 }
+ 3 { ^ Item4 }
+ 4 { ^ Item5 }
+ 5 { ^ Item6 }
+ : { OutOfRangeException.raise() }
+ }
}
}
\ No newline at end of file
diff --git a/src60/system/convertors.l b/src60/system/convertors.l
index 66cac2110b..20de08529a 100644
--- a/src60/system/convertors.l
+++ b/src60/system/convertors.l
@@ -36,6 +36,10 @@ public singleton byteConvertor
byte convert(int n)
{
+ if (n > 255 || n < 0) {
+ OutOfRangeException.raise();
+ };
+
byte b;
self.convert(n, ref b);
@@ -84,11 +88,11 @@ public singleton byteConvertor
public singleton shortConvertor
{
- convert(int n, ref short retVal) : external(system'core_routines'__intToShort);
+ private convertInt(int n, ref short retVal) : external(system'core_routines'__intToShort);
- convert(uint n, ref short retVal) : external(system'core_routines'__uintToShort);
+ private convertUInt(uint n, ref short retVal) : external(system'core_routines'__uintToShort);
- convert(byte b, ref short retVal) : external(system'core_routines'__byteToShort);
+ private convertByte(byte b, ref short retVal) : external(system'core_routines'__byteToShort);
short convert(o)
= cast short(o);
@@ -99,7 +103,7 @@ public singleton shortConvertor
short convert(byte b)
{
short s;
- self.convert(b, ref s);
+ self.convertByte(b, ref s);
^ s;
}
@@ -107,7 +111,7 @@ public singleton shortConvertor
short convert(int n)
{
short s;
- self.convert(n, ref s);
+ self.convertInt(n, ref s);
^ s;
}
@@ -115,7 +119,7 @@ public singleton shortConvertor
short convert(uint n)
{
short s;
- self.convert(n, ref s);
+ self.convertUInt(n, ref s);
^ s;
}
@@ -163,6 +167,7 @@ public singleton intConvertor
private convertChar(char ch, ref int retVal) : external(system'core_routines'__charToInt);
private convertLong(long l, ref int retVal) : external(system'core_routines'__longToInt);
private convertReal(real l, ref int retVal) : external(system'core_routines'__realToInt);
+ private convertUInt(uint l, ref int retVal) : external(system'core_routines'__uintToInt);
int convert(o)
= cast int(o);
@@ -184,6 +189,13 @@ public singleton intConvertor
^ n;
}
+ int convert(uint n)
+ {
+ self.convertUInt(n, ref int retVal);
+
+ ^ retVal
+ }
+
int convert(char ch)
{
self.convertChar(ch, ref int retVal);
@@ -222,7 +234,7 @@ public singleton intConvertor
int ch := c;
ch := ch - 48;
if (ch >= radix) {
- ch := ch - 49;
+ ch := ch - 7;
};
val := val * radix;
val := val + ch;
@@ -247,7 +259,7 @@ public singleton intConvertor
int ch := c;
ch := ch - 48;
if (ch >= radix) {
- ch := ch - 49;
+ ch := ch - 7;
};
val := val * radix;
val := val + ch;
@@ -258,28 +270,41 @@ public singleton intConvertor
int convert(wide s)
<= convert(s, 10);
-
- int convert(uint n)
- = new IntNumber(n);
}
// --- uintConvertor ---
public singleton uintConvertor
{
+ private copyDirectly(int n, ref uint retVal) : external(system'core_routines'__intToUInt);
+
uint convert(o)
= cast uint(o);
uint convert(int n)
- = new UIntNumber(n);
+ {
+// if (n < 0) {
+// InvalidArgumentException.raise();
+// };
+
+ self.copyDirectly(n, ref uint retVal);
+
+ ^ retVal
+ }
uint convert(byte b)
{
- uint n := b;
+ int n := b;
- ^ n;
+ ^ uintConvertor.convert(n);
}
+ uint convert(short s)
+ {
+ int n := s;
+
+ ^ uintConvertor.convert(n);
+ }
uint convert(long l)
{
int n := intConvertor.convert(l);
@@ -291,14 +316,15 @@ public singleton uintConvertor
{
int len := s.Length;
uint val := 0;
+ uint r := radix;
for (int i := 0, i < len, i := i + 1) {
byte c := s[i];
- int ch := c;
+ uint ch := c;
ch := ch - 48;
- if (ch >= radix) {
- ch := ch - 49;
+ if (ch >= r) {
+ ch := ch - 7;
};
- val := val * radix;
+ val := val * r;
val := val + ch;
};
@@ -555,11 +581,19 @@ public singleton stringConvertor
n := n / radix;
tmp := 48 + r;
+ if (r > 9) {
+ tmp :=tmp + 7;
+ };
+
buffer[index] := tmp;
index := index - 1;
len := len + 1;
};
tmp := 48 + n;
+ if (n > 9) {
+ tmp :=tmp + 7;
+ };
+
buffer[index] := tmp;
len := len + 1;
@@ -617,21 +651,30 @@ public singleton stringConvertor
string convert(uint value, int radix)
{
uint n := value;
+ uint uradix := radix;
byte buffer[12];
byte tmp;
int len := 0;
int index := 11;
- while (n >= radix) {
- int r := n.mod(radix);
- n := n / radix;
+ while (n >= uradix) {
+ uint r := n.mod(uradix);
+ n := n / uradix;
tmp := 48 + r;
+ if (r > 9) {
+ tmp :=tmp + 7;
+ };
+
buffer[index] := tmp;
index := index - 1;
len := len + 1;
};
tmp := 48 + n;
+ if (n > 9) {
+ tmp := tmp + 7;
+ };
+
buffer[index] := tmp;
len := len + 1;
diff --git a/src60/system/dynamic/tape.l b/src60/system/dynamic/tape.l
new file mode 100644
index 0000000000..3b871bb287
--- /dev/null
+++ b/src60/system/dynamic/tape.l
@@ -0,0 +1,6 @@
+import system;
+
+public singleton StreamTapeInterpreter
+{
+ build(byte[] buffer, int len) : external(system'core_routines'__tape_eval);
+}
\ No newline at end of file
diff --git a/src60/system/exceptions.l b/src60/system/exceptions.l
index 36c95c1412..7837cadf2b 100644
--- a/src60/system/exceptions.l
+++ b/src60/system/exceptions.l
@@ -7,7 +7,7 @@ public class Exception
constructor new(string message)
{
this message := message;
- this callStack := new CallStack();
+ this callStack := new CallStack(3);
}
constructor new()
@@ -143,3 +143,13 @@ public class FormatException : Exception
constructor new(string message)
<= super new(message);
}
+
+// --- TypeLoaderException ---
+
+public class TypeLoaderException : Exception
+{
+ /// Creates the exception
+ constructor new(string className)
+ <= super new("Type " + className + " cannot be loaded");
+}
+
diff --git a/src60/system/extensions.l b/src60/system/extensions.l
index 3093e63b1b..e05f93b124 100644
--- a/src60/system/extensions.l
+++ b/src60/system/extensions.l
@@ -24,6 +24,184 @@ public extension objectOp
^ len != 0;
}
+
+ doWith(action)
+ = action(self);
+
+ bool instanceOf(type) : external(system'core_routines'__object_instanceOf),
+ info("Checks if the object is an instance of type");
+}
+
+// --- byteOp ---
+
+public extension byteOp : ByteNumber
+{
+ int Hashcode
+ {
+ // Reads the object hash code into the output parameter
+ get()
+ {
+ int val := self;
+ int retVal := PrimitiveIntOperations.getHashcode(val);
+
+ ^ retVal
+ }
+ }
+
+ get byte Absolute()
+ {
+ byte n := self;
+
+ if (n < 0)
+ { n := -n };
+
+ ^ n
+ }
+
+ byte power(int y)
+ {
+ byte x := self;
+ byte r := 1;
+
+ for (int i := 0, i < y, i += 1)
+ {
+ r := r * x
+ };
+
+ ^ new ByteNumber(r)
+ }
+
+ byte sqr()
+ = self * self;
+
+ byte sqrt()
+ {
+ byte num := self;
+
+ if (num == 0)
+ { ^ 0 };
+
+ byte n := num / 2 + 1;
+ byte n1 := (n + (num / n)) / 2;
+ while (n1 < n)
+ {
+ n := n1;
+ n1 := (n + (num / n)) / 2
+ };
+
+ ^ n
+ }
+
+ byte mod(operand)
+ {
+ var retVal := self / operand * operand;
+
+ ^ byteConvertor.convert(retVal)
+ }
+
+ bool isOdd()
+ = self.mod:2 != 0;
+
+ bool isEven()
+ = self.mod:2 == 0;
+
+ bool isZero()
+ = self.equal(0);
+
+ bool isPositive()
+ = self > 0;
+
+ bool isNegative()
+ = self < 0;
+
+ bool isNonnegative()
+ = self <= 0;
+}
+
+// --- shortOp ---
+
+public extension shortOp : ShortNumber
+{
+ int Hashcode
+ {
+ // Reads the object hash code into the output parameter
+ get()
+ {
+ int val := self;
+ int retVal := PrimitiveIntOperations.getHashcode(val);
+
+ ^ retVal
+ }
+ }
+
+ get short Absolute()
+ {
+ short n := self;
+
+ if (n < 0)
+ { n := -n };
+
+ ^ n
+ }
+
+ short power(int y)
+ {
+ short x := self;
+ short r := 1;
+
+ for (int i := 0, i < y, i += 1)
+ {
+ r := r * x
+ };
+
+ ^ new ShortNumber(r)
+ }
+
+ short sqr()
+ = self * self;
+
+ short sqrt()
+ {
+ short num := self;
+
+ if (num == 0)
+ { ^ 0 };
+
+ short n := num / 2 + 1;
+ short n1 := (n + (num / n)) / 2;
+ while (n1 < n)
+ {
+ n := n1;
+ n1 := (n + (num / n)) / 2
+ };
+
+ ^ n
+ }
+
+ short mod(operand)
+ {
+ var retVal := self / operand * operand;
+
+ ^ shortConvertor.convert(retVal)
+ }
+
+ bool isOdd()
+ = self.mod:2 != 0;
+
+ bool isEven()
+ = self.mod:2 == 0;
+
+ bool isZero()
+ = self.equal(0);
+
+ bool isPositive()
+ = self > 0;
+
+ bool isNegative()
+ = self < 0;
+
+ bool isNonnegative()
+ = self <= 0;
}
// --- intOp ---
@@ -51,6 +229,45 @@ public extension intOp : IntNumber
^ n
}
+ int power(int y)
+ {
+ int x := self;
+ int r := 1;
+ if (x == 0)
+ { r := 0 };
+
+ for(int i := 0, i < y, i += 1)
+ {
+ r := r * x
+ };
+
+ ^ r
+ }
+
+ int sqr()
+ = self * self;
+
+ int sqrt()
+ {
+ int num := self;
+
+ if (num == 0)
+ { ^ 0 };
+
+ int n := num / 2 + 1;
+ int n1 := (n + (num / n)) / 2;
+ while (n1 < n)
+ {
+ n := n1;
+ n1 := (n + (num / n)) / 2
+ };
+
+ ^ n
+ }
+
+ real realDiv(n)
+ = new RealNumber(self).divide:n;
+
int mod(int operand)
{
int retVal := self / operand * operand;
@@ -66,12 +283,152 @@ public extension intOp : IntNumber
^ retVal
}
+
+ bool isOdd()
+ = self.mod:2 != 0;
+
+ bool isEven()
+ = self.mod:2 == 0;
+
+ bool isZero()
+ = self.equal(0);
+
+ bool isPositive()
+ = self > 0;
+
+ bool isNegative()
+ = self < 0;
+
+ bool isNonnegative()
+ = self <= 0;
+}
+
+// --- uintOp ---
+
+public extension uintOp : UIntNumber
+{
+ uint sqr()
+ = self * self;
+
+ uint sqrt()
+ {
+ uint num := self;
+
+ if (num == 0u)
+ { ^ 0u };
+
+ uint n := num / 2u + 1u;
+ uint n1 := (n + (num / n)) / 2u;
+ while (n1 < n)
+ {
+ n := n1;
+ n1 := (n + (num / n)) / 2u
+ };
+
+ ^ n
+ }
+
+ uint mod(uint operand)
+ {
+ uint retVal := self / operand * operand;
+
+ retVal := self - retVal;
+
+ ^ retVal
+ }
+
+ uint mod(int operand)
+ {
+ uint uoperand := operand;
+ uint retVal := self / uoperand * uoperand;
+
+ retVal := self - retVal;
+
+ ^ retVal
+ }
+
+ uint mod(operand)
+ = self.mod(cast uint(operand));
+
+ real realDiv(n)
+ = new RealNumber(self).divide:n;
+
+ bool isOdd()
+ = self.mod:2 != 0;
+
+ bool isEven()
+ = self.mod:2 == 0;
+
+ bool isZero()
+ = self.equal(0);
+
+ bool isPositive()
+ = self > 0;
+
+ bool isNegative()
+ = self < 0;
+
+ bool isNonnegative()
+ = self <= 0;
}
// --- longOp ---
public extension longOp : LongNumber
-{
+{
+ long power(long y)
+ {
+ long x := self;
+ long r := 1;
+
+ for(long i := 0l, i < y, i += 1l)
+ {
+ r := r * x;
+ };
+
+ ^ new LongNumber(r)
+ }
+
+ long power(int y)
+ {
+ long x := self;
+ long r := 1;
+
+ int i := 0;
+ while (i < y)
+ {
+ r := r * x;
+
+ i += 1;
+ };
+
+ ^ new LongNumber(r)
+ }
+
+ long sqr()
+ = self * self;
+
+ long sqrt()
+ {
+ long num := self;
+
+ if (num == 0l)
+ { ^ 0l };
+
+ long n := num / 2l + 1l;
+ long n1 := (n + (num / n)) / 2l;
+ while (n1 < n)
+ {
+ n := n1;
+ n1 := (n + (num / n)) / 2l
+ };
+
+ ^ n
+ }
+
+ real realDiv(n)
+ = new RealNumber(self).divide:n;
+
long mod(long operand)
{
long retVal := self / operand * operand;
@@ -80,6 +437,24 @@ public extension longOp : LongNumber
^ retVal
}
+
+ bool isOdd()
+ = self.mod:2l != 0l;
+
+ bool isEven()
+ = self.mod:2l == 0l;
+
+ bool isZero()
+ = self.equal(0l);
+
+ bool isPositive()
+ = self > 0l;
+
+ bool isNegative()
+ = self < 0l;
+
+ bool isNonnegative()
+ = self <= 0l;
}
// --- realOp ---
@@ -97,12 +472,257 @@ public extension realOp : RealNumber
}
}
+ real power(real y)
+ {
+ real x := self;
+
+ if(x == 0.0r)
+ { ^ 0.0r };
+
+ if(y == 0.0r)
+ { ^ 1.0r };
+
+ x := x.ln();
+
+ x := x * y;
+
+ x := x.exp();
+
+ ^ x
+ }
+
+ real power(int y)
+ {
+ real x := self;
+
+ if(x == 0.0r)
+ { ^ 0.0r };
+
+ if(y == 0)
+ { ^ 1.0r };
+
+ if (x < 0.0r)
+ {
+ x := x * -1.0r;
+
+ x := x.ln();
+
+ x := x * y;
+
+ x := x.exp();
+
+ if (y.isOdd())
+ { x := x * -1.0r }
+ }
+ else
+ {
+ x := x.ln();
+
+ x := x * y;
+
+ x := x.exp()
+ };
+
+ ^ x
+ }
+
+ real sqr()
+ = self * self;
+
+ real sqrt()
+ {
+ PrimitiveRealOperations.sqrt(self, ref real retVal);
+
+ ^ retVal
+ }
+
+ real exp()
+ {
+ PrimitiveRealOperations.exp(self, ref real retVal);
+
+ ^ retVal
+ }
+
+ real ln()
+ {
+ real retVal := PrimitiveRealOperations.ln(self);
+
+ ^ retVal
+ }
+
+ real sin()
+ {
+ real retVal := PrimitiveRealOperations.sin(self);
+
+ ^ retVal
+ }
+
+ real cos()
+ {
+ real retVal := PrimitiveRealOperations.cos(self);
+
+ ^ retVal
+ }
+
+ real tan()
+ {
+ real sinVal := PrimitiveRealOperations.sin(self);
+ real cosVal := PrimitiveRealOperations.cos(self);
+
+ real n := sinVal / cosVal;
+
+ ^ n
+ }
+
+ real arctan()
+ {
+ real retVal := PrimitiveRealOperations.arctan(self);
+
+ ^ retVal
+ }
+
+ real arcsin()
+ {
+ real n := self;
+ real retVal := 0.0r;
+
+ retVal := n * n;
+ retVal := 1.0r - retVal;
+ real arg := PrimitiveRealOperations.sqrt(retVal);
+
+ arg := n / arg;
+ retVal := PrimitiveRealOperations.arctan(arg);
+
+ ^ retVal
+ }
+
+ real arccos()
+ {
+ real n := self;
+ real retVal := 0.0r;
+
+ retVal := n * n;
+ retVal := 1.0r - retVal;
+ real arg := PrimitiveRealOperations.sqrt(retVal);
+
+ arg := arg / n;
+ retVal := PrimitiveRealOperations.arctan(arg);
+
+ ^ retVal
+ }
+
+ real log2()
+ {
+ real x := self.ln();
+ real y := 2.0.ln();
+
+ ^ x / y
+ }
+
+ real log10()
+ {
+ real x := self.ln();
+ real y := 10.0.ln();
+
+ ^ x / y
+ }
+
get real Integer()
{
PrimitiveRealOperations.trunc(self, ref real retVal);
^ retVal
}
+
+ get int IntegerInt()
+ = intConvertor.convert(self.Integer);
+
+ get real Rounded()
+ {
+ real retVal := PrimitiveRealOperations.round(self);
+
+ ^ retVal
+ }
+
+ get int RoundedInt()
+ = intConvertor.convert(self.Rounded);
+
+ real Absolute
+ = PrimitiveRealOperations.abs(self);
+
+ get real Reciprocal()
+ {
+ real value := self;
+
+ value := 1.0r / value;
+
+ ^ value
+ }
+
+ real frac()
+ {
+ real retVal := self.Absolute;
+
+ ^ retVal - retVal.Integer
+ }
+
+ real ceil()
+ {
+ if (self < 0)
+ {
+ ^ self.Integer
+ }
+ else
+ {
+ real y := self.Integer;
+
+ ^ (y == self).iif(y,y+1)
+ }
+ }
+
+ real floor()
+ {
+ if (self >= 0)
+ {
+ ^ self.Integer
+ }
+ else
+ {
+ real y := self.Integer;
+
+ ^ (y == self).iif(y,y-1)
+ }
+ }
+
+ real truncate(int precision)
+ {
+ real a := self;
+ bool neg := false;
+ if(self.isNegative())
+ {
+ a := a * -1.0r;
+ neg := true
+ };
+
+ int b := 10.power(precision);
+ real c := (a * b).Integer; // returns the integer part of the real number
+
+ a := c / b;
+
+ ^ neg ? (a * -1.0r) : a
+ }
+
+ bool isZero()
+ = self.equal(0.0);
+
+ bool isPositive()
+ = self > 0.0;
+
+ bool isNegative()
+ = self < 0.0;
+
+ bool isNonnegative()
+ = self <= 0.0;
}
// --- intRefOp ---
diff --git a/src60/system/io/win_console.l b/src60/system/io/win_console.l
index f5cc838983..e259b574a4 100644
--- a/src60/system/io/win_console.l
+++ b/src60/system/io/win_console.l
@@ -2,7 +2,7 @@ namespace io
{
import system'text;
- const int FILE_TYPE_CHAR = 2;
+ const IntNumber FILE_TYPE_CHAR = 2;
struct KEY_EVENT_RECORD
{
@@ -108,10 +108,18 @@ namespace io
this h := h
}
+ write(wide s)
+ {
+ int len := s.Length;
+
+ extern KERNEL32.WriteConsoleW(h,s,len,0,0);
+
+ // !!check the result of the operation
+ }
+
write(string s)
{
- int l := s.Length;
- extern KERNEL32.WriteConsoleA(h,s,l,0,0);
+ self.write(cast wide(s))
}
}
diff --git a/src60/system/io/win_files.l b/src60/system/io/win_files.l
index e637c5b439..80616e8d15 100644
--- a/src60/system/io/win_files.l
+++ b/src60/system/io/win_files.l
@@ -3,23 +3,23 @@ import system'text;
namespace io
{
// --- File Access Modes ---
- const int FILE_READ_DATA = 00000001h;
- const int FILE_APPEND_DATA = 00000004h;
- const int FILE_GENERIC_READ = 80000000h;
- const int FILE_GENERIC_WRITE = 40000000h;
+ const IntNumber FILE_READ_DATA = 00000001h;
+ const IntNumber FILE_APPEND_DATA = 00000004h;
+ const IntNumber FILE_GENERIC_READ = 80000000h;
+ const IntNumber FILE_GENERIC_WRITE = 40000000h;
- const int OPEN_EXISTING = 0003h;
- const int CREATE_ALWAYS = 0002h;
- const int OPEN_ALWAYS = 0004h;
+ const IntNumber OPEN_EXISTING = 0003h;
+ const IntNumber CREATE_ALWAYS = 0002h;
+ const IntNumber OPEN_ALWAYS = 0004h;
- const int FILE_SHARE_READ = 00000001h;
- const int FILE_SHARE_WRITE = 00000002h;
+ const IntNumber FILE_SHARE_READ = 00000001h;
+ const IntNumber FILE_SHARE_WRITE = 00000002h;
- const int FILE_BEGIN = 0;
- const int FILE_CURRENT = 1;
- const int FILE_END = 2;
+ const IntNumber FILE_BEGIN = 0;
+ const IntNumber FILE_CURRENT = 1;
+ const IntNumber FILE_END = 2;
- const int FILE_ATTRIBUTE_DIRECTORY = 10h;
+ const IntNumber FILE_ATTRIBUTE_DIRECTORY = 10h;
// --- FileStream ---
public struct FileStream : Stream
diff --git a/src60/system/lnx_basic.l b/src60/system/lnx_basic.l
index 51872567b9..56555af560 100644
--- a/src60/system/lnx_basic.l
+++ b/src60/system/lnx_basic.l
@@ -34,6 +34,14 @@ public sealed class CallStack
this stack := class Array.copy(stack, 0, length);
}
+ constructor(int trimingLevel)
+ {
+ pointer stack[64];
+ self.load(stack, 64, ref int length);
+
+ this stack := class Array.copy(stack, trimingLevel, length - trimingLevel);
+ }
+
string toPrintable()
: info("Generates the call stack literal representation")
{
diff --git a/src60/system/math/math.l b/src60/system/math/math.l
index d4194c98e3..a826cdda79 100644
--- a/src60/system/math/math.l
+++ b/src60/system/math/math.l
@@ -5,6 +5,27 @@ namespace math
// --- mathController ---
singleton mathController
{
+ absolute(byte n)
+ = n.Absolute;
+
+ absolute(short n)
+ = n.Absolute;
+
+ absolute(int n)
+ = n.Absolute;
+
+ absolute(long n)
+ = n.Absolute;
+
+ absolute(real n)
+ = n.Absolute;
+
+ mod(byte n, object m)
+ = n.mod:m;
+
+ mod(short n, object m)
+ = n.mod:m;
+
mod(int n, object m)
= n.mod:m;
@@ -16,6 +37,26 @@ namespace math
{
mod(n)
= mathController.mod(self, n);
+
+ frac()
+ = cast real(self).frac();
+
+ sin()
+ = cast real(self).sin();
+
+ cos()
+ = cast real(self).cos();
+
+ tan()
+ = cast real(self).tan();
+
+ arctan()
+ = cast real(self).arctan();
+
+ arcsin()
+ = cast real(self).arcsin();
+
+ arccos()
+ = cast real(self).arccos();
}
-
}
\ No newline at end of file
diff --git a/src60/system/operations/operations.l b/src60/system/operations/operations.l
index a299f71a2c..7a4647d32a 100644
--- a/src60/system/operations/operations.l
+++ b/src60/system/operations/operations.l
@@ -44,7 +44,6 @@ public template until(loop_body) : __included(statementTem
$rep cast bool(cond_expr) ! { loop_body; __ignore_duplicates step_expr }
}
-
// --- do:until ---
public template do::until(loop_body, cond_expr) : __included(statementTemplates)
@@ -54,6 +53,15 @@ public template do::until(loop_body, cond_expr) : __included(statementTemplates)
$rep cast bool(cond_expr) ! { loop_body }
}
+// --- do:while ---
+
+public template do::while(loop_body, cond_expr) : __included(statementTemplates)
+{
+ loop_body;
+
+ $rep cast bool(cond_expr) ? { loop_body }
+}
+
// --- for ---
public template for(loopBody) : __included(statementTemplates)
@@ -77,9 +85,30 @@ public template try::catch(try_block,catch_block) : __included(statementTemplate
try_block \\ on(catch_block);
}
+// --- try:catch:finally ---
+
+public template try::catch::finally(try_block,catch_block,finally_block) : __included(statementTemplates)
+{
+ try_block \\ on(catch_block) $fnl finally_block;
+}
+
+// --- try:finally ---
+
+public template try::finally(try_block,finally_block) : __included(statementTemplates)
+{
+ try_block $fnl finally_block;
+}
+
// --- extern ---
public template extern(body) : __included(statementTemplates)
{
$ext body
}
+
+// --- operator templates ---
+
+public template operator::alt(expr) : __included(statementTemplates)
+{
+ expr \ back:identifier;
+}
\ No newline at end of file
diff --git a/src60/system/predefined/attributes.l b/src60/system/predefined/attributes.l
index 9ae628cce9..fa5baac968 100644
--- a/src60/system/predefined/attributes.l
+++ b/src60/system/predefined/attributes.l
@@ -22,6 +22,7 @@
#let attributesSymbols["const"] := 80002001h;
#let attributesSymbols["embeddable"] := 80002002h;
#let attributesSymbols["ref"] := 80002003h;
+#let attributesSymbols["readonly"] := 80002004h;
#let attributesSymbols["retoverload"] := 8000200Ah;
#let attributesSymbols["params"] := 8000200Bh;
@@ -55,12 +56,13 @@
#let attributesSymbols["__probe"] := 80001026h;
#let attributesSymbols["template"] := 80001027h;
#let attributesSymbols["weak"] := 80001029h;
+#let attributesSymbols["distributed"] := 8000102Bh;
/// primitive types
#let attributesSymbols["__string"] := 80000801h;
#let attributesSymbols["__float"] := 80000802h;
#let attributesSymbols["__int"] := 80000803h;
-//#let attributesSymbols["__meta"] := 80000804h;
+#let attributesSymbols["__uint"] := 80000804h;
#let attributesSymbols["__word"] := 80000805h;
#let attributesSymbols["mssgconst"] := 80000806h;
#let attributesSymbols["mssg"] := 80000806h;
diff --git a/src60/system/predefined/predefined.l b/src60/system/predefined/predefined.l
index 846424f53a..9ee77bb119 100644
--- a/src60/system/predefined/predefined.l
+++ b/src60/system/predefined/predefined.l
@@ -5,3 +5,4 @@
#let predefinedSymbols["self"] := 80000081h;
#let predefinedSymbols["__decl"] := 80000082h;
#let predefinedSymbols["super"] := 80000083h;
+#let predefinedSymbols["__received"] := 80000084h;
diff --git a/src60/system/primitives.l b/src60/system/primitives.l
index 8a8c9f67bb..769a35ea53 100644
--- a/src60/system/primitives.l
+++ b/src60/system/primitives.l
@@ -67,14 +67,14 @@ internal singleton PrimitiveOperations
};
if (ch < 0C0h)
{
- //InvalidOperaionException.raise()
+ InvalidOperationException.raise()
};
if (ch < 0E0h)
{
int ch2 := sour[index + 1];
int mask := ch2 & 0C0h;
if (mask != 80h) {
- //InvalidOperaionException.raise()
+ InvalidOperationException.raise()
};
ch := ch $shl 6;
ch2 := ch2 + ch;
@@ -88,7 +88,7 @@ internal singleton PrimitiveOperations
int mask := ch2 & 0C0h;
if (mask != 80h) {
- //InvalidOperaionException.raise()
+ InvalidOperationException.raise()
};
ch := ch $shl 12;
@@ -97,7 +97,7 @@ internal singleton PrimitiveOperations
int mask2 := ch3 & 0C0h;
if (mask2 != 80h) {
- //InvalidOperaionException.raise()
+ InvalidOperationException.raise()
};
ch3 := ch3 + ch;
ch3 := ch3 - 0E2080h;
@@ -110,7 +110,7 @@ internal singleton PrimitiveOperations
int mask := ch2 & 0C0h;
if (mask != 80h) {
- //InvalidOperaionException.raise()
+ InvalidOperationException.raise()
};
ch := ch $shl 18;
@@ -119,7 +119,7 @@ internal singleton PrimitiveOperations
int mask2 := ch3 & 0C0h;
if (mask2 != 80h) {
- //InvalidOperaionException.raise()
+ InvalidOperationException.raise()
};
ch3 := ch3 $shl 6;
@@ -127,15 +127,15 @@ internal singleton PrimitiveOperations
int mask3 := ch4 & 0C0h;
if (mask3 != 80h) {
- //InvalidOperaionException.raise()
+ InvalidOperationException.raise()
};
ch4 := ch4 + ch3;
ch4 := ch4 - 3C82080h;
^ ch4
- }
+ };
- //InvalidOperaionException.raise()
+ InvalidOperationException.raise()
}
int readUTF32(short[] sour, int index)
@@ -297,6 +297,31 @@ internal singleton PrimitiveRealOperations
{
trunc(real r, ref real retVal) : external(system'core_routines'__realTrunc);
+ round(real r, ref real retVal) : external(system'core_routines'__realRound);
+
+ abs(real r, ref real retVal) : external(system'core_routines'__realAbs);
+
+ sqrt(real r, ref real retVal) : external(system'core_routines'__realSqrt);
+
+ exp(real r, ref real retVal) : external(system'core_routines'__realExp);
+
+ ln(real r, ref real retVal) : external(system'core_routines'__realLn);
+
+ sin(real r, ref real retVal) : external(system'core_routines'__realSin);
+
+ cos(real r, ref real retVal) : external(system'core_routines'__realCos);
+
+ arctan(real r, ref real retVal) : external(system'core_routines'__realArctan);
+
+ getPi(ref real retVal) : external(system'core_routines'__realPi);
+
+ real getPi()
+ {
+ self.getPi(ref real retVal);
+
+ ^ retVal
+ }
+
int normalizeFloat(ref real value)
{
real positiveExpThreshold := 1.0e7;
diff --git a/src60/system/routines/enumerables.l b/src60/system/routines/enumerables.l
index b66a09d8b9..a5c6aac3e3 100644
--- a/src60/system/routines/enumerables.l
+++ b/src60/system/routines/enumerables.l
@@ -37,6 +37,32 @@ public extension stringListOp : String
^ list
}
+
+ Array splitBy(string value)
+ {
+ ArrayList list := new ArrayList();
+ int start := 0;
+ int index := 0;
+ int valueLen := value.Length;
+ int literalLen := self.Length;
+
+ while (index >= 0)
+ {
+ index := self.indexOf(start, value);
+ if (-1 != index)
+ {
+ list.append(self.Substring(start, index - start));
+ start := index + valueLen
+ }
+ else
+ {
+ list.append(self.Substring(start, literalLen - start))
+ }
+ };
+
+ ^ list
+ }
+
}
public extension wideListOp : WideString
@@ -137,6 +163,26 @@ public extension enumerableOp
^ nil
}
}
+
+ get LastMember()
+ {
+ auto en := cast Enumerator(self.enumerator());
+ object lastItem := nil;
+
+ while (en.next())
+ { lastItem := *en };
+
+ ^ lastItem
+ }
+
+ repeatTill(n)
+ = RangeEnumerator.new(self, n - 1, 1);
+
+ zipBy(enumerable, zipper)
+ = ZipEnumerator.new(zipper, cast Enumerator(self.enumerator()), cast Enumerator(enumerable.enumerator()));
+
+ zipForEach(enumerable, func2)
+ = self.zipBy(enumerable, func2).forEach:idleFunc1;
}
// --- indexableOp ---
@@ -203,4 +249,33 @@ public extension indexableOp
ascendant()
= self.clone().sort(ifOrdered);
+
+ sequenceReverse()
+ = self.sequenceReverse(0, self.Length);
+
+ sequenceReverse(int index, int counter)
+ {
+ Indexer it := self.indexer();
+
+ int i := index;
+ int j := counter;
+ j := j + i;
+ j := j - 1;
+
+ while (i < j)
+ {
+ it.Index := i;
+ var temp1 := *it;
+ it.Index := j;
+ var temp2 := *it;
+ it.Value := temp1;
+ it.Index := i;
+ it.Value := temp2;
+
+ i := i + 1;
+ j := j - 1
+ };
+
+ ^ self
+ }
}
\ No newline at end of file
diff --git a/src60/system/routines/patterns.l b/src60/system/routines/patterns.l
index 82998d3406..c531e77b2a 100644
--- a/src60/system/routines/patterns.l
+++ b/src60/system/routines/patterns.l
@@ -1,5 +1,7 @@
import system;
+idleFunc1 = (x){};
+
// --- Selecting ---
public class Selector : Enumerator
@@ -96,3 +98,93 @@ public class Filter : Enumerator
enumerable() => _enumerator;
}
+// --- RangeEnumerator ---
+
+public class RangeEnumerator : Enumerator
+{
+ object _variable;
+ object _start;
+ object _end;
+ object _step;
+
+ bool _forward;
+
+ constructor new(var,start,end,step)
+ {
+ _variable := var;
+ _start := start;
+ _end := end;
+ _step := step;
+
+ _forward := (start < end);
+
+ self.reset()
+ }
+
+ constructor new(start, end, step)
+ <= new(new Variable(), start, end, step);
+
+ constructor new(start, end)
+ <= new(new Variable(), start, end, 1);
+
+ reset()
+ {
+ _variable.Value := _start;
+
+ if(_forward)
+ {
+ _variable.reduce:_step
+ }
+ else
+ {
+ _variable.append:_step
+ }
+ }
+
+ get Value() = _variable.Value;
+
+ bool next()
+ {
+ if(_forward)
+ { _variable.append:_step; ^ (_variable <= _end) };
+
+ _variable.reduce:_step;
+
+ ^ (_variable >= _end)
+ }
+
+ enumerable() = _variable;
+}
+
+// --- ZipEnumerator ---
+
+public class ZipEnumerator : Enumerator
+{
+ Enumerator _enumerator1;
+ Enumerator _enumerator2;
+
+ Func2 _zipper;
+
+ constructor new(Func2 fn, Enumerator enum1, Enumerator enum2)
+ {
+ _zipper := fn;
+
+ _enumerator1 := enum1;
+ _enumerator2 := enum2;
+ }
+
+ constructor new(ExtensionMessage ext, Enumerator enum1, Enumerator enum2)
+ <= new((n,m => ext(n,m)), enum1, enum2);
+
+ get Value() = _zipper(_enumerator1.Value, _enumerator2.Value);
+
+ bool next() = _enumerator1.next() && _enumerator2.next();
+
+ reset()
+ {
+ _enumerator1.reset();
+ _enumerator2.reset();
+ }
+
+ enumerable() => _enumerator1;
+}
diff --git a/src60/system/strings.l b/src60/system/strings.l
index 27f3866a06..5ad5752110 100644
--- a/src60/system/strings.l
+++ b/src60/system/strings.l
@@ -166,6 +166,9 @@ public sealed nonstructural VariadicArray //: Indexable
private readArgLength(ref int retVal) : external(system'core_routines'__varg_readLength);
+ T at(int n)
+ = array[n];
+
int Length
{
get()
@@ -174,7 +177,37 @@ public sealed nonstructural VariadicArray //: Indexable
^ len
}
- }
+ }
+
+ Enumerator enumerator() = new BaseEnumerator
+ {
+ this index := -1;
+
+ this length := self.Length;
+
+ get T Value() = self.at(this index.Value);
+
+ enumerable() = self;
+
+ reset()
+ {
+ this index := -1
+ }
+ };
+
+ T[] cast()
+ {
+ int len := self.Length;
+
+ T[] copy := new T[](len);
+ for(int i := 0, i < len, i += 1)
+ {
+ copy[i] := array[i]
+ };
+
+ ^ copy
+ }
+
}
// --- String ---
@@ -266,7 +299,7 @@ public const struct String : BaseValue,
page := 256
};
- m := shortArrayConvertor.convert(buffer, 0, l, self.Substring(i,page));
+ m := shortArrayConvertor.convert(buffer, 0, page, self.Substring(i,page));
retVal := retVal.add(WideString.fromShortArray(0, m, buffer));
@@ -420,7 +453,7 @@ public const struct String : BaseValue,
string clone() = String.copy(self);
}
-public const string emptyString = String.MinValue;
+public const String emptyString = String.MinValue;
// --- StringEnumerator ---
@@ -632,7 +665,7 @@ public const struct WideString : BaseValue
page := 256
};
- m := byteArrayConvertor.convert(buffer, 0, l, self.Substring(i,page));
+ m := byteArrayConvertor.convert(buffer, 0, page, self.Substring(i,page));
retVal := retVal.add(String.fromByteArray(0, m, buffer));
@@ -694,7 +727,7 @@ public const struct WideString : BaseValue
};
int l2 := subs.Length;
- string retVal := WideString.allocate(l1 + l2);
+ wide retVal := WideString.allocate(l1 + l2);
self.copySubS(retVal, self, 0, l1);
self.copySubS(retVal, subs, l1, l2);
@@ -786,7 +819,7 @@ public const struct WideString : BaseValue
// --- emptyWideString ---
/// An empty wide literal value
-public const wide emptyWideString = WideString.MinValue;
+public const WideString emptyWideString = WideString.MinValue;
// --- WideStringEnumerator ---
diff --git a/src60/system/system.prj b/src60/system/system.prj
index 2ef2b4e5cf..10fcbb1403 100644
--- a/src60/system/system.prj
+++ b/src60/system/system.prj
@@ -74,5 +74,8 @@
threading\win32_handlers.l
threading\thread.l
+
+ dynamic\tape.l
+
\ No newline at end of file
diff --git a/src60/system/system.project b/src60/system/system.project
index ba977dcd92..2551101284 100644
--- a/src60/system/system.project
+++ b/src60/system/system.project
@@ -100,5 +100,8 @@
runtime/gc_routines.l
runtime/vectortable.l
+
+ dynamic/tape.l
+
\ No newline at end of file
diff --git a/src60/system/text/textbuffer.l b/src60/system/text/textbuffer.l
index 05ee67880e..e93ab2c3db 100644
--- a/src60/system/text/textbuffer.l
+++ b/src60/system/text/textbuffer.l
@@ -1,6 +1,6 @@
namespace text
{
- const int TextPageSize = 128;
+ const IntNumber TextPageSize = 128;
// --- TextBuffer ---
diff --git a/src60/system/text/win_encoding.l b/src60/system/text/win_encoding.l
index cd9e82a9b1..46c5f29ae3 100644
--- a/src60/system/text/win_encoding.l
+++ b/src60/system/text/win_encoding.l
@@ -1,6 +1,6 @@
namespace text
{
- const int MB_ERR_INVALID_CHARS = 00000008h;
+ const IntNumber MB_ERR_INVALID_CHARS = 00000008h;
// --- WinEncoder ---
public class WinEncoder : Encoder
diff --git a/src60/system/win_basic.l b/src60/system/win_basic.l
index 7703b5dcaf..6a92a585b2 100644
--- a/src60/system/win_basic.l
+++ b/src60/system/win_basic.l
@@ -21,6 +21,8 @@ public sealed const struct UnsafePointer
{
embeddable __ptr pointer;
+ private readIntPtr(ref int retVal) : external(system'core_routines'__readIntPtr);
+
bool isUnassigned()
{
^ pointer == 0;
@@ -44,6 +46,15 @@ public sealed const struct UnsafePointer
^ s
}
+
+ int cast()
+ {
+ self.readIntPtr(ref int retVal);
+
+ ^ retVal
+ }
+
+ copyTo(byte[] target, int len) : external(system'core_routines'__ptrCopyTo);
}
// --- CallStack ---
@@ -63,6 +74,14 @@ public sealed class CallStack
this stack := class Array.copy(stack, 0, length);
}
+ constructor(int trimingLevel)
+ {
+ pointer stack[64];
+ self.load(stack, 64, ref int length);
+
+ this stack := class Array.copy(stack, trimingLevel, length - trimingLevel);
+ }
+
string toPrintable()
: info("Generates the call stack literal representation")
{
diff --git a/src60/system/win_strings.l b/src60/system/win_strings.l
index 43f544aa4d..bb4003d613 100644
--- a/src60/system/win_strings.l
+++ b/src60/system/win_strings.l
@@ -1,2 +1,2 @@
-public const string newLineConstant
+public const String newLineConstant
= $13$10;
diff --git a/tests60/sandbox/sandbox.l b/tests60/sandbox/sandbox.l
index fc08a4287e..50375f3289 100644
--- a/tests60/sandbox/sandbox.l
+++ b/tests60/sandbox/sandbox.l
@@ -1,20 +1,11 @@
-import system'routines;
import extensions;
-
public program()
{
- var s:= "1234".toArray();
-
- var ch := s[0];
-
-// console.printLine(s[0] == ch);
- console.printLine(s[0].equalReference(ch));
+ uint k := 2H;
+ uint l := 0AH;
-// var duplicate := guess.seekEach:(x => (x == ch)&&(x.equalReference(ch).Inverted));
-// if (nil != duplicate)
-// {
-// InvalidArgumentException.raise()
-// };
+ var r := l < k;
+ Assert.ifTrue(r); // 2 > 10
}
\ No newline at end of file
diff --git a/tests60/system_tests/basic.l b/tests60/system_tests/basic.l
index 1301850c6b..e444c92c4f 100644
--- a/tests60/system_tests/basic.l
+++ b/tests60/system_tests/basic.l
@@ -4,34 +4,66 @@ import extensions;
intTests()
{
- console.write("intTests:");
+ console.write("intTests:");
- int n := 2;
- int m := 3;
- int k := 4;
+ int n := 2;
+ int m := 3;
+ int k := 4;
- Assert.ifTrue(2 + 3 * 4 == 14);
- Assert.ifTrue(n + m * k == 14);
- console.write(".");
- Assert.ifFalse(n == m);
- Assert.ifTrue(n == n);
- Assert.ifTrue(n < m);
- Assert.ifFalse(n > m);
- Assert.ifTrue(n <= m);
- Assert.ifTrue(n <= n);
- Assert.ifTrue(n >= n);
- Assert.ifFalse(n >= m);
- console.write(".");
+ Assert.ifTrue(2 + 3 * 4 == 14);
+ Assert.ifTrue(n + m * k == 14);
+ console.write(".");
+ Assert.ifFalse(n == m);
+ Assert.ifTrue(n == n);
+ Assert.ifTrue(n < m);
+ Assert.ifFalse(n > m);
+ Assert.ifTrue(n <= m);
+ Assert.ifTrue(n <= n);
+ Assert.ifTrue(n >= n);
+ Assert.ifFalse(n >= m);
+ console.write(".");
- int i := 1;
- i += 2;
- i -= 2;
- i *= 2;
- i /= 2;
- Assert.ifTrue(i == 1);
- console.writeLine(".");
+ int m2 := 10;
+ int k2 := -2;
+ int l2 := -10;
+
+ Assert.ifFalse(k2 > m2);
+ Assert.ifTrue(m2 > k2);
+ Assert.ifFalse(k2 < l2);
+ console.write(".");
+
+ int i := 1;
+ i += 2;
+ i -= 2;
+ i *= 2;
+ i /= 2;
+ Assert.ifTrue(i == 1);
+ console.writeLine(".");
}
+uintTests()
+{
+ console.write("uintTests:");
+
+ uint k := 2H;
+ uint l := 0AH;
+ uint m := 081000000H;
+ uint n := 08FFFFFFFH;
+
+ Assert.ifFalse(k > l); // 2 > 10
+ Assert.ifFalse(m < l); // 081000000H < 10
+ Assert.ifTrue(l < m); // 10 < 081000000H
+ Assert.ifTrue(n > m); // 08FFFFFFFH > 081000000H
+ console.write(".");
+
+ m := 80000000H;
+ n := 10H;
+ k := m / n;
+ Assert.ifTrue(k == 8000000H);
+ console.writeLine(".");
+}
+
+
// --- longTests ---
longTests()
@@ -166,6 +198,33 @@ stringTests()
var s3 := s + s2;
Assert.ifTrue(s3 == "abcde");
+ console.write(".");
+
+ Assert.ifTrue("s1" < "s2");
+ Assert.ifFalse("s2" < "s2");
+ Assert.ifFalse("s2" < "s1");
+
+ console.writeLine(".");
+}
+
+// --- wideTests ---
+wideTests()
+{
+ console.write("wideTests:");
+ wide s := "abc"w;
+
+ Assert.ifTrue(s == "abc"w);
+ console.write(".");
+ wide s2 := "de"w;
+ var s3 := s + s2;
+
+ Assert.ifTrue(s3 == "abcde"w);
+ console.write(".");
+
+ Assert.ifTrue("s1"w < "s2"w);
+ Assert.ifFalse("s2"w < "s2"w);
+ Assert.ifFalse("s2"w < "s1"w);
+
console.writeLine(".");
}
@@ -509,3 +568,63 @@ variadicTest()
strong.validate();
console.writeLine(".");
}
+
+
+// --- dynamicLoadTests ---
+
+public class DynamicallyLoadedClass
+{
+ constructor new() {}
+}
+
+dynamicLoadTests()
+{
+ console.write("dynamicLoadTests:");
+
+ var class := new ClassReference("system_tests'DynamicallyLoadedClass");
+
+ var o := class.new();
+
+ Assert.ifTrue(o.instanceOf(DynamicallyLoadedClass));
+
+ console.writeLine(".");
+}
+
+interface ITest
+{
+ abstract int Index
+ {
+ get();
+ }
+}
+
+class ATest
+{
+ int value;
+
+ constructor(int value)
+ {
+ this value := value
+ }
+
+ get int Index()
+ {
+ ^ value;
+ }
+
+ ITest cast() = new ITest { embeddable dispatch() => self; };
+}
+
+interfaceTests()
+{
+ console.write("interfaceTests:");
+
+ var a := new ATest(2);
+
+ ITest i := a;
+
+ int n := i.Index;
+ Assert.ifTrue(n == 2);
+
+ console.writeLine(".");
+}
diff --git a/tests60/system_tests/main.l b/tests60/system_tests/main.l
index 5d02c01a0b..a96595c1ed 100644
--- a/tests60/system_tests/main.l
+++ b/tests60/system_tests/main.l
@@ -3,6 +3,7 @@ public program()
console.writeLine("--- ELENA 6 API Unit Tests ---");
intTests();
+ uintTests();
longTests();
realTests();
gcTests();
@@ -10,11 +11,14 @@ public program()
boxingTests();
byRefTests();
stringTests();
+ wideTests();
shortTests();
conversionTests();
inlineAssignmentTests();
singleDispatchTest();
variadicTest();
+ dynamicLoadTests();
+ interfaceTests();
console.writeLine("--- Passed ---")
}
\ No newline at end of file