diff --git a/.github/workflows/msbuild.yml b/.github/workflows/msbuild.yml index e7f354031f..83ee851d11 100644 --- a/.github/workflows/msbuild.yml +++ b/.github/workflows/msbuild.yml @@ -35,10 +35,10 @@ jobs: platform: [x86, x64] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Add MSBuild to PATH - uses: microsoft/setup-msbuild@v1.0.2 + uses: microsoft/setup-msbuild@v2 - name: Setup Nuget uses: Nuget/setup-nuget@v1.0.5 diff --git a/CHANGELOG.md b/CHANGELOG.md index cdbebb0c05..f399f134e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,46 @@ +## ELENA 6.0.10 +*07.05.2024* + +- ELENA + - [ADDED] #646 : Calling own method directly without target + - [ADDED] #651 : Template Expression - typecasting + - [ADDED] #497 : a static method must have an access to private methods + +- ELC + - [FIXED] aarch64 : xstorefir opcode + - [FIXED] ppc64le : open opcode + - [ADDED] new option : auto-preloaded module extension ("-xm") + - [FIXED] reducing the total size of an executable by ignoring module extensions by default + - [FIXED] #401 - += operator with array + - [FIXED] #488 : Declaring auto struct variable + - [FIXED] #522 : single dispatch variadic message + - [FIXED] x86-64 : calling from external + - [FIXED] #608 : single dispatch for constructors + - [FIXED] #504 : Support an array operation with external function arguments + - [FIXED] #589 : Supporting ?: operator inside ?? + - [ADDED] #569 : Ignoring order of declaration + - [FIXED] xhookdpr for x86-64 mode + +- VM + - [ADDED] #635 : new entry point to invoke the functionality from another program + +- API + - [FIXED] toJson extension + - [FIXED] try statement does not allocate an exception + - [ADDED] extensions'io:ByteArrayReader,ByteArrayWriter + +- SAMPLES + - [ADDED] #635 : new tutorial to call an ELENA library from C++ / C# + - [ADDED] chat sample + +- Tools + - [ADDED] ecv-cli : adding a filter for listing members + - [FIXED]elt-cli : fixing support for extension methods + +- IDE + - [FIXED] watch : displaying stack-allocated classes + - [ADDED] syntax highlighting + ## ELENA 6.0.9 *19.04.2024* diff --git a/README.md b/README.md index 0c0780f7bb..701a26e2d0 100644 --- a/README.md +++ b/README.md @@ -55,25 +55,9 @@ The compiler code is implemented in C++ and does not require external dependenci You have to add a path to _BIN_ folder to the system environment *PATH* or copy elenavm.dll and elenart.dll to _Windows\System32_ folder. -To build the compiler under VS2019 you have to go to the root folder and type: +To build the compiler and API under VS2019 / VS2022 you have to go to the root folder and type: - recompile60.bat - -To build the ELENA libraries type the following command: - - rebuild_lib60.bat - -To build ELENA samples type the following command: - - rebuild_examples60.bat - -To build ELENA Rosetta-code samples type the following command: - - examples\rosetta\build.bat - -To run unit-tests type the following command: - - lib_tests.bat + recompile60.bat ## Source Code Organization diff --git a/VERSION b/VERSION index fb06ed73fa..c5a1e4c436 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -6.0.9 \ No newline at end of file +6.0.10 \ No newline at end of file diff --git a/asm/aarch64/core60.asm b/asm/aarch64/core60.asm index d86e77a39b..091ac705fa 100644 --- a/asm/aarch64/core60.asm +++ b/asm/aarch64/core60.asm @@ -3594,6 +3594,16 @@ inline %2F1h end +// ; xstoresir i, 0 +inline %5F1h + + mov x11, #0 + + add x12, sp, __arg12_1 + str x11, [x12] + +end + // ; xstoresir :0, 0 inline %6F1h @@ -3611,9 +3621,7 @@ end // ; xstoresir :n, -1 inline %8F1h - movz x11, __n16lo_1 - movk x11, __n16hi_1, lsl #16 - sxtw x11, w11 + mov x11, #-1 add x12, sp, __arg12_1 str x11, [x12] @@ -3623,22 +3631,14 @@ end // ; xstoresir :0, -1 inline %9F1h - movz x11, __n16lo_1 - movk x11, __n16hi_1, lsl #16 - sxtw x11, w11 - - mov x0, x11 + mov x0, #-1 end // ; xstoresir :1, -1 inline %0AF1h - movz x11, __n16lo_1 - movk x11, __n16hi_1, lsl #16 - sxtw x11, w11 - - mov x1, x11 + mov x1, #-1 end @@ -4054,10 +4054,42 @@ labEnd: end // ; xstorefir +// ; NOTE : it is presumed that arg1 < 0 (it is inverted in jitcompiler) inline %0F9h movz x11, __ptr32lo_2 movk x11, __ptr32hi_2, lsl #16 + sub x12, x29, -__arg12_1 + str x11, [x12] + +end + +// ; xstorefir +// ; NOTE : it is presumed that arg1 > 0 (it is inverted in jitcompiler) +inline %4F9h + + movz x11, __ptr32lo_2 + movk x11, __ptr32hi_2, lsl #16 + add x12, x29, __arg12_1 + str x11, [x12] + +end + +// ; xstorefir i, 0 +// ; NOTE : it is presumed that arg1 < 0 (it is inverted in jitcompiler) +inline %5F9h + + mov x11, #0 + sub x12, x29, -__arg12_1 + str x11, [x12] + +end + +// ; xstorefir i, 0 +// ; NOTE : it is presumed that arg1 > 0 (it is inverted in jitcompiler) +inline %9F9h + + mov x11, #0 add x12, x29, __arg12_1 str x11, [x12] diff --git a/asm/amd64/core60.asm b/asm/amd64/core60.asm index 62fc16f5cc..e15cc2f090 100644 --- a/asm/amd64/core60.asm +++ b/asm/amd64/core60.asm @@ -2021,7 +2021,15 @@ inline %0CAh add rsp, 24 pop rbp - + pop r15 + pop r14 + pop r13 + pop r12 + pop rbx + pop rdi + pop rsi + add rsp, 8 + end // ; extclosen 0 @@ -2032,6 +2040,14 @@ inline %1CAh add rsp, 24 pop rbp + pop r15 + pop r14 + pop r13 + pop r12 + pop rbx + pop rdi + pop rsi + add rsp, 8 end @@ -3015,6 +3031,15 @@ inline %0F2h mov [rsp+24], r8 mov [rsp+32], r9 + push 0 + push rsi + push rdi + push rbx + push r12 + push r13 + push r14 + push r15 + push rbp mov rax, [data : %CORE_SINGLE_CONTENT + tt_stack_frame] push rax @@ -3047,6 +3072,15 @@ inline %1F2h mov [rsp+24], r8 mov [rsp+32], r9 + push 0 + push rsi + push rdi + push rbx + push r12 + push r13 + push r14 + push r15 + push rbp mov rax, [data : %CORE_SINGLE_CONTENT + tt_stack_frame] push rax @@ -3075,6 +3109,15 @@ inline %2F2h mov [rsp+24], r8 mov [rsp+32], r9 + push 0 + push rsi + push rdi + push rbx + push r12 + push r13 + push r14 + push r15 + push rbp mov rax, [data : %CORE_SINGLE_CONTENT + tt_stack_frame] push rax @@ -3105,6 +3148,15 @@ inline %3F2h mov [rsp+24], r8 mov [rsp+32], r9 + push 0 + push rsi + push rdi + push rbx + push r12 + push r13 + push r14 + push r15 + push rbp mov rax, [data : %CORE_SINGLE_CONTENT + tt_stack_frame] push rax @@ -3135,6 +3187,15 @@ inline %4F2h mov [rsp+24], r8 mov [rsp+32], r9 + push 0 + push rsi + push rdi + push rbx + push r12 + push r13 + push r14 + push r15 + push rbp mov rax, [data : %CORE_SINGLE_CONTENT + tt_stack_frame] push rax @@ -3167,6 +3228,15 @@ inline %5F2h mov [rsp+24], r8 mov [rsp+32], r9 + push 0 + push rsi + push rdi + push rbx + push r12 + push r13 + push r14 + push r15 + push rbp mov rax, [data : %CORE_SINGLE_CONTENT + tt_stack_frame] push rax @@ -3199,6 +3269,15 @@ inline %6F2h mov [rsp+24], r8 mov [rsp+32], r9 + push 0 + push rsi + push rdi + push rbx + push r12 + push r13 + push r14 + push r15 + push rbp mov rax, [data : %CORE_SINGLE_CONTENT + tt_stack_frame] push rax @@ -3227,6 +3306,15 @@ inline %7F2h mov [rsp+24], r8 mov [rsp+32], r9 + push 0 + push rsi + push rdi + push rbx + push r12 + push r13 + push r14 + push r15 + push rbp mov rax, [data : %CORE_SINGLE_CONTENT + tt_stack_frame] push rax @@ -3250,6 +3338,15 @@ inline %8F2h mov [rsp+24], r8 mov [rsp+32], r9 + push 0 + push rsi + push rdi + push rbx + push r12 + push r13 + push r14 + push r15 + push rbp mov rax, [data : %CORE_SINGLE_CONTENT + tt_stack_frame] push rax @@ -3275,6 +3372,15 @@ inline %9F2h mov [rsp+24], r8 mov [rsp+32], r9 + push 0 + push rsi + push rdi + push rbx + push r12 + push r13 + push r14 + push r15 + push rbp mov rax, [data : %CORE_SINGLE_CONTENT + tt_stack_frame] push rax @@ -3301,6 +3407,15 @@ inline %0AF2h mov [rsp+24], r8 mov [rsp+32], r9 + push 0 + push rsi + push rdi + push rbx + push r12 + push r13 + push r14 + push r15 + push rbp mov rax, [data : %CORE_SINGLE_CONTENT + tt_stack_frame] push rax @@ -3329,6 +3444,15 @@ inline %0BF2h mov [rsp+24], r8 mov [rsp+32], r9 + push 0 + push rsi + push rdi + push rbx + push r12 + push r13 + push r14 + push r15 + push rbp mov rax, [data : %CORE_SINGLE_CONTENT + tt_stack_frame] push rax diff --git a/asm/ppc64le/core60.asm b/asm/ppc64le/core60.asm index c2f724c9bc..ae9eebdd0e 100644 --- a/asm/ppc64le/core60.asm +++ b/asm/ppc64le/core60.asm @@ -3236,10 +3236,11 @@ end inline %0F0h mflr r0 + std r31, -10h(r1) // ; save frame pointer std r0, -08h(r1) // ; save return address - addi r1, r1, -16 // ; allocate raw stack + mr r31, r1 // ; set frame pointer addi r1, r1, -__n16_2 // ; allocate raw stack @@ -3267,80 +3268,132 @@ labEnd: end -// ; openin 0, 0 +// ; openin 0, n inline %1F0h mflr r0 + std r31, -10h(r1) // ; save frame pointer std r0, -08h(r1) // ; save return address + addi r1, r1, -16 // ; allocate raw stack + + mr r31, r1 // ; set frame pointer + + addi r1, r1, -__n16_2 // ; allocate raw stack + li r16, 0 + std r31, -08h(r1) // ; save frame pointer + std r16, -10h(r1) // ; save dummy addi r1, r1, -10h // ; allocate stack mr r31, r1 // ; set frame pointer end -// ; openin 1, 0 +// ; openin 1, n inline %2F0h mflr r0 + std r31, -10h(r1) // ; save frame pointer - li r16, 0 std r0, -08h(r1) // ; save return address - addi r31, r1, -10h // ; set frame pointer - std r16, -18h(r1) // ; save return address - std r16, -20h(r1) // ; save return address + addi r1, r1, -16 // ; allocate raw stack - addi r1, r1, -20h // ; allocate stack + mr r31, r1 // ; set frame pointer + + addi r1, r1, -__n16_2 // ; allocate raw stack + + li r16, 0 + std r31, -08h(r1) // ; save frame pointer + std r16, -10h(r1) // ; save dummy + addi r1, r1, -10h // ; allocate stack + mr r31, r1 // ; set frame pointer + + std r16, -08h(r1) // ; save frame pointer + std r16, -10h(r1) // ; save frame pointer + addi r1, r1, -10h // ; allocate stack end -// ; openin 2, 0 +// ; openin 2, n inline %3F0h mflr r0 + std r31, -10h(r1) // ; save frame pointer - li r16, 0 std r0, -08h(r1) // ; save return address - addi r31, r1, -10h // ; set frame pointer - std r16, -18h(r1) // ; save return address - std r16, -20h(r1) // ; save return address + addi r1, r1, -16 // ; allocate raw stack - addi r1, r1, -20h // ; allocate stack + mr r31, r1 // ; set frame pointer + + addi r1, r1, -__n16_2 // ; allocate raw stack + + li r16, 0 + std r31, -08h(r1) // ; save frame pointer + std r16, -10h(r1) // ; save dummy + addi r1, r1, -10h // ; allocate stack + mr r31, r1 // ; set frame pointer + + std r16, -08h(r1) // ; save frame pointer + std r16, -10h(r1) // ; save frame pointer + addi r1, r1, -10h // ; allocate stack end -// ; openin 3, 0 +// ; openin 3, n inline %4F0h mflr r0 + std r31, -10h(r1) // ; save frame pointer - li r16, 0 std r0, -08h(r1) // ; save return address - addi r31, r1, -10h // ; set frame pointer - std r16, -18h(r1) // ; save return address - std r16, -20h(r1) // ; save return address - std r16, -28h(r1) // ; save return address - std r16, -30h(r1) // ; save return address + addi r1, r1, -16 // ; allocate raw stack - addi r1, r1, -30h // ; allocate stack + mr r31, r1 // ; set frame pointer + + addi r1, r1, -__n16_2 // ; allocate raw stack + + li r16, 0 + std r31, -08h(r1) // ; save frame pointer + std r16, -10h(r1) // ; save dummy + addi r1, r1, -10h // ; allocate stack + mr r31, r1 // ; set frame pointer + + std r16, -08h(r1) // ; save frame pointer + std r16, -10h(r1) // ; save frame pointer + addi r1, r1, -10h // ; allocate stack + + std r16, -08h(r1) // ; save frame pointer + std r16, -10h(r1) // ; save frame pointer + addi r1, r1, -10h // ; allocate stack end -// ; openin 0, n +// ; openin 4, n inline %5F0h mflr r0 + std r31, -10h(r1) // ; save frame pointer std r0, -08h(r1) // ; save return address + addi r1, r1, -16 // ; allocate raw stack mr r31, r1 // ; set frame pointer + addi r1, r1, -__n16_2 // ; allocate raw stack li r16, 0 - std r31, -10h(r1) // ; save frame pointer - std r0, -08h(r16) // ; save dummy + std r31, -08h(r1) // ; save frame pointer + std r16, -10h(r1) // ; save dummy + addi r1, r1, -10h // ; allocate stack + mr r31, r1 // ; set frame pointer - addi r1, r1, -10h // ; allocate stack + std r16, -08h(r1) // ; save frame pointer + std r16, -10h(r1) // ; save frame pointer + addi r1, r1, -10h // ; allocate stack + + std r16, -08h(r1) // ; save frame pointer + std r16, -10h(r1) // ; save frame pointer + addi r1, r1, -10h // ; allocate stack end @@ -3371,6 +3424,81 @@ labEnd: end +// ; openin 0, 0 +inline %7F0h + + mflr r0 + std r31, -10h(r1) // ; save frame pointer + std r0, -08h(r1) // ; save return address + + addi r1, r1, -10h // ; allocate stack + mr r31, r1 // ; set frame pointer + +end + +// ; openin 1, 0 +inline %8F0h + + mflr r0 + std r31, -10h(r1) // ; save frame pointer + li r16, 0 + std r0, -08h(r1) // ; save return address + addi r31, r1, -10h // ; set frame pointer + std r16, -18h(r1) // ; save return address + std r16, -20h(r1) // ; save return address + + addi r1, r1, -20h // ; allocate stack + +end + +// ; openin 2, 0 +inline %9F0h + + mflr r0 + std r31, -10h(r1) // ; save frame pointer + li r16, 0 + std r0, -08h(r1) // ; save return address + addi r31, r1, -10h // ; set frame pointer + std r16, -18h(r1) // ; save return address + std r16, -20h(r1) // ; save return address + + addi r1, r1, -20h // ; allocate stack + +end + +// ; openin 3, 0 +inline %0AF0h + + mflr r0 + std r31, -10h(r1) // ; save frame pointer + li r16, 0 + std r0, -08h(r1) // ; save return address + addi r31, r1, -10h // ; set frame pointer + std r16, -18h(r1) // ; save return address + std r16, -20h(r1) // ; save return address + std r16, -28h(r1) // ; save return address + std r16, -30h(r1) // ; save return address + + addi r1, r1, -30h // ; allocate stack +end + +// ; openin 4, 0 +inline %0BF0h + + mflr r0 + std r31, -10h(r1) // ; save frame pointer + li r16, 0 + std r0, -08h(r1) // ; save return address + addi r31, r1, -10h // ; set frame pointer + std r16, -18h(r1) // ; save return address + std r16, -20h(r1) // ; save return address + std r16, -28h(r1) // ; save return address + std r16, -30h(r1) // ; save return address + + addi r1, r1, -30h // ; allocate stack + +end + // ; xstoresir inline %0F1h diff --git a/asm/x32/core60.asm b/asm/x32/core60.asm index 6ce0f210f7..90df1b26dc 100644 --- a/asm/x32/core60.asm +++ b/asm/x32/core60.asm @@ -3888,6 +3888,7 @@ labNextBaseClass: jnz labNextOverloadlist pop ebx + add esp, 8 mov esi, [esp+4] // ; restore arg0 mov edx, __arg32_1 diff --git a/bin/elt60.es b/bin/elt60.es index aa6de97eaf..fd15f2a267 100644 --- a/bin/elt60.es +++ b/bin/elt60.es @@ -1,7 +1,7 @@ [[ #grammar vmbuild #config vm_client - #set preloaded preloadedSymbols + #set preloaded "system@preloadedSymbols" #postfix " ^ ""safeEval[1]"" " diff --git a/bin/scripts/grammar60.es b/bin/scripts/grammar60.es index 3cbedd864b..74fb318083 100644 --- a/bin/scripts/grammar60.es +++ b/bin/scripts/grammar60.es @@ -144,6 +144,7 @@ #define expression ::= "message_operation" "(" call_expression ")"; #define expression ::= "property_operation" "(" prop_expression ")"; #define expression ::= "add_operation" "(" add_expression ")"; + #define expression ::= "sub_operation" "(" sub_expression ")"; #define expression ::= "mul_operation" "(" mul_expression ")"; #define expression ::= "div_operation" "(" div_expression ")"; #define expression ::= "equal_operation" "(" equal_expression ")"; @@ -245,6 +246,18 @@ #define add_operation ::= <= "add" => expression; + #define sub_expression ::= +<= + system'dynamic'expressions'MessageCallExpression ( +=> + expression sub_operation +<= + ) +=>; + + #define sub_operation ::= + <= "subtract" => expression; + #define mul_expression ::= <= system'dynamic'expressions'MessageCallExpression ( diff --git a/bin/scripts/lscript60.es b/bin/scripts/lscript60.es index 72d07a3f1f..aec2248df4 100644 --- a/bin/scripts/lscript60.es +++ b/bin/scripts/lscript60.es @@ -160,6 +160,7 @@ #define l3_operation ::= ^ <= div_operation ( => "/" l2_expression <= ) =>; #define l4_operation ::= ^ <= add_operation ( => "+" l3_expression <= ) =>; + #define l4_operation ::= ^ <= sub_operation ( => "-" l3_expression <= ) =>; #define l5_operation ::= ^ <= equal_operation ( => "==" l4_expression <= ) =>; #define l5_operation ::= ^ <= less_operation ( => "<" l4_expression <= ) =>; diff --git a/bin/templates/lib60.cfg b/bin/templates/lib60.cfg index e22db3aa39..2407654c81 100644 --- a/bin/templates/lib60.cfg +++ b/bin/templates/lib60.cfg @@ -51,7 +51,5 @@ system'BaseLazyExpression system'Nullable#1 system'UnsafePointer - meta$preloadedSymbols - meta$preloadedSymbols \ No newline at end of file diff --git a/bin/templates/vm_win_console60.cfg b/bin/templates/vm_win_console60.cfg index e8fb7a0616..11f1fd761b 100644 --- a/bin/templates/vm_win_console60.cfg +++ b/bin/templates/vm_win_console60.cfg @@ -1,18 +1,10 @@ - - ..\x32\core60.bin - ..\x32\core60_win.bin - elenavm60 - - ..\amd64\core60.bin - ..\amd64\core60_win.bin - elenavm60_64 @@ -25,7 +17,7 @@ system'core_routines'vm_sta_start - $rootnamespace'program system'$private'entrySymbol + $rootnamespace'program \ No newline at end of file diff --git a/build/aarch64/build_package_arm64.script b/build/aarch64/build_package_arm64.script index 053c1e0904..48306bda60 100755 --- a/build/aarch64/build_package_arm64.script +++ b/build/aarch64/build_package_arm64.script @@ -1,5 +1,5 @@ #!/bin/bash -RELEASE=elena-6.0.9.aarch64-linux +RELEASE=elena-6.0.10.aarch64-linux mkdir -p /usr/share/elena mkdir -p /etc/elena/ @@ -161,21 +161,21 @@ fi mkdir -p ./$RELEASE/usr/bin/ mkdir -p ./$RELEASE/usr/elena-lang - mkdir -p ./$RELEASE/usr/elena-lang/examples/console/helloworld/ - mkdir -p ./$RELEASE/usr/elena-lang/examples/console/sum/ - mkdir -p ./$RELEASE/usr/elena-lang/examples/console/words/ - - mkdir -p ./$RELEASE/usr/elena-lang/examples/rosetta/accumulator/ - mkdir -p ./$RELEASE/usr/elena-lang/examples/rosetta/ackermann/ - mkdir -p ./$RELEASE/usr/elena-lang/examples/rosetta/addfield/ - mkdir -p ./$RELEASE/usr/elena-lang/examples/rosetta/anonymrec/ - mkdir -p ./$RELEASE/usr/elena-lang/examples/rosetta/aplusb/ - mkdir -p ./$RELEASE/usr/elena-lang/examples/rosetta/applycallback/ - mkdir -p ./$RELEASE/usr/elena-lang/examples/rosetta/arithmeticint/ - mkdir -p ./$RELEASE/usr/elena-lang/examples/rosetta/arithmeval/ - mkdir -p ./$RELEASE/usr/elena-lang/examples/rosetta/arithmmean/ - mkdir -p ./$RELEASE/usr/elena-lang/examples/rosetta/arrayconcat/ - mkdir -p ./$RELEASE/usr/elena-lang/examples/rosetta/arraymode/ + mkdir -p ./$RELEASE/usr/elena-lang/examples60/console/helloworld/ + mkdir -p ./$RELEASE/usr/elena-lang/examples60/console/sum/ + mkdir -p ./$RELEASE/usr/elena-lang/examples60/console/words/ + + mkdir -p ./$RELEASE/usr/elena-lang/examples60/rosetta/accumulator/ + mkdir -p ./$RELEASE/usr/elena-lang/examples60/rosetta/ackermann/ + mkdir -p ./$RELEASE/usr/elena-lang/examples60/rosetta/addfield/ + mkdir -p ./$RELEASE/usr/elena-lang/examples60/rosetta/anonymrec/ + mkdir -p ./$RELEASE/usr/elena-lang/examples60/rosetta/aplusb/ + mkdir -p ./$RELEASE/usr/elena-lang/examples60/rosetta/applycallback/ + mkdir -p ./$RELEASE/usr/elena-lang/examples60/rosetta/arithmeticint/ + mkdir -p ./$RELEASE/usr/elena-lang/examples60/rosetta/arithmeval/ + mkdir -p ./$RELEASE/usr/elena-lang/examples60/rosetta/arithmmean/ + mkdir -p ./$RELEASE/usr/elena-lang/examples60/rosetta/arrayconcat/ + mkdir -p ./$RELEASE/usr/elena-lang/examples60/rosetta/arraymode/ echo copying configuration @@ -201,7 +201,7 @@ fi cp /usr/lib/elena/lib60_64/*.* ./$RELEASE/usr/lib/elena/lib60_64/ - cp -r ../../examples $RELEASE/usr/elena-lang + cp -r ../../examples60 $RELEASE/usr/elena-lang cp -r ../../src60 $RELEASE/usr/elena-lang mkdir ./$RELEASE/DEBIAN diff --git a/build/aarch64/control b/build/aarch64/control index dbefcb3128..5e44b3d3e5 100644 --- a/build/aarch64/control +++ b/build/aarch64/control @@ -1,5 +1,5 @@ Package: elena-lang -Version: 6.0.9 +Version: 6.0.10 Architecture: aarch64 Maintainer: Alex Rakov Depends: libc6 (>= 2.1) diff --git a/build/amd64/build_package_amd64.script b/build/amd64/build_package_amd64.script index fdcf518a30..306d5497ab 100755 --- a/build/amd64/build_package_amd64.script +++ b/build/amd64/build_package_amd64.script @@ -1,5 +1,5 @@ #!/bin/bash -RELEASE=elena-6.0.9.amd64-linux +RELEASE=elena-6.0.10.amd64-linux mkdir -p /usr/share/elena mkdir -p /etc/elena/ @@ -173,21 +173,21 @@ fi mkdir -p ./$RELEASE/usr/bin/ mkdir -p ./$RELEASE/usr/elena-lang - mkdir -p ./$RELEASE/usr/elena-lang/examples/console/helloworld/ - mkdir -p ./$RELEASE/usr/elena-lang/examples/console/sum/ - mkdir -p ./$RELEASE/usr/elena-lang/examples/console/words/ - - mkdir -p ./$RELEASE/usr/elena-lang/examples/rosetta/accumulator/ - mkdir -p ./$RELEASE/usr/elena-lang/examples/rosetta/ackermann/ - mkdir -p ./$RELEASE/usr/elena-lang/examples/rosetta/addfield/ - mkdir -p ./$RELEASE/usr/elena-lang/examples/rosetta/anonymrec/ - mkdir -p ./$RELEASE/usr/elena-lang/examples/rosetta/aplusb/ - mkdir -p ./$RELEASE/usr/elena-lang/examples/rosetta/applycallback/ - mkdir -p ./$RELEASE/usr/elena-lang/examples/rosetta/arithmeticint/ - mkdir -p ./$RELEASE/usr/elena-lang/examples/rosetta/arithmeval/ - mkdir -p ./$RELEASE/usr/elena-lang/examples/rosetta/arithmmean/ - mkdir -p ./$RELEASE/usr/elena-lang/examples/rosetta/arrayconcat/ - mkdir -p ./$RELEASE/usr/elena-lang/examples/rosetta/arraymode/ + mkdir -p ./$RELEASE/usr/elena-lang/examples60/console/helloworld/ + mkdir -p ./$RELEASE/usr/elena-lang/examples60/console/sum/ + mkdir -p ./$RELEASE/usr/elena-lang/examples60/console/words/ + + mkdir -p ./$RELEASE/usr/elena-lang/examples60/rosetta/accumulator/ + mkdir -p ./$RELEASE/usr/elena-lang/examples60/rosetta/ackermann/ + mkdir -p ./$RELEASE/usr/elena-lang/examples60/rosetta/addfield/ + mkdir -p ./$RELEASE/usr/elena-lang/examples60/rosetta/anonymrec/ + mkdir -p ./$RELEASE/usr/elena-lang/examples60/rosetta/aplusb/ + mkdir -p ./$RELEASE/usr/elena-lang/examples60/rosetta/applycallback/ + mkdir -p ./$RELEASE/usr/elena-lang/examples60/rosetta/arithmeticint/ + mkdir -p ./$RELEASE/usr/elena-lang/examples60/rosetta/arithmeval/ + mkdir -p ./$RELEASE/usr/elena-lang/examples60/rosetta/arithmmean/ + mkdir -p ./$RELEASE/usr/elena-lang/examples60/rosetta/arrayconcat/ + mkdir -p ./$RELEASE/usr/elena-lang/examples60/rosetta/arraymode/ echo copying configuration @@ -213,7 +213,7 @@ fi cp /usr/lib/elena/lib60_64/*.* ./$RELEASE/usr/lib/elena/lib60_64/ - cp -r ../../examples $RELEASE/usr/elena-lang + cp -r ../../examples60 $RELEASE/usr/elena-lang cp -r ../../src60 $RELEASE/usr/elena-lang mkdir ./$RELEASE/DEBIAN diff --git a/build/amd64/control b/build/amd64/control index 46232edc74..be7a3c4175 100644 --- a/build/amd64/control +++ b/build/amd64/control @@ -1,5 +1,5 @@ Package: elena-lang -Version: 6.0.9 +Version: 6.0.10 Architecture: amd64 Maintainer: Alex Rakov Depends: libc6 (>= 2.1) diff --git a/build/elena_inno.iss b/build/elena_inno.iss index 7deb21bea4..cfeac38450 100644 --- a/build/elena_inno.iss +++ b/build/elena_inno.iss @@ -7,8 +7,8 @@ ; (To generate a new GUID, click Tools | Generate GUID inside the IDE.) AppId={{3CAA69D3-0F98-44B1-A73E-E864BA51D5BD} AppName=ELENA Programming Language -AppVersion=6.0.9 -;AppVerName=ELENA Programming Language 5.0.0 +AppVersion=6.0.10 +;AppVerName=ELENA Programming Language 6.0.10 AppPublisher=Alexey Rakov AppPublisherURL=http://github.com/ELENA-LANG/elena-lang AppSupportURL=http://github.com/ELENA-LANG/elena-lang @@ -18,7 +18,7 @@ DefaultGroupName=ELENA Programming Language AllowNoIcons=yes LicenseFile=..\doc\license InfoAfterFile=..\CHANGELOG.md -OutputBaseFilename=elena-lang-6.0.9.x86-setup +OutputBaseFilename=elena-lang-6.0.10.x86-setup Compression=lzma SolidCompression=yes ChangesEnvironment=yes diff --git a/build/i386/build_package_i386.script b/build/i386/build_package_i386.script index 251767181c..6e6c38857f 100755 --- a/build/i386/build_package_i386.script +++ b/build/i386/build_package_i386.script @@ -1,5 +1,5 @@ #!/bin/bash -RELEASE=elena-6.0.9.i386-linux +RELEASE=elena-6.0.10.i386-linux mkdir -p /usr/share/elena mkdir -p /etc/elena/ @@ -173,21 +173,17 @@ echo compiling lib60 files mkdir -p ./$RELEASE/usr/bin/ mkdir -p ./$RELEASE/usr/elena-lang - mkdir -p ./$RELEASE/usr/elena-lang/examples/console/helloworld/ - mkdir -p ./$RELEASE/usr/elena-lang/examples/console/sum/ - mkdir -p ./$RELEASE/usr/elena-lang/examples/console/words/ - - mkdir -p ./$RELEASE/usr/elena-lang/examples/rosetta/accumulator/ - mkdir -p ./$RELEASE/usr/elena-lang/examples/rosetta/ackermann/ - mkdir -p ./$RELEASE/usr/elena-lang/examples/rosetta/addfield/ - mkdir -p ./$RELEASE/usr/elena-lang/examples/rosetta/anonymrec/ - mkdir -p ./$RELEASE/usr/elena-lang/examples/rosetta/aplusb/ - mkdir -p ./$RELEASE/usr/elena-lang/examples/rosetta/applycallback/ - mkdir -p ./$RELEASE/usr/elena-lang/examples/rosetta/arithmeticint/ - mkdir -p ./$RELEASE/usr/elena-lang/examples/rosetta/arithmeval/ - mkdir -p ./$RELEASE/usr/elena-lang/examples/rosetta/arithmmean/ - mkdir -p ./$RELEASE/usr/elena-lang/examples/rosetta/arrayconcat/ - mkdir -p ./$RELEASE/usr/elena-lang/examples/rosetta/arraymode/ + mkdir -p ./$RELEASE/usr/elena-lang/examples60/rosetta/accumulator/ + mkdir -p ./$RELEASE/usr/elena-lang/examples60/rosetta/ackermann/ + mkdir -p ./$RELEASE/usr/elena-lang/examples60/rosetta/addfield/ + mkdir -p ./$RELEASE/usr/elena-lang/examples60/rosetta/anonymrec/ + mkdir -p ./$RELEASE/usr/elena-lang/examples60/rosetta/aplusb/ + mkdir -p ./$RELEASE/usr/elena-lang/examples60/rosetta/applycallback/ + mkdir -p ./$RELEASE/usr/elena-lang/examples60/rosetta/arithmeticint/ + mkdir -p ./$RELEASE/usr/elena-lang/examples60/rosetta/arithmeval/ + mkdir -p ./$RELEASE/usr/elena-lang/examples60/rosetta/arithmmean/ + mkdir -p ./$RELEASE/usr/elena-lang/examples60/rosetta/arrayconcat/ + mkdir -p ./$RELEASE/usr/elena-lang/examples60/rosetta/arraymode/ echo copying configuration @@ -213,7 +209,7 @@ echo compiling lib60 files cp /usr/lib/elena/lib60/*.* ./$RELEASE/usr/lib/elena/lib60/ - cp -r ../../examples $RELEASE/usr/elena-lang + cp -r ../../examples60 $RELEASE/usr/elena-lang cp -r ../../src60 $RELEASE/usr/elena-lang mkdir ./$RELEASE/DEBIAN diff --git a/build/i386/control b/build/i386/control index 193babd676..c19e19d45a 100644 --- a/build/i386/control +++ b/build/i386/control @@ -1,5 +1,5 @@ Package: elena-lang -Version: 6.0.9 +Version: 6.0.10 Architecture: i386 Maintainer: Alex Rakov Depends: libc6 (>= 2.1) diff --git a/build/ppc64le/build_package_ppc64le.script b/build/ppc64le/build_package_ppc64le.script index c92ba7560d..bcd49a0d64 100755 --- a/build/ppc64le/build_package_ppc64le.script +++ b/build/ppc64le/build_package_ppc64le.script @@ -1,5 +1,5 @@ #!/bin/bash -RELEASE=elena-6.0.9.ppc64le-linux +RELEASE=elena-6.0.10.ppc64le-linux mkdir -p /usr/share/elena mkdir -p /etc/elena/ @@ -161,21 +161,21 @@ fi mkdir -p ./$RELEASE/usr/bin/ mkdir -p ./$RELEASE/usr/elena-lang - mkdir -p ./$RELEASE/usr/elena-lang/examples/console/helloworld/ - mkdir -p ./$RELEASE/usr/elena-lang/examples/console/sum/ - mkdir -p ./$RELEASE/usr/elena-lang/examples/console/words/ - - mkdir -p ./$RELEASE/usr/elena-lang/examples/rosetta/accumulator/ - mkdir -p ./$RELEASE/usr/elena-lang/examples/rosetta/ackermann/ - mkdir -p ./$RELEASE/usr/elena-lang/examples/rosetta/addfield/ - mkdir -p ./$RELEASE/usr/elena-lang/examples/rosetta/anonymrec/ - mkdir -p ./$RELEASE/usr/elena-lang/examples/rosetta/aplusb/ - mkdir -p ./$RELEASE/usr/elena-lang/examples/rosetta/applycallback/ - mkdir -p ./$RELEASE/usr/elena-lang/examples/rosetta/arithmeticint/ - mkdir -p ./$RELEASE/usr/elena-lang/examples/rosetta/arithmeval/ - mkdir -p ./$RELEASE/usr/elena-lang/examples/rosetta/arithmmean/ - mkdir -p ./$RELEASE/usr/elena-lang/examples/rosetta/arrayconcat/ - mkdir -p ./$RELEASE/usr/elena-lang/examples/rosetta/arraymode/ + mkdir -p ./$RELEASE/usr/elena-lang/examples60/console/helloworld/ + mkdir -p ./$RELEASE/usr/elena-lang/examples60/console/sum/ + mkdir -p ./$RELEASE/usr/elena-lang/examples60/console/words/ + + mkdir -p ./$RELEASE/usr/elena-lang/examples60/rosetta/accumulator/ + mkdir -p ./$RELEASE/usr/elena-lang/examples60/rosetta/ackermann/ + mkdir -p ./$RELEASE/usr/elena-lang/examples60/rosetta/addfield/ + mkdir -p ./$RELEASE/usr/elena-lang/examples60/rosetta/anonymrec/ + mkdir -p ./$RELEASE/usr/elena-lang/examples60/rosetta/aplusb/ + mkdir -p ./$RELEASE/usr/elena-lang/examples60/rosetta/applycallback/ + mkdir -p ./$RELEASE/usr/elena-lang/examples60/rosetta/arithmeticint/ + mkdir -p ./$RELEASE/usr/elena-lang/examples60/rosetta/arithmeval/ + mkdir -p ./$RELEASE/usr/elena-lang/examples60/rosetta/arithmmean/ + mkdir -p ./$RELEASE/usr/elena-lang/examples60/rosetta/arrayconcat/ + mkdir -p ./$RELEASE/usr/elena-lang/examples60/rosetta/arraymode/ echo copying configuration @@ -201,7 +201,7 @@ fi cp /usr/lib/elena/lib60_64/*.* ./$RELEASE/usr/lib/elena/lib60_64/ - cp -r ../../examples $RELEASE/usr/elena-lang + cp -r ../../examples60 $RELEASE/usr/elena-lang cp -r ../../src60 $RELEASE/usr/elena-lang mkdir ./$RELEASE/DEBIAN diff --git a/build/ppc64le/control b/build/ppc64le/control index 64dcb0917b..c029b9d762 100644 --- a/build/ppc64le/control +++ b/build/ppc64le/control @@ -1,5 +1,5 @@ Package: elena-lang -Version: 6.0.9 +Version: 6.0.10 Architecture: ppc64le Maintainer: Alex Rakov Depends: libc6 (>= 2.1) diff --git a/build/rebuild_lib60_x86.bat b/build/rebuild_lib60_x86.bat index 828617b3f2..84fcaab094 100644 --- a/build/rebuild_lib60_x86.bat +++ b/build/rebuild_lib60_x86.bat @@ -94,14 +94,20 @@ bin\ldoc system'routines doc\api bin\ldoc system'runtime doc\api bin\ldoc system'threading doc\api bin\ldoc system'dynamic doc\api +bin\ldoc system'drawing doc\api bin\ldoc system'winforms doc\api +bin\ldoc system'net doc\api bin\ldoc extensions doc\api bin\ldoc extensions'routines doc\api bin\ldoc extensions'scripting doc\api +bin\ldoc extensions'dynamic doc\api +bin\ldoc extensions'io doc\api bin\ldoc cellular doc\api bin\ldoc algorithms doc\api bin\ldoc sqlite doc\api bin\ldoc forms doc\api +bin\ldoc ltests doc\api +bin\ldoc net doc\api bin\elena-cli tests60\system_tests\system_tests.prj @echo off diff --git a/dat/api2html/api2html.bat b/dat/api2html/api2html.bat index 9291b1bb94..fe4be5ce30 100644 --- a/dat/api2html/api2html.bat +++ b/dat/api2html/api2html.bat @@ -1,7 +1,7 @@ ..\..\bin\ldoc system ..\..\bin\ldoc system'routines +..\..\bin\ldoc system'routines'stex ..\..\bin\ldoc system'runtime -..\..\bin\ldoc system'runtime'stex ..\..\bin\ldoc system'threading ..\..\bin\ldoc system'dynamic ..\..\bin\ldoc system'drawing @@ -11,6 +11,7 @@ ..\..\bin\ldoc extensions'routines ..\..\bin\ldoc extensions'scripting ..\..\bin\ldoc extensions'dynamic +..\..\bin\ldoc extensions'io ..\..\bin\ldoc cellular ..\..\bin\ldoc algorithms ..\..\bin\ldoc sqlite diff --git a/dat/og/bt_rules60.txt b/dat/og/bt_rules60.txt index f7a3fde8cc..64d8db7c5e 100644 --- a/dat/og/bt_rules60.txt +++ b/dat/og/bt_rules60.txt @@ -11,6 +11,7 @@ local_address, saving_stack, local_address, conversion_op, local_address, copyin create_struct =4, assigning, local_address, saving_stack =0, local, copying_to_acc => 6; intcondop, assigning, local, branchop => 7; realcondop, assigning, local, branchop => 7; +nilcondop, assigning, local, branchop => 7; int_real_op, local_address, copying => 10; real_int_op, local_address, copying => 10; direct_call_op, inplacemark, copying => 12; diff --git a/dat/sg/syntax60.txt b/dat/sg/syntax60.txt index 1779e71568..3bed66c20b 100644 --- a/dat/sg/syntax60.txt +++ b/dat/sg/syntax60.txt @@ -81,6 +81,7 @@ __define YIELD_OPERATION 6248; __define REFER_OPERATION 6251; __define INC_OPERATION 6252; __define DEC_OPERATION 6253; +__define TEMPLATE_EXPR_BLOCK 6304; __define MESSAGE_OPERATION 6337; __define PROPERTY_OPERATION 6340; @@ -431,6 +432,7 @@ EXPRESSION ::= BRACKET ^OBJECT FUNCTION_R L3_OP* L4_OP* L5_OP* L6_OP? L7_OP* L8_OP? L9_OP? | "{" ^OBJECT COLLECTION "}" ^ COLLECTION_EXPRESSION L3_OP* L4_OP* L5_OP* L6_OP? L7_OP* L8_OP? L9_OP? } + | ":" ^OBJECT ^EXPRESSION identifier TEMPLATE_ARG ^ TEMPLATE_EXPR_BLOCK | SBRACKET ^OBJECT INDEXER_R L0_F | ASSIGN ^OBJECT ASSIGN_R | L1a_OOP @@ -470,6 +472,12 @@ EXPRESSION ::= | L9_OOP | eps ^OBJECT } + | { DYNAMIC_DIMENSION ^ARRAY_TYPE }+ { + BRACKET FUNCTION_R L3_OP* L4_OP* L5_OP* L6_OP? L7_OP* L8_OP? L9_OP? + | "{" ^OBJECT COLLECTION "}" ^ COLLECTION_EXPRESSION L3_OP* L4_OP* L5_OP* L6_OP? L7_OP* L8_OP? L9_OP? + | identifier ^OBJECT { ASSIGN ASSIGN_R }? + } + | ":" ^OBJECT ^EXPRESSION identifier TEMPLATE_ARG ^ TEMPLATE_EXPR_BLOCK | SBRACKET ^OBJECT INDEXER_R L0_F | L1a_OOP | ASSIGN ^OBJECT ASSIGN_R @@ -536,10 +544,20 @@ SUB_EXPRESSION ::= identifier+ { SBRACKET ^OBJECT INDEXER_R L0_OP* L2_OP* L3_OP* L4_OP* L5_OP* L6_OP? L7_OP* L8_OP? L9_OP? TUPLE_R? ")" | { DYNAMIC_DIMENSION ^ARRAY_TYPE }+ { - L2_OOP L2_OP* L3_OP* L4_OP* L5_OP* L6_OP? L7_OP* + identifier ")" "{" ^ PARAMETER_BLOCK BLOCK ^CLOSURE ^EXPRESSION + | L2_OOP L2_OP* L3_OP* L4_OP* L5_OP* L6_OP? L7_OP* | "{" ^OBJECT COLLECTION "}" ^ COLLECTION_EXPRESSION L3_OP* } ")" + | ":" ^OBJECT ^EXPRESSION identifier TEMPLATE_ARG ^ TEMPLATE_EXPR_BLOCK ")" | L2_OOP L2_OP* L3_OP* L4_OP* L5_OP* L6_OP? L7_OP* L8_OP? L9_OP? TUPLE_R? ")" - | L3_OOP L3_OP* L4_OP* L5_OP* L6_OP? L7_OP* L8_OP? L9_OP? TUPLE_R? ")" + | L3_OOP L3_OP* { + ":" identifier TEMPLATE_ARG ^ TEMPLATE_EXPR_BLOCK ^EXPRESSION + | L4_OP+ L5_OP* L6_OP? L7_OP* L8_OP? L9_OP? + | L5_OP+ L6_OP? L7_OP* L8_OP? L9_OP? + | L6_OP L7_OP* L8_OP? L9_OP? + | L7_OP+ L8_OP? L9_OP? + | L8_OP L9_OP? + | L9_OP + | eps } TUPLE_R? ")" | L4_OOP L4_OP* L5_OP* L6_OP? L7_OP* L8_OP? L9_OP? TUPLE_R? ")" | L5_OOP L5_OP* L6_OP? L7_OP* L8_OP? L9_OP? TUPLE_R? ")" | L6_OOP L7_OP* L8_OP? L9_OP? TUPLE_R? ")" @@ -585,7 +603,15 @@ SUB_EXPRESSION ::= } | SBRACKET ^OBJECT INDEXER_R L2_OP* L3_OP* L4_OP* L5_OP* L6_OP? L7_OP* L8_OP? L9_OP? TUPLE_R? ")" | L2_OOP L2_OP* L3_OP* L4_OP* L5_OP* L6_OP? L7_OP* L8_OP? L9_OP? TUPLE_R? ")" - | L3_OOP L3_OP* L4_OP* L5_OP* L6_OP? L7_OP* L8_OP? L9_OP? TUPLE_R? ")" + | L3_OOP L3_OP* { + ":" identifier TEMPLATE_ARG ^ TEMPLATE_EXPR_BLOCK ^EXPRESSION + | L4_OP+ L5_OP* L6_OP? L7_OP* L8_OP? L9_OP? + | L5_OP+ L6_OP? L7_OP* L8_OP? L9_OP? + | L6_OP L7_OP* L8_OP? L9_OP? + | L7_OP+ L8_OP? L9_OP? + | L8_OP L9_OP? + | L9_OP + | eps } TUPLE_R? ")" | IF_DOT ^OBJECT MESSAGE? CALL_R ^IF_OPERATION ^OPERATION_TEMPLATE OL_F TUPLE_R? ")" | ELSE_DOT ^OBJECT MESSAGE? CALL_R ^ELSE_OPERATION ^OPERATION_TEMPLATE OL_F TUPLE_R? ")" | ALT_DOT ^OBJECT MESSAGE? CALL_R ^ALT_OPERATION ^OPERATION_TEMPLATE OL_F TUPLE_R? ")" @@ -596,6 +622,10 @@ SUB_EXPRESSION ::= | L7_OOP L7_OP* L8_OP? L9_OP? TUPLE_R? ")" | L8_OOP ")" | L9_OOP ")" + | { DYNAMIC_DIMENSION ^ARRAY_TYPE }+ identifier { + "=>" ^ PARAMETER_BLOCK RET_EXPRESSION ^CLOSURE ")" ^EXPRESSION + | ")" "{" ^ PARAMETER_BLOCK BLOCK ^CLOSURE ^EXPRESSION + } | "{" NESTED_EXPRESSION ^NESTED L2_OP* L3_OP* L4_OP* L5_OP* L6_OP? L7_OP* L8_OP? L9_OP? TUPLE_R? ")" | "=>" ^ PARAMETER RET_EXPRESSION ^CLOSURE ")" ^EXPRESSION | "," ^ OBJECT ^ EXPRESSION EXPRESSION { "," EXPRESSION }* { @@ -888,6 +918,7 @@ OL_F ::= L0_F ::= L0_OP L0_F + | L1a_OP | L1_OP | L2_OP L2_F | DOT MESSAGE { L3_F | eps ^PROPERTY_OPERATION } @@ -949,7 +980,7 @@ L3_F ::= | FNL ^PROPERTY_OPERATION FNL_R | ISNIL ^PROPERTY_OPERATION SINGLE_EXPRESSION ^ISNIL_OPERATION; -L0_OP +L0_OP ::= SBRACKET INDEXER_R; L1_OP ::= diff --git a/doc/api/extensions-io-summary.html b/doc/api/extensions-io-summary.html index 690d885e5a..dbb90a8d81 100644 --- a/doc/api/extensions-io-summary.html +++ b/doc/api/extensions-io-summary.html @@ -2,7 +2,7 @@ -ELENA Standard Library 4.1: Module extensions'io +ELENA Standard Library 6.0: Module extensions'io @@ -19,7 +19,7 @@
-ELENA Standard Library
4.1 +ELENA Standard Library
6.0
@@ -36,19 +36,37 @@

  • -Extended Class Summary +Class Summary
    - + + + + + + + + +
    Extended class nameClass name Description
    -Object +BufferWriter
    -Object
    +public class BufferWriter +
    +ByteArrayReader + +
    +public class ByteArrayReader
    +
    +ByteArrayWriter + +
    +public class ByteArrayWriter
    @@ -66,7 +84,7 @@

    -ELENA Standard Library
    4.1 +ELENA Standard Library
    6.0
    diff --git a/doc/api/extensions-io.html b/doc/api/extensions-io.html index d2d95693dc..d59110f131 100644 --- a/doc/api/extensions-io.html +++ b/doc/api/extensions-io.html @@ -2,7 +2,7 @@ -ELENA Standard Library 4.1: Module extensions'io +ELENA Standard Library 6.0: Module extensions'io @@ -19,30 +19,136 @@
    -ELENA Standard Library
    4.1 +ELENA Standard Library
    6.0
    - + - +
    -system'
    -

    Object

    +extensions'io'
    +

    BufferWriter



    -Object
    +public class BufferWriter
    -
    + + +
      +
    • +

      Field Summary

      + + + + + + + + + + + + + +
      Modifier and TypeField
      + +IntNumber +_position +
      + + +_buffer +
      +
    • +
    + +
      +
    • +

      Constructor / Static Method Summary

      + + + + + + + + + +
      Modifier and TypeConstructor / Static Method
      + +internal   +flush(BufferWriter bufferWriter, BinaryWriter externalWriter) + +
      +
    • +
    +
    • - +

      Property Summary

      + + + + + + + + + +
      Modifier and TypeProperty
      + +get  Object +Source() +
      +
    • +
    + + + +
    +
    + + + +
    +
    +extensions'io'
    +

    ByteArrayReader

    +
    +
    +
    +
    +
    +
    +public class ByteArrayReader
    +
    +
    + + + + + + +
      +
    • +

      Property Summary

      + + + + + + + + + + + + + +
      Modifier and TypeProperty
      + +get  Object +Source() +
      + +get  BoolValue +Available() +
      +
    • +
    + +
      +
    • +

      Method Summary

      + + + + + + + + + + + + + +
      Modifier and TypeMethod
      + + +read(system'ByteNumber[] array, ref IntNumber actualLength) + +
      + + +close() + +
    +
    +
    + + + +
    +
    +extensions'io'
    +

    ByteArrayWriter

    +
    +
    +
    +
    +
    +public class ByteArrayWriter
    +
    +
    + + + + + + +
      +
    • +

      Property Summary

      + + + + + + + + + +
      Modifier and TypeProperty
      + +get  Object +Source() +
      +
    • +
    + +
    @@ -88,7 +494,7 @@

    Extension Summary

    -ELENA Standard Library
    4.1 +ELENA Standard Library
    6.0
    diff --git a/doc/api/index.html b/doc/api/index.html index 1af5b1e733..6cf6e86cc9 100644 --- a/doc/api/index.html +++ b/doc/api/index.html @@ -171,7 +171,7 @@

    -system'net(not yet migrated) +system'net
    @@ -306,7 +306,7 @@

    -extensions'io(not yet migrated) +extensions'io
    diff --git a/doc/api/net-summary.html b/doc/api/net-summary.html index ae423c5734..1bb3280e23 100644 --- a/doc/api/net-summary.html +++ b/doc/api/net-summary.html @@ -2,7 +2,7 @@ -ELENA Standard Library 5.8: Module net +ELENA Standard Library 6.0: Module net @@ -19,7 +19,7 @@
    -ELENA Standard Library
    5.8 +ELENA Standard Library
    6.0
    @@ -48,7 +48,7 @@

    -sealed Class TcpClient
    +public class TcpClient

    @@ -57,25 +57,43 @@

    -Class TcpClientException
    +public class TcpClientException

    -TcpRemoteClient +TcpClientWriter
    -sealed Class TcpRemoteClient
    +public class TcpClientWriter +TcpRemoteClient + + +
    +public class TcpRemoteClient
    + + + + TcpServer
    -sealed Class TcpServer
    +public class TcpServer + + + + +TcpServerWriter + + +
    +public class TcpServerWriter
    @@ -93,7 +111,7 @@

    -ELENA Standard Library
    5.8 +ELENA Standard Library
    6.0
    diff --git a/doc/api/net.html b/doc/api/net.html index f6caf9579c..0e093a8e46 100644 --- a/doc/api/net.html +++ b/doc/api/net.html @@ -2,7 +2,7 @@ -ELENA Standard Library 5.8: Module net +ELENA Standard Library 6.0: Module net @@ -19,7 +19,7 @@
    -ELENA Standard Library
    5.8 +ELENA Standard Library
    6.0
    @@ -36,13 +36,20 @@

    TcpClient



    -sealed Class TcpClient
    +public class TcpClient
    -
    -

    @@ -355,13 +248,20 @@

    TcpClientException



    -Class TcpClientException
    +public class TcpClientException
    -
    -
    + + + +
    +
    +net'
    +

    TcpClientWriter

    +
    +
    +
    +
    +
    +
    +public class TcpClientWriter
    +
    +
    + + + + + - +
    • -

      Conversion Summary

      +

      Property Summary

      - - + + +get  Object
      TypeConversion MethodModifier and TypeProperty
      -TcpClientException -cast() - +Source()
      @@ -458,12 +408,27 @@

      Method Summary

      Modifier and Type Method + + + + + +close() + + + + + + +BoolValue + +write(system'ByteNumber[] buffer, IntNumber length) + + +
    -
  • - -
    @@ -479,13 +444,20 @@

    TcpRemoteClient



    -sealed Class TcpRemoteClient
    +public class TcpRemoteClient
    -
    - -

    @@ -650,13 +560,20 @@

    TcpServer



    -sealed Class TcpServer
    +public class TcpServer
    -
    -
    + + + +
    +
    +net'
    +

    TcpServerWriter

    +
    +
    +
    +
    +
    +
    +public class TcpServerWriter
    +
    +
    + + +
      +
    • +

      Field Summary

      + + + + +TcpServer - - - +
      Modifier and TypeField
      -private  BoolValue -proceed() - +_server
      - -Object -start() - -
      +
    • +
    + + + +
      +
    • +

      Property Summary

      + + + + + + +get  Object +
      Modifier and TypeProperty
      -TcpServer -sendToAll(String s) - +Source()
      +
    • +
    + + - - -

    @@ -983,7 +887,7 @@

    Method Summary

    -ELENA Standard Library
    5.8 +ELENA Standard Library
    6.0
    diff --git a/doc/api/system-drawing-summary.html b/doc/api/system-drawing-summary.html index 9883eccacb..5091310b4d 100644 --- a/doc/api/system-drawing-summary.html +++ b/doc/api/system-drawing-summary.html @@ -172,6 +172,15 @@

    +COLOR_BACKGROUND + + +
    +COLOR_BACKGROUND
    + + + + IMAGE_BITMAP @@ -179,7 +188,7 @@

    IMAGE_BITMAP - + LR_LOADFROMFILE @@ -188,7 +197,7 @@

    LR_LOADFROMFILE - + SRCCOPY @@ -197,7 +206,7 @@

    SRCCOPY - + WhitePen diff --git a/doc/api/system-drawing.html b/doc/api/system-drawing.html index b2c7f68f66..82399fa474 100644 --- a/doc/api/system-drawing.html +++ b/doc/api/system-drawing.html @@ -672,6 +672,15 @@

    Constructor / Static Method Summary

    +internal  HBRUSH + +load(IntNumber constant) + + + + + + HBRUSH createSolid(IntNumber color) @@ -698,6 +707,14 @@

    Static Property Summary

    Default() + + + +get  HBRUSH + +COLOR_BACKGROUND() + + @@ -2016,6 +2033,43 @@

    Symbol Summary


    + + + +
    +
    +system'drawing'
    +

    COLOR_BACKGROUND

    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
      +
    • +

      Symbol Summary

      + + + + + + + +
      Modifier and TypeName
      + +public  IntNumber +COLOR_BACKGROUND +
      +
    • +
    +
    +
    +
    diff --git a/doc/api/system-io.html b/doc/api/system-io.html index 5983aa2d10..6e0241d232 100644 --- a/doc/api/system-io.html +++ b/doc/api/system-io.html @@ -49,34 +49,6 @@

    BinaryReader

    - -
      -
    • -

      Field Summary

      - - - - - - - - - - - - - -
      Modifier and TypeField
      - -Stream -_stream -
      - -IntNumber -_length -
      -
    • -
    • @@ -89,15 +61,15 @@

      Property Summary

      -get  Stream +get abstract  Object
      -Stream() +Source() -get  BoolValue +get abstract  BoolValue Available() @@ -117,7 +89,7 @@

      Method Summary

      - +abstract   read(system'ByteNumber[] array, ref IntNumber actualLength) @@ -126,7 +98,7 @@

      Method Summary

      - +abstract   close() @@ -249,32 +221,82 @@

      Field Summary

      _stream + +
    • +
    + +
      +
    • +

      Constructor / Static Method Summary

      + + + + + + + + + +
      Modifier and TypeConstructor / Static Method
      + +BinaryStreamReader +constructor(Stream stream) + +
      +
    • +
    + +
      +
    • +

      Property Summary

      + + + + + + + + + +get  BoolValue
      Modifier and TypeProperty
      + +get  Object +Source() +
      -IntNumber -_length +Available()
    - +
    • -

      Constructor / Static Method Summary

      +

      Method Summary

      - + + + + + + @@ -356,6 +378,56 @@

      Constructor / Static Method Summary

      Modifier and TypeConstructor / Static MethodMethod
      -BinaryStreamReader -constructor(Stream stream) +read(system'ByteNumber[] array, ref IntNumber actualLength) + +
      + + +close()
    + +
      +
    • +

      Property Summary

      + + + + + + + + + +
      Modifier and TypeProperty
      + +get  Object +Source() +
      +
    • +
    + +
    @@ -384,26 +456,6 @@

    BinaryWriter

    - -
      -
    • -

      Field Summary

      - - - - - - - - - -
      Modifier and TypeField
      - -Stream -_stream -
      -
    • -
    @@ -2287,15 +2348,6 @@

    Constructor / Static Method Summary

    - - - -StreamWriter - -new(String path, BoolValue appendMode) - - - @@ -2311,9 +2363,9 @@

    Property Summary

    -get  Stream +get  Object -Stream() +Source() @@ -2433,9 +2485,9 @@

    Property Summary

    -get abstract  Stream +get abstract  Object -Stream() +Source() @@ -2650,9 +2702,9 @@

    Property Summary

    -get  Stream +get  Object -Stream() +Source() @@ -2780,9 +2832,9 @@

    Property Summary

    -get abstract  Stream +get abstract  Object -Stream() +Source() diff --git a/doc/api/system-net-summary.html b/doc/api/system-net-summary.html index 1942011e2a..c7a13562ec 100644 --- a/doc/api/system-net-summary.html +++ b/doc/api/system-net-summary.html @@ -2,7 +2,7 @@ -ELENA Standard Library 5.8: Module system'net +ELENA Standard Library 6.0: Module system'net @@ -19,7 +19,7 @@
    -ELENA Standard Library
    5.8 +ELENA Standard Library
    6.0
    @@ -48,7 +48,7 @@

    -sealed Class AddrInfo
    +public class AddrInfo @@ -57,7 +57,7 @@

    -sealed Class AddrInfoReader
    +public class AddrInfoReader @@ -66,7 +66,7 @@

    -sealed Class IN_ADDR
    +public class IN_ADDR @@ -75,7 +75,7 @@

    -sealed Class SOCKADDR_IN
    +public class SOCKADDR_IN @@ -84,7 +84,7 @@

    -sealed Class Socket
    +public class Socket @@ -93,7 +93,7 @@

    -Class SocketException
    +public class SocketException @@ -109,15 +109,6 @@

    -#initializer - - -
    -#initializer
    - - - - AF_INET @@ -125,7 +116,7 @@

    AF_INET - + AF_UNSPEC @@ -134,7 +125,7 @@

    AF_UNSPEC - + AI_PASSIVE @@ -143,7 +134,7 @@

    AI_PASSIVE - + FIONBIO @@ -152,7 +143,7 @@

    FIONBIO - + INVALID_SOCKET @@ -161,7 +152,7 @@

    INVALID_SOCKET - + IPPROTO_TCP @@ -170,7 +161,7 @@

    IPPROTO_TCP - + SD_BOTH @@ -179,25 +170,25 @@

    SD_BOTH - + -SOCKET_ERROR +SOCK_STREAM
    -SOCKET_ERROR
    +SOCK_STREAM - + -SOCK_STREAM +SOCKET_ERROR
    -SOCK_STREAM
    +SOCKET_ERROR - + SOMAXCONN @@ -206,7 +197,7 @@

    SOMAXCONN - + TCP_NODELAY @@ -215,7 +206,7 @@

    TCP_NODELAY - + WSAECONNRESET @@ -224,7 +215,7 @@

    WSAECONNRESET - + WSAEWOULDBLOCK @@ -248,7 +239,7 @@

    -ELENA Standard Library
    5.8 +ELENA Standard Library
    6.0
    diff --git a/doc/api/system-net.html b/doc/api/system-net.html index c59c8c1a56..e38bd172ae 100644 --- a/doc/api/system-net.html +++ b/doc/api/system-net.html @@ -2,7 +2,7 @@ -ELENA Standard Library 5.8: Module system'net +ELENA Standard Library 6.0: Module system'net @@ -19,7 +19,7 @@
    -ELENA Standard Library
    5.8 +ELENA Standard Library
    6.0
    @@ -36,268 +36,95 @@

    AddrInfo



    -sealed Class AddrInfo
    +public class AddrInfo
    -
    -

    @@ -313,13 +140,20 @@

    AddrInfoReader



    -sealed Class AddrInfoReader
    +public class AddrInfoReader
    -
    -

    @@ -502,87 +285,52 @@

    IN_ADDR



    -sealed Class IN_ADDR
    +public class IN_ADDR
    -
    -

    @@ -630,13 +375,20 @@

    SOCKADDR_IN



    -sealed Class SOCKADDR_IN
    +public class SOCKADDR_IN
    -
    -
      -
    • - + + - +
      • -

        Constructor Summary

        +

        Static Property Summary

        - - - - - - -
        Modifier and TypeConstructor
        - -SOCKADDR_IN -constructor() - -
        -
      • -
      - -
        -
      • -

        Conversion Summary

        - - - - + +get  SOCKADDR_IN
        TypeConversion MethodStatic Property
        -SOCKADDR_IN -cast() - +Default()
      - +
      • Property Summary

        - - - - - - - - - + - - - - - - - - - - - - - - - - +set  
        Modifier and TypeProperty accessor
        - -get ShortNumber -family -
        - -set  -family(ShortNumber value) - -Property
        -get ShortNumber -port -
        - -set  -port(ShortNumber value) - -
        - -set  -family(IntNumber n) - -
        - -set  -port(IntNumber n) - -
        - -set  ip_address(String ip) @@ -795,30 +473,6 @@

        Property Summary

      - -
        -
      • -

        Method Summary

        - - - - - - - - - -
        Modifier and TypeMethod
        - -private  Object -constructor() - -
        -
      • -
      -
    • -
    -

    @@ -834,13 +488,20 @@

    Socket



    -sealed Class Socket
    +public class Socket
    -
    - -

    @@ -1067,13 +695,20 @@

    SocketException



    -Class SocketException
    +public class SocketException
    -
    -

    - +
    system'net'
    -

    #initializer

    +

    AF_INET

    -
    -
      -
    • -

      Symbol Summary

      - - - - - - - - - -
      Modifier and TypeName
      - - -symbol #initializer -
      -
    • -
    -
    +
    +

    -
    - - - -
    -
    -system'net'
    -

    AF_INET

    +
    +
    +
    -
    • Symbol Summary

      @@ -1274,14 +842,12 @@

      Symbol Summary

      Modifier and Type Name - -IntNumber - + +public  IntNumber -symbol AF_INET +AF_INET -
    @@ -1297,7 +863,14 @@

    Symbol Summary

    AF_UNSPEC

    -
    +
    +
    +
    +
    +
    +
    +
    +
    • Symbol Summary

      @@ -1306,14 +879,12 @@

      Symbol Summary

      Modifier and Type Name - -IntNumber - + +public  IntNumber -symbol AF_UNSPEC +AF_UNSPEC -
    @@ -1329,7 +900,14 @@

    Symbol Summary

    AI_PASSIVE

    -
    +
    +
    +
    +
    +
    +
    +
    +
    • Symbol Summary

      @@ -1338,14 +916,12 @@

      Symbol Summary

      Modifier and Type Name - -IntNumber - + +public  IntNumber -symbol AI_PASSIVE +AI_PASSIVE -
    @@ -1361,7 +937,14 @@

    Symbol Summary

    FIONBIO

    -
    +
    +
    +
    +
    +
    +
    +
    +
    • Symbol Summary

      @@ -1370,14 +953,12 @@

      Symbol Summary

      Modifier and Type Name - -IntNumber - + +public  IntNumber -symbol FIONBIO +FIONBIO -
    @@ -1393,7 +974,14 @@

    Symbol Summary

    INVALID_SOCKET

    -
    +
    +
    +
    +
    +
    +
    +
    +
    • Symbol Summary

      @@ -1402,14 +990,12 @@

      Symbol Summary

      Modifier and Type Name - -IntNumber - + +public  IntNumber -symbol INVALID_SOCKET +INVALID_SOCKET -
    @@ -1425,7 +1011,14 @@

    Symbol Summary

    IPPROTO_TCP

    -
    +
    +
    +
    +
    +
    +
    +
    +
    • Symbol Summary

      @@ -1434,14 +1027,12 @@

      Symbol Summary

      Modifier and Type Name - -IntNumber - + +public  IntNumber -symbol IPPROTO_TCP +IPPROTO_TCP -
    @@ -1457,7 +1048,14 @@

    Symbol Summary

    SD_BOTH

    -
    +
    +
    +
    +
    +
    +
    +
    +
    • Symbol Summary

      @@ -1466,30 +1064,35 @@

      Symbol Summary

      Modifier and Type Name - -IntNumber - + +public  IntNumber -symbol SD_BOTH +SD_BOTH -

    - +
    system'net'
    -

    SOCKET_ERROR

    +

    SOCK_STREAM

    +
    +
    +
    +
    +
    +
    +
    +
    -
    • Symbol Summary

      @@ -1498,30 +1101,35 @@

      Symbol Summary

      Modifier and Type Name - -IntNumber - + +public  IntNumber -symbol SOCKET_ERROR +SOCK_STREAM -

    - +
    system'net'
    -

    SOCK_STREAM

    +

    SOCKET_ERROR

    +
    +
    +
    +
    +
    +
    +
    +
    -
    • Symbol Summary

      @@ -1530,14 +1138,12 @@

      Symbol Summary

      Modifier and Type Name - -IntNumber - + +public  IntNumber -symbol SOCK_STREAM +SOCKET_ERROR -
    @@ -1553,7 +1159,14 @@

    Symbol Summary

    SOMAXCONN

    -
    +
    +
    +
    +
    +
    +
    +
    +
    • Symbol Summary

      @@ -1562,14 +1175,12 @@

      Symbol Summary

      Modifier and Type Name - -IntNumber - + +public  IntNumber -symbol SOMAXCONN +SOMAXCONN -
    @@ -1585,7 +1196,14 @@

    Symbol Summary

    TCP_NODELAY

    -
    +
    +
    +
    +
    +
    +
    +
    +
    • Symbol Summary

      @@ -1594,14 +1212,12 @@

      Symbol Summary

      Modifier and Type Name - -IntNumber - + +public  IntNumber -symbol TCP_NODELAY +TCP_NODELAY -
    @@ -1617,7 +1233,14 @@

    Symbol Summary

    WSAECONNRESET

    -
    +
    +
    +
    +
    +
    +
    +
    +
    • Symbol Summary

      @@ -1626,14 +1249,12 @@

      Symbol Summary

      Modifier and Type Name - -IntNumber - + +public  IntNumber -symbol WSAECONNRESET +WSAECONNRESET -
    @@ -1649,7 +1270,14 @@

    Symbol Summary

    WSAEWOULDBLOCK

    -
    +
    +
    +
    +
    +
    +
    +
    +
    • Symbol Summary

      @@ -1658,14 +1286,12 @@

      Symbol Summary

      Modifier and Type Name - -IntNumber - + +public  IntNumber -symbol WSAEWOULDBLOCK +WSAEWOULDBLOCK -
    @@ -1683,7 +1309,7 @@

    Symbol Summary

    -ELENA Standard Library
    5.8 +ELENA Standard Library
    6.0
    diff --git a/doc/api/system-summary.html b/doc/api/system-summary.html index e6eaebc8b8..42e64f56b2 100644 --- a/doc/api/system-summary.html +++ b/doc/api/system-summary.html @@ -903,6 +903,15 @@

    +StartUpEvents + + +
    +public class StartUpEvents
    + + + + String @@ -911,7 +920,7 @@

    A UTF-8 literal value

    - + stringConvertor @@ -920,7 +929,7 @@

    public singleton stringConvertor

    - + Symbol @@ -929,7 +938,7 @@

    public class Symbol

    - + SymbolLoaderException @@ -938,7 +947,7 @@

    public class SymbolLoaderException

    - + TypeLoaderException @@ -947,7 +956,7 @@

    public class TypeLoaderException

    - + uintConvertor @@ -956,7 +965,7 @@

    public singleton uintConvertor

    - + UIntNumber @@ -966,7 +975,7 @@

    A unsigned 32 bit integer

    - + UnsafePointer @@ -975,7 +984,7 @@

    public class UnsafePointer

    - + ushortConvertor @@ -984,7 +993,7 @@

    public singleton ushortConvertor

    - + UShortNumber @@ -994,7 +1003,7 @@

    an unsigned 16 bit integer

    - + Variable @@ -1004,7 +1013,7 @@

    A generic variable.
    Extends an assigned value

    - + Variant @@ -1014,7 +1023,7 @@

    A basic type variant class

    - + wideConvertor @@ -1023,7 +1032,7 @@

    public singleton wideConvertor

    - + WideString @@ -1117,6 +1126,15 @@

    +startUpEvents + + +
    +startUpEvents
    + + + + true diff --git a/doc/api/system.html b/doc/api/system.html index e34d2a335c..1613f9e3b3 100644 --- a/doc/api/system.html +++ b/doc/api/system.html @@ -11626,6 +11626,17 @@

    Extension Summary

    + + +__getParent() + +
    +Returns the parent of the specified class
    + + + + + BoolValue safeEqual(Object o) @@ -11634,7 +11645,7 @@

    Extension Summary

    Returns true if the parameter is equal to the object or false. It does not raise an exception if the objects are not compatible
    - + BoolValue @@ -11643,7 +11654,7 @@

    Extension Summary

    - + BoolValue @@ -11652,7 +11663,7 @@

    Extension Summary

    - + BoolValue @@ -11663,7 +11674,7 @@

    Extension Summary

    Returns true if the object is nil
    - + @@ -11672,7 +11683,7 @@

    Extension Summary

    - + BoolValue @@ -11683,6 +11694,15 @@

    Extension Summary

    Checks if the object is an instance of type
    + + + +BoolValue + +subsetOf(Object type) + + + @@ -15885,6 +15905,113 @@

    Method Summary


    + + + +
    +
    +system'
    +

    StartUpEvents

    +
    +
    +
    +
    +
    +
    +public class StartUpEvents
    +
    +
    + + + + +
      +
    • +

      Constructor / Static Method Summary

      + + + + + + + + + +
      Modifier and TypeConstructor / Static Method
      + +internal  StartUpEvents +constructor() + +
      +
    • +
    + +
      +
    • +

      Method Summary

      + + + + + + + + + + + + + +
      Modifier and TypeMethod
      + +internal   +stopping() + +
      + +internal   +handlingError(e) + +
      +
    • +
    +
    +
    @@ -20755,6 +20882,43 @@

    Symbol Summary


    + + + +
    +
    +system'
    +

    startUpEvents

    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
      +
    • +

      Symbol Summary

      + + + + + + + +
      Modifier and TypeName
      + +public  StartUpEvents +startUpEvents +
      +
    • +
    +
    +
    +
    diff --git a/doc/features b/doc/features index 77ec08a2a5..8429c2209d 100644 --- a/doc/features +++ b/doc/features @@ -1,127 +1,7 @@ -Description missing points: -- Operators Templates : .? and .\ - - - - - - - - - - - - - - - -Literal constants - - custom defined numeric literals - - unsigned hexadecimal number - - -Declarations - Namespaces - * nested namespaces (import is declared for the namespace) - * reference identifier - Classes - Constructors - * Normal constructors - the default one is auto called + - * Expression constructors - the returning value is boxed, no default constructor call + - * constructors with resend expression - no default constructor call + - * conversion constructor - - default constructor / in-place initialization is not called + - - call explicit constructor - * Default constructor - - impicit : if no constructors are declared - default one is auto-generated + - - implicit protected - if there are constructors - protected one is auto-generated + - - explicit - if there are constructors - auto called + - - - private constructor - class cannot be inherited + - - protected constructor + - - conversion constructors + - - named : call the default constructor + - - anonymos / conversion - do not call default constructor + - - resending : to another constructor / to parent one + - Static Methods - * inheritable : cannot be overriden, accessible in all parent class - * sealed static methods - Methods - * Visibility : private / protected / internal ones + - * yield methods - * returning types + - * Multimethods - - implcit default + - - explcit default + - - multi-return - * variadic + - * byref args + - * in-place declaration - * resend + - * dispatch + - * ret expression + - * Generic handlers + - - __received - incoming message + - * abstract / sealed / predefined + - * inline arg - - * Build-in Variables + - - self vs this self + - - __received + - - class / global predicate - - Properties - * implicit + - * explicit + - * abstract + - * multi-return - Fields - * fixed-size arrays + - * realonly fields + - * constant fields + - * constant accumulating fields + - * static fields + - Closures - Nested classes - Creating - * in-place initialization : default constructor is not called - Templates - Extensions - * public / internal - * direct call - op.testMe(1) - Extension Templates - Property templates -Code - nested scopes - Idenifiers - * implicit - * reference - * global - Types - * conversions - Variables - * optional types - * fixed-size array - * in-place initializer - * in-place declaration - * previous - Operators - * a ?? b / a.msg() ?? b - * .? - * .\ - * switch operator - * $sizeof - Expressions - * In-place assignment (both variable and properties) - * lazy - Control statements - Conversions : cast vs conversion constructor - Message Dispaching - Modificators - * __weak attribute - custom literal constant -Mixins -Project - Options - * option to turn on / off auto system module import -VM +List of ELENA featuers: +----------------------- +- variadic functions +- if:is +- accessing private method inside static method +- project profile +- project target : stand-alone / vm client \ No newline at end of file diff --git a/doc/todo.txt b/doc/todo.txt index 9e84e8f105..2bc0e16c05 100644 --- a/doc/todo.txt +++ b/doc/todo.txt @@ -5,33 +5,17 @@ In development: [development] ### EPIC: elena 6.0 - redux ### - === Iteration 21 === - - === Iteration 22 === - -------------------------------------- - dev: #608, #637 (bt tests (>=4), all bc tests), #646, interface mockup - op: - opt:pi under 6 sec, #601 - maint: #506, #617, #620, #622 - exp:#612 - ide:vm debugger - tools: - prom:elena in nutshell every 1 week; post an article describing how to use distributed dictionary for test,#635 - port:chat sample, helloworld gui sample (button) - === Iteration 23 === -------------------------------------- - dev: 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"); - op: - opt: - maint: - exp: - ide: - tools: - prom: - port:elenavm / elt for linux + dev: #574,#265,#619,#637(bt tests (>=4), all bc tests) + op: github action - create a draft release + opt:pi under 6 sec + maint:#620, #486, #506 + exp: generate code templates - e.g. simple console app + ide:linux simplest gui, vm debugger + tools:elt64-cli + prom:#635 on reddit;elena in nutshell every 1 week; post an article describing how to use distributed dictionary for test + port:chat sample, elenavm / elt for linux, helloworld gui sample (button) === Iteration 24 === -------------------------------------- @@ -43,4 +27,4 @@ In development: ide: tools: prom: - port: + port:upndown diff --git a/elenasrc3/common/lists.h b/elenasrc3/common/lists.h index 2c390e9081..122d8997c8 100644 --- a/elenasrc3/common/lists.h +++ b/elenasrc3/common/lists.h @@ -1495,7 +1495,7 @@ namespace elena_lang if (currentKey == key) { T value = _defValue; - _buffer.read(position, &value, sizeof(Key)); + _buffer.read(position, &value, sizeof(T)); return value; } @@ -3086,7 +3086,7 @@ namespace elena_lang bool eof() { - return index == owner->count_pos(); + return index == owner->count_int(); } }; diff --git a/elenasrc3/common/tools.h b/elenasrc3/common/tools.h index fd98abb202..098a8c5834 100644 --- a/elenasrc3/common/tools.h +++ b/elenasrc3/common/tools.h @@ -215,6 +215,15 @@ inline void* UInt32ToPtr(unsigned int val) return (void*)(static_cast(val)); } +// --- ptrToUInt64 --- + +inline unsigned long long ptrToUInt64(void* ptr) +{ + uintptr_t ptrVal = (uintptr_t)ptr; + + return static_cast(ptrVal); +} + } // _ELENA_ #endif // toolsH diff --git a/elenasrc3/common/tree.h b/elenasrc3/common/tree.h index 138a6ffe3d..21a9ac335a 100644 --- a/elenasrc3/common/tree.h +++ b/elenasrc3/common/tree.h @@ -240,6 +240,11 @@ namespace elena_lang return this->_position != node._position; } + bool compare(Key key1, Key key2) + { + return this->key == key1 || this->key == key2; + } + ustr_t identifier() { if (arg.strArgPosition != INVALID_POS) { @@ -720,6 +725,18 @@ namespace elena_lang return counter; } + static int countSibling(Node current, Key key) + { + int counter = 0; + while (current.key == key) { + counter++; + + current = current.nextNode(); + } + + return counter; + } + static void serialize(Node& node, void(*encoder)(TextWriter&, Key, ustr_t, int, void*), TextWriter& writer, void* arg) { encoder(writer, node.key, node.identifier(), node.arg.value, arg); diff --git a/elenasrc3/common/ustring.h b/elenasrc3/common/ustring.h index 1f51e4e5c6..79e4756fc2 100644 --- a/elenasrc3/common/ustring.h +++ b/elenasrc3/common/ustring.h @@ -693,6 +693,13 @@ namespace elena_lang copy(value + index, length); } + DynamicString(const T* value) + { + _size = 0; + _string = nullptr; + + copy(value, getlength(value)); + } }; diff --git a/elenasrc3/elc/clicommon.h b/elenasrc3/elc/clicommon.h index ca273c89d6..2bee6e3772 100644 --- a/elenasrc3/elc/clicommon.h +++ b/elenasrc3/elc/clicommon.h @@ -144,7 +144,8 @@ enum class TemplateType Inline, InlineProperty, Class, - Statement + Statement, + Expression }; enum class Visibility @@ -301,6 +302,7 @@ class ModuleScopeBase : public SectionScopeBase virtual bool withValidation() = 0; virtual bool isDeclared(ref_t reference) = 0; + virtual bool isSymbolDeclared(ref_t reference) = 0; virtual bool isInternalOp(ref_t reference) { @@ -416,7 +418,8 @@ enum class ExpressionAttribute : pos64_t RetValExpected = 0x00020000000, CheckShortCircle = 0x00040000000, LookaheadExprMode = 0x00080000000, - DistributedForward = 0x00040000000, + WithVariadicArgCast = 0x02008000000, + DistributedForward = 0x04000000000, DynamicObject = 0x08000000000, Superior = 0x10000000000, Lookahead = 0x20000000000, @@ -524,6 +527,8 @@ class TemplateProssesorBase List& parameters) = 0; virtual bool importCodeTemplate(ModuleScopeBase& moduleScope, ref_t templateRef, SyntaxNode target, List& arguments, List& parameters) = 0; + virtual bool importExpressionTemplate(ModuleScopeBase& moduleScope, ref_t templateRef, SyntaxNode target, + List& arguments, List& parameters) = 0; }; // --- SyntaxWriterBase --- @@ -708,7 +713,8 @@ class LinkerBase ErrorProcessorBase* _errorProcessor; public: - virtual LinkResult run(ProjectBase& project, ImageProviderBase& provider, PlatformType uiType) = 0; + virtual LinkResult run(ProjectBase& project, ImageProviderBase& provider, + PlatformType uiType, path_t exeExtension) = 0; LinkerBase(ErrorProcessorBase* errorProcessor) { diff --git a/elenasrc3/elc/cliconst.h b/elenasrc3/elc/cliconst.h index 05f6bd5499..70105d76ca 100644 --- a/elenasrc3/elc/cliconst.h +++ b/elenasrc3/elc/cliconst.h @@ -13,7 +13,7 @@ namespace elena_lang { - #define ELC_REVISION_NUMBER 0x0256 + #define ELC_REVISION_NUMBER 0x026F #if defined _M_IX86 || _M_X64 @@ -46,7 +46,7 @@ namespace elena_lang constexpr auto ELC_PROFILE_WARNING = "\nWARNING - Please select one of available profiles:%s\n"; - constexpr auto ELC_HELP_INFO = "elena-cli {-key} {source-file+ | project-file}\nkeys:\n -f{fwd=reference} - add a forward\n -l{profile name} - selecct a profile\n -m - turning on address mapping output\n -o{0 | 1 | 2} - set the optimization level\n -p - set the base path\n -r - clean the compilation output\n -s{ stackReserv:n } - set the linker option - stack reserved\n -t{ template name } - load the project template\n -v - turn on a verbose output mode\n - w{ 0 | 1 | 2 | 3 } - set the minimal warnings level to X = { 0 | 1 | 2 | 3 }\n -xb[-] - turn on / off a conditional boxing\n -xe[-] - turn on / off a compile-time expression evaluation\n -xp[-] - turn on / off generation of the parameter meta info"; + constexpr auto ELC_HELP_INFO = "elena-cli {-key} {source-file+ | project-file}\nkeys:\n -f{fwd=reference} - add a forward\n -l{profile name} - selecct a profile\n -m - turning on address mapping output\n -o{0 | 1 | 2} - set the optimization level\n -p - set the base path\n -r - clean the compilation output\n -s{ stackReserv:n } - set the linker option - stack reserved\n -t{ template name } - load the project template\n -v - turn on a verbose output mode\n - w{ 0 | 1 | 2 | 3 } - set the minimal warnings level to X = { 0 | 1 | 2 | 3 }\n -xb[-] - turn on / off a conditional boxing\n -xe[-] - turn on / off a compile-time expression evaluation\n -xm[-] - turn on / off auto loading module extension list\n -xp[-] - turn on / off generation of the parameter meta info"; constexpr auto SYNTAX_FILE = "syntax60.dat"; constexpr auto BC_RULES_FILE = "bc_rules60.dat"; diff --git a/elenasrc3/elc/codeimage.cpp b/elenasrc3/elc/codeimage.cpp index 2f5165e54f..3a060709ec 100644 --- a/elenasrc3/elc/codeimage.cpp +++ b/elenasrc3/elc/codeimage.cpp @@ -2,7 +2,7 @@ // E L E N A P r o j e c t: ELENA Compiler // // This file contains ELENA Image class implementations -// (C)2021-2023, by Aleksey Rakov +// (C)2021-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #include "elena.h" @@ -82,7 +82,7 @@ TargetImage :: TargetImage(PlatformType systemTarget, ForwardResolverBase* resol // creating start up symbol Module* dummyModule = new Module(); - linker.loadPreloaded(PRELOADED_FORWARD); + linker.loadPreloaded(PRELOADED_FORWARD, !imageInfo.autoModuleExtension); addLazyReference({ mskAutoSymbolRef, INVALID_POS, dummyModule, dummyModule->mapReference(resolver->resolveForward(START_FORWARD)), 0}); diff --git a/elenasrc3/elc/codeimage.h b/elenasrc3/elc/codeimage.h index ee6b716977..a8caf7f372 100644 --- a/elenasrc3/elc/codeimage.h +++ b/elenasrc3/elc/codeimage.h @@ -2,7 +2,7 @@ // E L E N A P r o j e c t: ELENA Compiler // // This header contains ELENA Image class declarations -// (C)2021-2022, by Aleksey Rakov +// (C)2021-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #ifndef CODEIMAGE_H @@ -19,6 +19,7 @@ namespace elena_lang PlatformType type; pos_t codeAlignment; bool autoClassSymbol; + bool autoModuleExtension; bool withTLS; JITSettings coreSettings; ustr_t ns; @@ -27,7 +28,7 @@ namespace elena_lang { type = PlatformType::None; codeAlignment = 0; - autoClassSymbol = withTLS = false; + autoClassSymbol = autoModuleExtension = withTLS = false; coreSettings = {}; ns = nullptr; } diff --git a/elenasrc3/elc/compiler.cpp b/elenasrc3/elc/compiler.cpp index 31b9d63d4a..c5bfe3cd2b 100644 --- a/elenasrc3/elc/compiler.cpp +++ b/elenasrc3/elc/compiler.cpp @@ -1,4 +1,5 @@ //--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- // E L E N A P r o j e c t: ELENA Compiler // // This file contains ELENA compiler class implementation. @@ -59,6 +60,13 @@ MethodHint operator | (const ref_t& l, const MethodHint& r) // SyntaxTreeSerializer::save(node, target); //} +//inline void storeNode(BuildNode node) +//{ +// DynamicUStr target; +// +// BuildTreeSerializer::save(node, target); +//} + inline bool isSelfCall(ObjectInfo target) { switch (target.kind) { @@ -1161,9 +1169,9 @@ void Compiler::ClassScope :: save() // --- ClassClassScope --- -Compiler::ClassClassScope::ClassClassScope(Scope* parent, ref_t reference, Visibility visibility, ClassInfo* classInfo) +Compiler::ClassClassScope::ClassClassScope(Scope* parent, ref_t reference, Visibility visibility, ClassInfo* classInfo, ref_t classInfoRef) : ClassScope(parent, reference, visibility), - classInfo(classInfo) + classInfo(classInfo), classInfoRef(classInfoRef) { } @@ -1213,7 +1221,7 @@ bool Compiler::MethodScope :: checkType(MethodInfo& methodInfo, MethodHint type) return (methodInfo.hints & MethodHint::Mask) == type; } -ObjectInfo Compiler::MethodScope :: mapSelf(bool memberMode) +ObjectInfo Compiler::MethodScope :: mapSelf(bool memberMode, bool ownerClass) { if (!memberMode) { if (isExtension) { @@ -1223,6 +1231,9 @@ ObjectInfo Compiler::MethodScope :: mapSelf(bool memberMode) } return { ObjectKind::Param, { }, -1 }; } + else if (ownerClass && (closureMode || nestedMode)) { + return parent->mapIdentifier(OWNER_VAR, false, EAttr::None); + } else if (selfLocal != 0) { if (isEmbeddable) { return { ObjectKind::SelfBoxableLocal, { getClassRef(false) }, (ref_t)selfLocal, TargetMode::Conditional }; @@ -1394,7 +1405,7 @@ void Compiler::CodeScope :: markAsAssigned(ObjectInfo object) parent->markAsAssigned(object); } -bool Compiler::CodeScope :: resolveAutoType(ObjectInfo& info, TypeInfo typeInfo) +bool Compiler::CodeScope :: resolveAutoType(ObjectInfo& info, TypeInfo typeInfo, int size, int extra) { if (info.kind == ObjectKind::Local) { for (auto it = locals.start(); !it.eof(); ++it) { @@ -1402,8 +1413,18 @@ bool Compiler::CodeScope :: resolveAutoType(ObjectInfo& info, TypeInfo typeInfo) if ((*it).typeInfo.typeRef == V_AUTO) { (*it).typeInfo.typeRef = typeInfo.typeRef; (*it).typeInfo.elementRef = typeInfo.elementRef; + (*it).size = size; + // HOTFIX : update the reference if required + if (size > 0) { + SyntaxNode terminal = localNodes.exclude((*it).offset); + localNodes.add(-(int)extra, terminal); + + (*it).offset = extra; + info.reference = extra; + info.kind = ObjectKind::LocalAddress; + } - info.typeInfo = typeInfo; + info.typeInfo = typeInfo; return true; } @@ -1411,7 +1432,7 @@ bool Compiler::CodeScope :: resolveAutoType(ObjectInfo& info, TypeInfo typeInfo) } } - return Scope::resolveAutoType(info, typeInfo); + return Scope::resolveAutoType(info, typeInfo, size, extra); } // --- Compiler::ExprScope --- @@ -1688,12 +1709,25 @@ Compiler :: Compiler( _evaluateOp = false; _verbose = false; _noValidation = false; + _withDebugInfo = true; _trackingUnassigned = false; _lookaheadOptMode = true; // !! temporal } +bool Compiler :: isClassClassOperation(Scope& scope, ObjectInfo target) +{ + if (target.kind == ObjectKind::Param || target.kind == ObjectKind::ParamAddress) { + ClassScope* classScope = Scope::getScope(scope, Scope::ScopeLevel::Class); + if (classScope && classScope->isClassClass()) { + return target.typeInfo.typeRef == (static_cast(classScope))->getProperClassRef(); + } + } + + return false; +} + inline ref_t resolveDictionaryMask(TypeInfo typeInfo) { if (typeInfo.typeRef == V_DICTIONARY) { @@ -2021,6 +2055,9 @@ void Compiler :: declareDictionary(Scope& scope, SyntaxNode node, Visibility vis // create a meta section scope.moduleScope->module->mapSection(reference | mask, false); + + // NOTE : comment it to prevent from executing second time + node.setKey(SyntaxKey::Idle); } void Compiler :: declareVMT(ClassScope& scope, SyntaxNode node, bool& withConstructors, bool& withDefaultConstructor, @@ -3921,6 +3958,9 @@ ObjectInfo Compiler :: evalExpression(Interpreter& interpreter, Scope& scope, Sy break; case SyntaxKey::Object: retVal = evalObject(interpreter, scope, node); + if (!ignoreErrors && retVal.kind == ObjectKind::Unknown) { + scope.raiseError(errCannotEval, node); + } break; case SyntaxKey::PropertyOperation: retVal = evalPropertyOperation(interpreter, scope, node, ignoreErrors); @@ -4405,6 +4445,9 @@ void Compiler :: declareTemplateAttributes(TemplateScope& scope, SyntaxNode node postfix.append(':'); postfix.append(current.firstChild(SyntaxKey::TerminalMask).identifier()); break; + case SyntaxKey::ReturnExpression: + scope.type = TemplateType::Expression; + break; default: break; } @@ -4577,6 +4620,7 @@ void Compiler :: declareTemplate(TemplateScope& scope, SyntaxNode& node) } case TemplateType::Inline: case TemplateType::Statement: + case TemplateType::Expression: break; default: scope.raiseError(errInvalidSyntax, node); @@ -4609,6 +4653,11 @@ void Compiler :: declareTemplateCode(TemplateScope& scope, SyntaxNode& node) postfix.append('#'); postfix.appendInt(argCount); break; + case TemplateType::Expression: + prefix.append(INLINEEXPR_PREFIX); + postfix.append('#'); + postfix.appendInt(argCount); + break; default: break; } @@ -7151,9 +7200,12 @@ ObjectInfo Compiler :: compileCode(BuildTreeWriter& writer, CodeScope& codeScope ObjectInfo exprRetVal = {}; // variable declaration node - writer.newNode(BuildKey::VariableInfo); - BuildNode variableNode = writer.CurrentNode(); - writer.closeNode(); + BuildNode variableNode = {}; + if (!noDebugInfoMode) { + writer.newNode(BuildKey::VariableInfo); + variableNode = writer.CurrentNode(); + writer.closeNode(); + } EAttr mode = closureMode ? EAttr::RetValExpected : EAttr::None; if (noDebugInfoMode) @@ -7178,7 +7230,7 @@ ObjectInfo Compiler :: compileCode(BuildTreeWriter& writer, CodeScope& codeScope } CodeScope subScope(&codeScope); - exprRetVal = compileCode(writer, subScope, current, false, autoGenerated); + exprRetVal = compileCode(writer, subScope, current, false, autoGenerated || !_withDebugInfo); subScope.syncStack(&codeScope); if (!noDebugInfoMode && autoGenerated) @@ -7195,19 +7247,8 @@ ObjectInfo Compiler :: compileCode(BuildTreeWriter& writer, CodeScope& codeScope current = current.nextNode(); } - injectVariableInfo(variableNode, codeScope); - - if (_trackingUnassigned) { - // warn if the variable was not assigned - for (auto it = codeScope.locals.start(); !it.eof(); ++it) { - if ((*it).unassigned) { - if((*it).size > 0) { - warnOnUnassignedLocal(node, codeScope, -(*it).offset); - } - else warnOnUnassignedLocal(node, codeScope, (*it).offset); - } - } - } + if(!noDebugInfoMode) + injectVariableInfo(variableNode, codeScope); // NOTE : in the closure mode the last statement is the closure result return closureMode ? exprRetVal : retVal; @@ -7277,7 +7318,7 @@ void Compiler :: compileMethodCode(BuildTreeWriter& writer, ClassScope* classSco SyntaxNode bodyNode = node.firstChild(SyntaxKey::ScopeMask); switch (bodyNode.key) { case SyntaxKey::CodeBlock: - retVal = compileCode(writer, codeScope, bodyNode, scope.closureMode); + retVal = compileCode(writer, codeScope, bodyNode, scope.closureMode, !_withDebugInfo); break; case SyntaxKey::ReturnExpression: if (scope.isYieldable()) { @@ -7309,6 +7350,18 @@ void Compiler :: compileMethodCode(BuildTreeWriter& writer, ClassScope* classSco break; } + if (_trackingUnassigned) { + // warn if the variable was not assigned + for (auto it = codeScope.locals.start(); !it.eof(); ++it) { + if ((*it).unassigned) { + if ((*it).size > 0) { + warnOnUnassignedLocal(node, codeScope, -(*it).offset); + } + else warnOnUnassignedLocal(node, codeScope, (*it).offset); + } + } + } + // if the method returns itself if (retVal.kind == ObjectKind::Unknown && !codeScope.withRetStatement) { Expression expression(this, codeScope, writer); @@ -7583,15 +7636,22 @@ ObjectInfo Compiler :: compileResendCode(BuildTreeWriter& writer, CodeScope& cod if (!test(messageRef, FUNCTION_MESSAGE)) arguments.add(source); - bool withVariadicArg = false; + Expression::ArgumentListType argListType = Expression::ArgumentListType::Normal; ref_t implicitSignatureRef = expression.compileMessageArguments(current, arguments, expectedSignRef, - EAttr::NoPrimitives, &updatedOuterArgs, withVariadicArg); + EAttr::NoPrimitives, &updatedOuterArgs, argListType); EAttr opMode = EAttr::CheckShortCircle; - if (withVariadicArg) { + if (argListType == Expression::ArgumentListType::VariadicArgList || argListType == Expression::ArgumentListType::VariadicArgListWithTypecasting) { messageRef |= VARIADIC_MESSAGE; - opMode = opMode | EAttr::WithVariadicArg; + + if (getArgCount(messageRef) > 2) + messageRef = overwriteArgCount(messageRef, 2); + + + + opMode = opMode | + ((argListType == Expression::ArgumentListType::VariadicArgList) ? EAttr::WithVariadicArg : EAttr::WithVariadicArgCast); } retVal = expression.compileMessageOperation(node, target, messageRef, @@ -7754,7 +7814,7 @@ mssg_t Compiler :: compileInplaceConstructorHandler(BuildTreeWriter& writer, Met privateScope.selfLocal = -1; CodeScope codeScope(&privateScope); - beginMethod(writer, privateScope, methodNode, BuildKey::Method, true); + beginMethod(writer, privateScope, methodNode, BuildKey::Method, _withDebugInfo); writer.appendNode(BuildKey::OpenFrame); if (methodNode.existChild(SyntaxKey::FillingAttr)) { @@ -8008,7 +8068,7 @@ void Compiler :: compileMethod(BuildTreeWriter& writer, MethodScope& scope, Synt return; } } - beginMethod(writer, scope, node, BuildKey::Method, true); + beginMethod(writer, scope, node, BuildKey::Method, _withDebugInfo); switch (current.key) { case SyntaxKey::CodeBlock: @@ -8224,7 +8284,7 @@ void Compiler :: compileConstructor(BuildTreeWriter& writer, MethodScope& scope, // NOTE : special case - abstract class with a protected constructor bool protectedAbstractMode = scope.isProtected() && abstractMode; - beginMethod(writer, scope, node, BuildKey::Method, true); + beginMethod(writer, scope, node, BuildKey::Method, _withDebugInfo); CodeScope codeScope(&scope); ref_t classFlags = codeScope.getClassFlags(); @@ -8603,7 +8663,8 @@ void Compiler :: compileClosureClass(BuildTreeWriter& writer, ClassScope& scope, writer.newNode(BuildKey::Class, scope.reference); NamespaceScope* ns = Scope::getScope(scope, Scope::ScopeLevel::Namespace); - writer.appendNode(BuildKey::Path, *ns->sourcePath); + if (_withDebugInfo) + writer.appendNode(BuildKey::Path, *ns->sourcePath); MethodScope methodScope(&scope); declareClosureMessage(methodScope, node); @@ -8703,36 +8764,8 @@ void Compiler :: compileVMT(BuildTreeWriter& writer, ClassScope& scope, SyntaxNo continue; } - MethodScope methodScope(&scope); - initializeMethod(scope, methodScope, current); - - #ifdef FULL_OUTOUT_INFO - IdentifierString messageName; - ByteCodeUtil::resolveMessageName(messageName, scope.module, methodScope.message); - - // !! temporal - if (messageName.compare("static:getItem<'IntNumber,'Object>[3]")) - methodScope.message |= 0; - - _errorProcessor->info(infoCurrentMethod, *messageName); - #endif // FULL_OUTOUT_INFO - - // if it is a dispatch handler - if (methodScope.message == scope.moduleScope->buildins.dispatch_message) { - compileDispatcherMethod(writer, methodScope, current, - test(scope.info.header.flags, elWithGenerics), - test(scope.info.header.flags, elWithVariadics)); - } - // if it is an abstract one - else if (methodScope.checkHint(MethodHint::Abstract)) { - compileAbstractMethod(writer, methodScope, current, scope.abstractMode); - } - // if it is an initializer - else if (methodScope.checkHint(MethodHint::Initializer)) { - compileInitializerMethod(writer, methodScope, node); - } - // if it is a normal method - else compileMethod(writer, methodScope, current); + Method method(this, scope); + method.compile(writer, current); break; } case SyntaxKey::Constructor: @@ -9054,20 +9087,17 @@ void Compiler :: compileNamespace(BuildTreeWriter& writer, NamespaceScope& ns, S } case SyntaxKey::Class: { - ClassScope classScope(&ns, current.arg.reference, ns.defaultVisibility); - ns.moduleScope->loadClassInfo(classScope.info, current.arg.reference, false); - classScope.abstractMode = test(classScope.info.header.flags, elAbstract); - if (test(classScope.info.header.flags, elExtension)) - classScope.extensionClassRef = classScope.getAttribute(ClassAttribute::ExtensionRef); + Class classHelper(this, &ns, current.arg.reference, ns.defaultVisibility); + classHelper.load(); - compileClass(writer, classScope, current); + compileClass(writer, classHelper.scope, current); // compile class class if it available - if (classScope.info.header.classRef != classScope.reference && classScope.info.header.classRef != 0) { - ClassClassScope classClassScope(&ns, classScope.info.header.classRef, classScope.visibility, &classScope.info); + if (classHelper.scope.info.header.classRef != classHelper.scope.reference && classHelper.scope.info.header.classRef != 0) { + ClassClassScope classClassScope(&ns, classHelper.scope.info.header.classRef, classHelper.scope.visibility, &classHelper.scope.info, classHelper.scope.reference); ns.moduleScope->loadClassInfo(classClassScope.info, classClassScope.reference, false); - compileClassClass(writer, classClassScope, classScope, current); + compileClassClass(writer, classClassScope, classHelper.scope, current); } break; } @@ -9338,8 +9368,10 @@ void Compiler :: declareModuleIdentifiers(ModuleScopeBase* moduleScope, SyntaxNo } } -void Compiler :: declareModule(ModuleScopeBase* moduleScope, SyntaxNode node, ExtensionMap* outerExtensionList) +bool Compiler :: declareModule(ModuleScopeBase* moduleScope, SyntaxNode node, ExtensionMap* outerExtensionList, bool& repeatMode, bool forced) { + bool declared = false; + SyntaxNode current = node.firstChild(); while (current != SyntaxKey::None) { if (current == SyntaxKey::Namespace) { @@ -9349,11 +9381,13 @@ void Compiler :: declareModule(ModuleScopeBase* moduleScope, SyntaxNode node, Ex ns.declareNamespace(current, false, true); // declare all module members - map symbol identifiers - ns.declareMembers(current); + declared |= ns.declareMembers(current, repeatMode, forced); } current = current.nextNode(); } + + return declared; } void Compiler :: declare(ModuleScopeBase* moduleScope, SyntaxTree& input, ExtensionMap* outerExtensionList) @@ -9366,7 +9400,18 @@ void Compiler :: declare(ModuleScopeBase* moduleScope, SyntaxTree& input, Extens declareModuleIdentifiers(moduleScope, root, outerExtensionList); // declare all members - declareModule(moduleScope, root, outerExtensionList); + bool repeatMode = true; + bool idle = false; + while (repeatMode) { + repeatMode = false; + + idle = !declareModule(moduleScope, root, outerExtensionList, repeatMode, false); + if (idle && repeatMode) { + repeatMode = false; + // if the last declaration was not successful, force it last time + idle = !declareModule(moduleScope, root, outerExtensionList, repeatMode, true); + } + } } void Compiler :: compile(ModuleScopeBase* moduleScope, SyntaxTree& input, BuildTree& output, ExtensionMap* outerExtensionList) @@ -9477,7 +9522,7 @@ void Compiler :: injectVirtualEmbeddableWrapper(SyntaxNode classNode, SyntaxKey inline bool isSingleDispatch(SyntaxNode node, SyntaxKey methodType, mssg_t message, mssg_t& targetMessage) { // !! currently constructor is not supporting single dispatch operation - if (methodType == SyntaxKey::Constructor) + if (methodType == SyntaxKey::Constructor && test(message, FUNCTION_MESSAGE)) return false; mssg_t foundMessage = 0; @@ -9508,6 +9553,8 @@ inline bool isSingleDispatch(SyntaxNode node, SyntaxKey methodType, mssg_t messa bool Compiler :: injectVirtualStrongTypedMultimethod(SyntaxNode classNode, SyntaxKey methodType, ModuleScopeBase& scope, mssg_t message, mssg_t resendMessage, ref_t outputRef, Visibility visibility, bool isExtension) { + bool variadicOne = (getFlags(resendMessage) & PREFIX_MESSAGE_MASK) == VARIADIC_MESSAGE; + ref_t actionRef = getAction(resendMessage); ref_t signRef = 0; ustr_t actionName = scope.module->resolveAction(actionRef, signRef); @@ -9540,8 +9587,10 @@ bool Compiler :: injectVirtualStrongTypedMultimethod(SyntaxNode classNode, Synta if (!actionName.compare(INVOKE_MESSAGE)) operationNode.appendChild(SyntaxKey::Message).appendChild(SyntaxKey::identifier, actionName); + size_t len = signLen - (variadicOne ? 1 : 0); + String arg; - for (size_t i = 0; i < signLen; i++) { + for (size_t i = 0; i < len; i++) { arg.copy("$"); arg.appendInt((int)i); @@ -9560,6 +9609,32 @@ bool Compiler :: injectVirtualStrongTypedMultimethod(SyntaxNode classNode, Synta else operationNode.appendChild(SyntaxKey::Expression).appendChild(SyntaxKey::Object).appendChild(SyntaxKey::identifier, arg.str()); } + if (variadicOne) { + // pass variadic argument + SyntaxNode param = methodNode.appendChild(SyntaxKey::Parameter); + param.appendChild(SyntaxKey::Attribute, V_VARIADIC); + param.appendChild(SyntaxKey::ArrayType).appendChild(SyntaxKey::Type, scope.buildins.superReference); + SyntaxNode nameParam = param.appendChild(SyntaxKey::Name); + nameParam.appendChild(SyntaxKey::identifier, "$x"); + + // pass variadic argument + if (signArgs[len] != scope.buildins.superReference) { + SyntaxNode castNode = operationNode.appendChild(SyntaxKey::Expression).appendChild(SyntaxKey::MessageOperation); + SyntaxNode castObject = castNode.appendChild(SyntaxKey::Object); + castObject.appendChild(SyntaxKey::Attribute, V_CONVERSION); + castObject.appendChild(SyntaxKey::Type, signArgs[len]); + castNode.appendChild(SyntaxKey::Message); + SyntaxNode varParamNode = castNode.appendChild(SyntaxKey::Expression).appendChild(SyntaxKey::Object); + varParamNode.appendChild(SyntaxKey::Attribute, V_VARIADIC); + varParamNode.appendChild(SyntaxKey::identifier, "$x"); + } + else { + SyntaxNode varParamNode = operationNode.appendChild(SyntaxKey::Expression).appendChild(SyntaxKey::Object); + varParamNode.appendChild(SyntaxKey::Attribute, V_VARIADIC); + varParamNode.appendChild(SyntaxKey::identifier, "$x"); + }; + } + return true; } @@ -9579,7 +9654,7 @@ void Compiler :: injectVirtualMultimethod(SyntaxNode classNode, SyntaxKey method // try to resolve an argument list in run-time if it is only a single dispatch and argument list is not weak // !! temporally do not support variadic arguments - if (isSingleDispatch(classNode, methodType, message, resendMessage) && ((message & PREFIX_MESSAGE_MASK) != VARIADIC_MESSAGE) && + if (isSingleDispatch(classNode, methodType, message, resendMessage) && injectVirtualStrongTypedMultimethod(classNode, methodType, scope, message, resendMessage, outputRef, visibility, isExtension)) { @@ -9929,8 +10004,9 @@ void Compiler::Namespace :: declare(SyntaxNode node, bool withMembers) // declare all module members - map symbol identifiers declareMemberIdentifiers(node); + bool dummy = false; if (withMembers) - declareMembers(node); + declareMembers(node, dummy, true); } void Compiler::Namespace :: declareNamespace(SyntaxNode node, bool ignoreImport, bool ignoreExtensions) @@ -10039,9 +10115,10 @@ void Compiler::Namespace:: declareMemberIdentifiers(SyntaxNode node) } } - -void Compiler::Namespace :: declareMembers(SyntaxNode node) +bool Compiler::Namespace :: declareMembers(SyntaxNode node, bool& repeatMode, bool forced) { + bool declared = false; + SyntaxNode current = node.firstChild(); while (current != SyntaxKey::None) { switch (current.key) { @@ -10050,21 +10127,30 @@ void Compiler::Namespace :: declareMembers(SyntaxNode node) Namespace subNamespace(compiler, &scope); subNamespace.declareNamespace(current, false, true); - subNamespace.declareMembers(current); + declared |= subNamespace.declareMembers(current, repeatMode, forced); break; } case SyntaxKey::Symbol: { - SymbolScope symbolScope(&scope, current.arg.reference, scope.defaultVisibility); + Symbol symbol(compiler, &scope, current.arg.reference, scope.defaultVisibility); + if (!symbol.isDeclared()) { + compiler->declareSymbol(symbol.scope, current); - compiler->declareSymbol(symbolScope, current); + declared = true; + } break; } case SyntaxKey::Class: { Class classHelper(compiler, &scope, current.arg.reference, scope.defaultVisibility); + if (!classHelper.isDeclared()) { + if (classHelper.isParentDeclared(current) || forced) { + classHelper.declare(current); - classHelper.declare(current); + declared = true; + } + else repeatMode = true; + } break; } case SyntaxKey::MetaExpression: @@ -10072,6 +10158,7 @@ void Compiler::Namespace :: declareMembers(SyntaxNode node) MetaScope metaScope(&scope, Scope::ScopeLevel::Namespace); compiler->evalStatement(metaScope, current); + current.setKey(SyntaxKey::Idle); break; } case SyntaxKey::Template: @@ -10082,6 +10169,7 @@ void Compiler::Namespace :: declareMembers(SyntaxNode node) break; } case SyntaxKey::TemplateCode: + case SyntaxKey::InlineTemplateExpr: { TemplateScope templateScope(&scope, 0, scope.defaultVisibility); compiler->declareTemplateCode(templateScope, current); @@ -10106,6 +10194,8 @@ void Compiler::Namespace :: declareMembers(SyntaxNode node) scope.declaredExtensions.clear(); } + + return declared; } // --- Compiler::Symbol --- @@ -10132,6 +10222,22 @@ Compiler::Class :: Class(Namespace& ns, ref_t reference, Visibility visibility) { } +bool Compiler::Class :: isParentDeclared(SyntaxNode node) +{ + SyntaxNode parentNode = node.findChild(SyntaxKey::Parent); + if (parentNode == SyntaxKey::None) + return true; + + SyntaxNode child = parentNode.firstChild(); + if (child != SyntaxKey::TemplateType && child != SyntaxKey::None) { + ref_t parentRef = compiler->resolveStrongTypeAttribute(scope, child, true, false); + + return scope.moduleScope->isDeclared(parentRef); + } + + return true; +} + void Compiler::Class :: declare(SyntaxNode node) { bool extensionDeclaration = isExtensionDeclaration(node); @@ -10302,6 +10408,14 @@ void Compiler::Class :: declareClassClass(ClassScope& classClassScope, SyntaxNod classClassScope.save(); } +void Compiler::Class :: load() +{ + scope.moduleScope->loadClassInfo(scope.info, scope.reference, false); + scope.abstractMode = test(scope.info.header.flags, elAbstract); + if (test(scope.info.header.flags, elExtension)) + scope.extensionClassRef = scope.getAttribute(ClassAttribute::ExtensionRef); +} + // --- Compiler::Method --- Compiler::Method :: Method(Class& cls) @@ -10310,6 +10424,42 @@ Compiler::Method :: Method(Class& cls) } +Compiler::Method::Method(Compiler* compiler, ClassScope& classScope) + : compiler(compiler), scope(&classScope) +{ +} + +void Compiler::Method :: compile(BuildTreeWriter& writer, SyntaxNode current) +{ + ClassScope* classScope = Scope::getScope(scope, Scope::ScopeLevel::Class); + + compiler->initializeMethod(*classScope, scope, current); + +#ifdef FULL_OUTOUT_INFO + IdentifierString messageName; + ByteCodeUtil::resolveMessageName(messageName, scope.module, scope.message); + + compiler->_errorProcessor->info(infoCurrentMethod, *messageName); +#endif // FULL_OUTOUT_INFO + + // if it is a dispatch handler + if (scope.message == scope.moduleScope->buildins.dispatch_message) { + compiler->compileDispatcherMethod(writer, scope, current, + test(classScope->info.header.flags, elWithGenerics), + test(classScope->info.header.flags, elWithVariadics)); + } + // if it is an abstract one + else if (scope.checkHint(MethodHint::Abstract)) { + compiler->compileAbstractMethod(writer, scope, current, classScope->abstractMode); + } + // if it is an initializer + else if (scope.checkHint(MethodHint::Initializer)) { + compiler->compileInitializerMethod(writer, scope, current.parentNode()); + } + // if it is a normal method + else compiler->compileMethod(writer, scope, current); +} + // --- Compiler::Code --- Compiler::Code :: Code(Method& method) @@ -10318,7 +10468,6 @@ Compiler::Code :: Code(Method& method) } - // --- Compiler::Expression --- Compiler::Expression :: Expression(Compiler* compiler, CodeScope& codeScope, BuildTreeWriter& writer) @@ -10394,8 +10543,10 @@ ObjectInfo Compiler::Expression :: compileReturning(SyntaxNode node, EAttr mode, if (codeScope == nullptr) scope.raiseError(errInvalidOperation, node); - writer->appendNode(BuildKey::OpenStatement); - addBreakpoint(*writer, findObjectNode(node), BuildKey::Breakpoint); + if (compiler->_withDebugInfo) { + writer->appendNode(BuildKey::OpenStatement); + addBreakpoint(*writer, findObjectNode(node), BuildKey::Breakpoint); + } ObjectInfo retVal = {}; SyntaxNode exprNode = node.findChild(SyntaxKey::Expression, SyntaxKey::CodeBlock); @@ -10439,8 +10590,10 @@ ObjectInfo Compiler::Expression :: compileReturning(SyntaxNode node, EAttr mode, scope.resolveAutoOutput(outputRef); } - writer->appendNode(BuildKey::EndStatement); - writer->appendNode(BuildKey::VirtualBreakoint); + if (compiler->_withDebugInfo) { + writer->appendNode(BuildKey::EndStatement); + writer->appendNode(BuildKey::VirtualBreakoint); + } writer->appendNode(BuildKey::goingToEOP); @@ -10682,23 +10835,134 @@ ObjectInfo Compiler::Expression :: compileLookAhead(SyntaxNode node, ref_t targe return retVal; } +ObjectInfo Compiler::Expression :: compileMessageOperationR(SyntaxNode node, SyntaxNode messageNode, ObjectInfo source, ArgumentsInfo& arguments, + ArgumentsInfo* updatedOuterArgs, ref_t expectedRef, bool propertyMode, bool probeMode, bool ignoreVariadics, ExpressionAttribute attrs) +{ + ObjectInfo retVal = {}; + + mssg_t messageRef = compiler->mapMessage(scope, messageNode, propertyMode, + source.kind == ObjectKind::Extension, probeMode); + + if (propertyMode || !test(messageRef, FUNCTION_MESSAGE)) + arguments.add(source); + + mssg_t resolvedMessage = 0; + + EAttr paramMode = EAttr::NoPrimitives; + if (source.mode != TargetMode::Weak) { + resolvedMessage = compiler->_logic->resolveSingleDispatch(*scope.moduleScope, + compiler->retrieveType(scope, source), messageRef); + if (!resolvedMessage && !ignoreVariadics) { + ref_t variadicMssg = resolveVariadicMessage(scope, messageRef); + + resolvedMessage = compiler->_logic->resolveSingleDispatch(*scope.moduleScope, + compiler->retrieveType(scope, source), variadicMssg); + if (resolvedMessage) { + messageRef = variadicMssg; + paramMode = paramMode | EAttr::WithVariadicArg; + } + } + } + + ref_t expectedSignRef = 0; + if (resolvedMessage) + scope.module->resolveAction(getAction(resolvedMessage), expectedSignRef); + + ArgumentListType argListType = ArgumentListType::Normal; + ref_t implicitSignatureRef = compileMessageArguments(messageNode, arguments, expectedSignRef, paramMode, + updatedOuterArgs, argListType); + + EAttr opMode = EAttr::None; + if (argListType == ArgumentListType::VariadicArgList || argListType == ArgumentListType::VariadicArgListWithTypecasting) { + messageRef |= VARIADIC_MESSAGE; + + opMode = argListType == Expression::ArgumentListType::VariadicArgList ? EAttr::WithVariadicArg : EAttr::WithVariadicArgCast; + } + + auto byRefResolution = resolveByRefHandler(source, expectedRef, messageRef, implicitSignatureRef, + EAttrs::test(attrs, EAttr::NoExtension)); + if (byRefResolution.resolved) { + ObjectInfo tempRetVal = declareTempLocal(expectedRef, false); + + addByRefRetVal(arguments, tempRetVal); + // adding mark for optimization routine + if (tempRetVal.kind == ObjectKind::TempLocalAddress) + writer->appendNode(BuildKey::ByRefOpMark, tempRetVal.argument); + + compileMessageOperation(node, source, byRefResolution, + implicitSignatureRef, arguments, opMode, updatedOuterArgs); + + retVal = tempRetVal; + } + else retVal = compileMessageOperation(node, source, messageRef, + implicitSignatureRef, arguments, opMode, updatedOuterArgs); + + return retVal; +} + +bool Compiler::Expression :: isDirectMethodCall(SyntaxNode& node) +{ + if (node == SyntaxKey::Message) { + return true; + } + else if (node == SyntaxKey::Object && node.firstChild() == SyntaxKey::identifier) { + if (node.nextNode().compare(SyntaxKey::Expression, SyntaxKey::None)) { + ustr_t name = node.firstChild().identifier(); + pos_t argCount = SyntaxTree::countSibling(node.nextNode(), SyntaxKey::Expression); + + ClassScope* classScope = Scope::getScope(scope, Scope::ScopeLevel::OwnerClass); + if (!classScope) + return false; + + mssg_t weakMessage = encodeMessage(scope.module->mapAction(name, 0, true), argCount + 1, 0); + if (compiler->_logic->isMessageSupported(classScope->info, weakMessage)) { + node.setKey(SyntaxKey::Message); + node.setArgumentReference(weakMessage); + + return true; + } + if (test(classScope->info.header.flags, elWithVariadics)) { + if (compiler->_logic->isMessageSupported(classScope->info, + encodeMessage(scope.module->mapAction(name, 0, true), 2, VARIADIC_MESSAGE))) + { + node.setKey(SyntaxKey::Message); + + return true; + } + + } + } + } + return false; +} + ObjectInfo Compiler::Expression :: compileMessageOperation(SyntaxNode node, ref_t expectedRef, ExpressionAttribute attrs) { ObjectInfo retVal = { }; + ObjectInfo source = {}; + ArgumentsInfo arguments; ArgumentsInfo updatedOuterArgs; + ArgumentListType argListType = ArgumentListType::Normal; SyntaxNode current = node.firstChild(); - ObjectInfo source = compileObject(current, EAttr::Parameter, &updatedOuterArgs); + if (isDirectMethodCall(current)) { + // if direct method call is possible (without specifying target) + source = scope.mapSelf(true); + + return compileMessageOperationR(node, current, source, arguments, + &updatedOuterArgs, expectedRef, false, false, false, attrs); + } + else source = compileObject(current, EAttr::Parameter, &updatedOuterArgs); + bool probeMode = source.mode == TargetMode::Probe; switch (source.mode) { case TargetMode::External: case TargetMode::WinApi: { - bool dummy = false; - compileMessageArguments(current, arguments, 0, EAttr::None, nullptr, dummy); - if (dummy) + compileMessageArguments(current, arguments, 0, EAttr::None, nullptr, argListType); + if (argListType != ArgumentListType::Normal) scope.raiseError(errInvalidOperation, current); retVal = compileExternalOp(node, source.reference, @@ -10707,9 +10971,8 @@ ObjectInfo Compiler::Expression :: compileMessageOperation(SyntaxNode node, } case TargetMode::CreatingArray: { - bool dummy = false; - compileMessageArguments(current, arguments, 0, EAttr::NoPrimitives, nullptr, dummy); - if (dummy) + compileMessageArguments(current, arguments, 0, EAttr::NoPrimitives, nullptr, argListType); + if (argListType != ArgumentListType::Normal) scope.raiseError(errInvalidOperation, current); retVal = compileNewArrayOp(node, source, expectedRef, arguments); @@ -10717,9 +10980,8 @@ ObjectInfo Compiler::Expression :: compileMessageOperation(SyntaxNode node, } case TargetMode::Creating: { - bool dummy = false; - ref_t signRef = compileMessageArguments(current, arguments, 0, EAttr::NoPrimitives, nullptr, dummy); - if (dummy) + ref_t signRef = compileMessageArguments(current, arguments, 0, EAttr::NoPrimitives, nullptr, argListType); + if (argListType != ArgumentListType::Normal) scope.raiseError(errInvalidOperation, current); retVal = compileNewOp(node, Compiler::mapClassSymbol(scope, @@ -10728,12 +10990,7 @@ ObjectInfo Compiler::Expression :: compileMessageOperation(SyntaxNode node, } case TargetMode::Casting: { - bool dummy = false; - compileMessageArguments(current, arguments, 0, EAttr::NoPrimitives, nullptr, dummy); - if (arguments.count() == 1 && !dummy) { - retVal = convertObject(current, arguments[0], compiler->retrieveStrongType(scope, source), false, true); - } - else scope.raiseError(errInvalidOperation, node); + retVal = compileMessageOperationR(source, current, false); break; } default: @@ -10742,47 +10999,9 @@ ObjectInfo Compiler::Expression :: compileMessageOperation(SyntaxNode node, source = validateObject(node, source, 0, true, true, false); current = current.nextNode(); - mssg_t messageRef = compiler->mapMessage(scope, current, false, - source.kind == ObjectKind::Extension, probeMode); - - if (!test(messageRef, FUNCTION_MESSAGE)) - arguments.add(source); - - mssg_t resolvedMessage = source.mode != TargetMode::Weak ? compiler->_logic->resolveSingleDispatch(*scope.moduleScope, - compiler->retrieveType(scope, source), messageRef) : 0; - - ref_t expectedSignRef = 0; - if (resolvedMessage) - scope.module->resolveAction(getAction(resolvedMessage), expectedSignRef); - - bool withVariadicArg = false; - ref_t implicitSignatureRef = compileMessageArguments(current, arguments, expectedSignRef, EAttr::NoPrimitives, - &updatedOuterArgs, withVariadicArg); - - EAttr opMode = EAttr::None; - if (withVariadicArg) { - messageRef |= VARIADIC_MESSAGE; - - opMode = EAttr::WithVariadicArg; - } - auto byRefResolution = resolveByRefHandler(source, expectedRef, messageRef, implicitSignatureRef, - EAttrs::test(attrs, EAttr::NoExtension)); - if (byRefResolution.resolved) { - ObjectInfo tempRetVal = declareTempLocal(expectedRef, false); - - addByRefRetVal(arguments, tempRetVal); - // adding mark for optimization routine - if (tempRetVal.kind == ObjectKind::TempLocalAddress) - writer->appendNode(BuildKey::ByRefOpMark, tempRetVal.argument); - - compileMessageOperation(node, source, byRefResolution, - implicitSignatureRef, arguments, opMode, &updatedOuterArgs); - - retVal = tempRetVal; - } - else retVal = compileMessageOperation(node, source, messageRef, - implicitSignatureRef, arguments, opMode, &updatedOuterArgs); + retVal = compileMessageOperationR(node, current, source, arguments, + &updatedOuterArgs, expectedRef, false, probeMode, false, attrs); break; } @@ -10802,49 +11021,13 @@ ObjectInfo Compiler::Expression :: compilePropertyOperation(SyntaxNode node, ref if (invalidObjectMode(source)) scope.raiseError(errInvalidOperation, node); - arguments.add(source); - // NOTE : the operation target shouldn't be a primtive type source = validateObject(node, source, 0, true, true, false); current = current.nextNode(); - mssg_t messageRef = compiler->mapMessage(scope, current, true, - source.kind == ObjectKind::Extension, false); - - mssg_t resolvedMessage = compiler->_logic->resolveSingleDispatch(*scope.moduleScope, - compiler->retrieveType(scope, source), messageRef); - - bool variadicArgList = false; - ref_t expectedSignRef = 0; - if (resolvedMessage) - scope.module->resolveAction(getAction(resolvedMessage), expectedSignRef); - ref_t implicitSignatureRef = compileMessageArguments(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; - } - - auto byRefResolution = resolveByRefHandler(source, expectedRef, - messageRef, implicitSignatureRef, EAttrs::test(attrs, EAttr::NoExtension)); - if (byRefResolution.resolved) { - ObjectInfo tempRetVal = declareTempLocal(expectedRef, false); - - addByRefRetVal(arguments, tempRetVal); - if (tempRetVal.kind == ObjectKind::TempLocalAddress) - writer->appendNode(BuildKey::ByRefOpMark, tempRetVal.argument); - - compileMessageOperation(node, source, byRefResolution, - implicitSignatureRef, arguments, opMode, &outerArgsToUpdate); - - retVal = tempRetVal; - } - else retVal = compileMessageOperation(node, source, { messageRef }, - implicitSignatureRef, arguments, opMode, &outerArgsToUpdate); + retVal = compileMessageOperationR(node, current, source, arguments, + &outerArgsToUpdate, expectedRef, true, false, true, attrs); return retVal; } @@ -10913,11 +11096,70 @@ void Compiler::Expression :: compileYieldOperation(SyntaxNode node) writer->closeNode(); } +ObjectInfo Compiler::Expression :: compileIndexAssignOperation(SyntaxNode node, SyntaxNode rnode, int operatorId, ref_t expectedRef) +{ + SyntaxNode lnode = node.firstChild(); + SyntaxNode inode = lnode.nextNode(); + + ArgumentsInfo updatedOuterArgs; + + //BuildKey op = BuildKey::None; + ObjectInfo loperand = compile(lnode, 0, + EAttr::Parameter | EAttr::RetValExpected | EAttr::LookaheadExprMode, &updatedOuterArgs); + ObjectInfo ioperand = compile(inode, 0, + EAttr::Parameter | EAttr::RetValExpected | EAttr::LookaheadExprMode, &updatedOuterArgs); + ObjectInfo roperand = compile(rnode, 0, + EAttr::Parameter | EAttr::RetValExpected | EAttr::LookaheadExprMode, &updatedOuterArgs); + + // get the array item + ArgumentsInfo arguments; + arguments.add(loperand); + arguments.add(ioperand); + + ObjectInfo tempInfo = compileOperation(node, arguments, INDEX_OPERATOR_ID, 0, &updatedOuterArgs); + + // make an operation with it + switch (operatorId) { + case ADD_ASSIGN_OPERATOR_ID: + operatorId = ADD_OPERATOR_ID; + break; + case SUB_ASSIGN_OPERATOR_ID: + operatorId = SUB_OPERATOR_ID; + break; + case MUL_ASSIGN_OPERATOR_ID: + operatorId = MUL_OPERATOR_ID; + break; + case DIV_ASSIGN_OPERATOR_ID: + operatorId = DIV_OPERATOR_ID; + break; + default: + break; + } + + arguments.clear(); + arguments.add(tempInfo); + arguments.add(roperand); + tempInfo = compileOperation(node, arguments, operatorId, 0, &updatedOuterArgs); + + // set the updated array item + arguments.clear(); + arguments.add(loperand); + arguments.add(tempInfo); + arguments.add(ioperand); + + return compileOperation(node, arguments, SET_INDEXER_OPERATOR_ID, expectedRef, &updatedOuterArgs); +} + ObjectInfo Compiler::Expression :: compileAssignOperation(SyntaxNode node, int operatorId, ref_t expectedRef) { SyntaxNode lnode = node.firstChild(); SyntaxNode rnode = lnode.nextNode(); + if (lnode == SyntaxKey::IndexerOperation) { + // HOTFIX : if it is an operation with an array item + return compileIndexAssignOperation(lnode, rnode, operatorId, expectedRef); + } + ArgumentsInfo updatedOuterArgs; ObjectInfo loperand = compile(lnode, 0, EAttr::Parameter, &updatedOuterArgs); ObjectInfo roperand = {}; @@ -11057,17 +11299,20 @@ ObjectInfo Compiler::Expression :: compileBoolOperation(SyntaxNode node, int ope } } +inline mssg_t mapTypecasting(ModuleBase* module, ref_t targetRef) +{ + ref_t signRef = module->mapSignature(&targetRef, 1, false); + ref_t actionRef = module->mapAction(CAST_MESSAGE, signRef, false); + + return encodeMessage(actionRef, 1, CONVERSION_MESSAGE); +} + ObjectInfo Compiler::Expression :: typecastObject(SyntaxNode node, ObjectInfo source, ref_t targetRef) { if (targetRef == scope.moduleScope->buildins.superReference) return source; - ustr_t refName2 = scope.module->resolveReference(targetRef); - - ref_t signRef = scope.module->mapSignature(&targetRef, 1, false); - ref_t actionRef = scope.module->mapAction(CAST_MESSAGE, signRef, false); - - mssg_t typecastMssg = encodeMessage(actionRef, 1, CONVERSION_MESSAGE); + mssg_t typecastMssg = mapTypecasting(scope.module, targetRef); ArgumentsInfo arguments; arguments.add(source); @@ -11233,18 +11478,37 @@ ObjectInfo Compiler::Expression :: compileAltOperation(SyntaxNode node) ObjectInfo target = {}; SyntaxNode current = node.firstChild(); - if (current == SyntaxKey::MessageOperation || current == SyntaxKey::PropertyOperation) { - SyntaxNode objNode = current.firstChild(); + switch (current.key) { + case SyntaxKey::MessageOperation: + case SyntaxKey::PropertyOperation: + { + SyntaxNode objNode = current.firstChild(); - target = compileObject(objNode, EAttr::Parameter, nullptr); + target = compileObject(objNode, EAttr::Parameter, nullptr); - writer->newNode(BuildKey::AltOp, ehLocal.argument); + writer->newNode(BuildKey::AltOp, ehLocal.argument); - writer->newNode(BuildKey::Tape); - compileMessageOperationR(target, objNode.nextNode(), current == SyntaxKey::PropertyOperation); - writer->closeNode(); + writer->newNode(BuildKey::Tape); + compileMessageOperationR(target, objNode.nextNode(), current == SyntaxKey::PropertyOperation); + writer->closeNode(); + break; + } + case SyntaxKey::CodeBlock: + case SyntaxKey::Object: + { + writer->newNode(BuildKey::AltOp, ehLocal.argument); + + writer->newNode(BuildKey::Tape); + compile(current, 0, EAttr::Parameter, nullptr); + writer->closeNode(); + + target = { ObjectKind::Nil }; + break; + } + default: + scope.raiseError(errInvalidOperation, node); + break; } - else scope.raiseError(errInvalidOperation, node); writer->newNode(BuildKey::Tape); SyntaxNode altNode = current.nextNode().firstChild(); @@ -11294,9 +11558,23 @@ ObjectInfo Compiler::Expression :: compileIsNilOperation(SyntaxNode node) else if (current == SyntaxKey::Object) { loperand = compileObject(current, EAttr::Parameter, nullptr); } - else scope.raiseError(errInvalidOperation, node); + else { + writer->newNode(BuildKey::AltOp, ehLocal.argument); - SyntaxNode altNode = current.nextNode(); + writer->newNode(BuildKey::Tape); + loperand = compile(current, 0, EAttr::Parameter | EAttr::RetValExpected, nullptr); + writer->closeNode(); + + writer->newNode(BuildKey::Tape); + writer->appendNode(BuildKey::NilReference, 0); + writer->closeNode(); + + writer->closeNode(); + + loperand = saveToTempLocal({ ObjectKind::Object }); + } + + SyntaxNode altNode = current.nextNode(SyntaxKey::DeclarationMask); ObjectInfo roperand = compile(altNode, 0, EAttr::Parameter, nullptr); writeObjectInfo(roperand, node); @@ -11603,6 +11881,11 @@ ObjectInfo Compiler::Expression :: validateObject(SyntaxNode node, ObjectInfo re retVal = saveToTempLocal(retVal); } if (targetRef) { + if (retVal.kind == ObjectKind::VArgParam && retVal.mode == TargetMode::UnboxingAndTypecastingVarArgument && retVal.typeInfo.elementRef == targetRef) { + // HOTFIX : allow to pass the check for explicit variadic argument typecasting + return retVal; + } + retVal = convertObject(node, retVal, targetRef, dynamicRequired, false); if (paramMode && hasToBePresaved(retVal)) retVal = saveToTempLocal(retVal); @@ -11666,41 +11949,51 @@ ObjectInfo Compiler::Expression :: compileNewOp(SyntaxNode node, ObjectInfo sour } ref_t Compiler::Expression :: compileMessageArguments(SyntaxNode current, ArgumentsInfo& arguments, ref_t expectedSignRef, EAttr mode, - ArgumentsInfo* updatedOuterArgs, bool& variadicArgList) + ArgumentsInfo* updatedOuterArgs, ArgumentListType& argListType) { + bool variadicArg = EAttrs::testAndExclude(mode, EAttr::WithVariadicArg); + EAttr paramMode = EAttr::Parameter | EAttr::RetValExpected; if (EAttrs::testAndExclude(mode, EAttr::NoPrimitives)) paramMode = paramMode | EAttr::NoPrimitives; // compile the message argument list ref_t signatures[ARG_COUNT] = { 0 }; - ref_t signatureLen = 0; + size_t signatureLen = 0; ref_t superReference = scope.moduleScope->buildins.superReference; + size_t signatureMaxLength = 0; if (expectedSignRef) - scope.module->resolveSignature(expectedSignRef, signatures); + signatureMaxLength = scope.module->resolveSignature(expectedSignRef, signatures); while (current != SyntaxKey::None) { if (current == SyntaxKey::Expression) { + if (variadicArg && signatureLen == signatureMaxLength) { + // for variadic last argument - stay at the same position + signatureLen--; + } + // try to recognize the message signature // NOTE : signatures[signatureLen] contains expected parameter type if expectedSignRef is provided auto argInfo = compile(current, signatures[signatureLen], paramMode, updatedOuterArgs); - if (argInfo.mode == TargetMode::UnboxingVarArgument) { + if ((argInfo.mode == TargetMode::UnboxingVarArgument || argInfo.mode == TargetMode::UnboxingAndTypecastingVarArgument) && signatureLen < ARG_COUNT) { if (argInfo.typeInfo.elementRef) { signatures[signatureLen++] = argInfo.typeInfo.elementRef; } else signatures[signatureLen++] = scope.moduleScope->buildins.superReference; - if (!variadicArgList) { - variadicArgList = true; + if (argListType == ArgumentListType::Normal) { + argListType = argInfo.mode == TargetMode::UnboxingVarArgument + ? ArgumentListType::VariadicArgList : ArgumentListType::VariadicArgListWithTypecasting; } else scope.raiseError(errInvalidOperation, current); } else { ref_t argRef = compiler->retrieveStrongType(scope, argInfo); - if (signatureLen >= ARG_COUNT) { + if (signatureLen >= ARG_COUNT || (variadicArg && signatureLen == signatureMaxLength - 1)) { + // for variadic last argument - do not overwrite the signature signatureLen++; } else if (argRef) { @@ -11775,6 +12068,16 @@ ObjectInfo Compiler::Expression :: compileExternalOp(SyntaxNode node, ref_t exte { writer->appendNode(BuildKey::SavingNInStack, i - 1); } + else if (compiler->_logic->isCompatible(*scope.moduleScope, { V_INT16 }, + arg.typeInfo, true)) + { + writer->appendNode(BuildKey::SavingNInStack, i - 1); + } + else if (compiler->_logic->isCompatible(*scope.moduleScope, { V_INT8 }, + arg.typeInfo, true)) + { + writer->appendNode(BuildKey::SavingNInStack, i - 1); + } else writer->appendNode(BuildKey::SavingInStack, i - 1); // !! temporally - passing dynamic references to the exteranl routines should not be allowed break; } @@ -11980,6 +12283,12 @@ ObjectInfo Compiler::Expression :: convertObject(SyntaxNode node, ObjectInfo sou } else source = compileNativeConversion(node, source, conversionRoutine.operationKey); } + else if (source.kind == ObjectKind::VArgParam && source.mode == TargetMode::UnboxingVarArgument) { + source.mode = TargetMode::UnboxingAndTypecastingVarArgument; + source.typeInfo = { V_ARGARRAY, targetRef }; + + return source; + } else source = typecastObject(node, source, targetRef); } @@ -12084,7 +12393,8 @@ ObjectInfo Compiler::Expression :: declareTempLocal(ref_t typeRef, bool dynamicO ObjectInfo Compiler::Expression :: compileMessageOperation(SyntaxNode node, ObjectInfo target, MessageResolution resolution, ref_t implicitSignatureRef, ArgumentsInfo& arguments, ExpressionAttributes mode, ArgumentsInfo* updatedOuterArgs) { - bool argUnboxingRequired = EAttrs::testAndExclude(mode.attrs, EAttr::WithVariadicArg); + bool vargCastingRequired = EAttrs::testAndExclude(mode.attrs, EAttr::WithVariadicArgCast); + bool argUnboxingRequired = vargCastingRequired || EAttrs::testAndExclude(mode.attrs, EAttr::WithVariadicArg); bool checkShortCircle = EAttrs::testAndExclude(mode.attrs, EAttr::CheckShortCircle); bool allowPrivateCall = EAttrs::testAndExclude(mode.attrs, EAttr::AllowPrivateCall); @@ -12116,7 +12426,7 @@ ObjectInfo Compiler::Expression :: compileMessageOperation(SyntaxNode node, Obje if (found) { switch (result.visibility) { case Visibility::Private: - if (allowPrivateCall || isSelfCall(target)) { + if (allowPrivateCall || isSelfCall(target) || isClassClassOperation(scope, target)) { resolution.message = result.message; } else found = false; @@ -12236,8 +12546,12 @@ ObjectInfo Compiler::Expression :: compileMessageOperation(SyntaxNode node, Obje if (operation != BuildKey::None) { bool targetOverridden = (target != arguments[0]); ObjectInfo lenLocal = {}; + ArgumentListType argListType = vargCastingRequired ? + ArgumentListType::VariadicArgListWithTypecasting + : (argUnboxingRequired ? ArgumentListType::VariadicArgList : ArgumentListType::Normal); + writeMessageArguments(target, resolution.message, arguments, lenLocal, - resolution.stackSafeAttr, targetOverridden, found, argUnboxingRequired, result.stackSafe); + resolution.stackSafeAttr, targetOverridden, found, argListType, result.stackSafe); if (!targetOverridden) { writer->appendNode(BuildKey::Argument, 0); @@ -12288,7 +12602,6 @@ ObjectInfo Compiler::Expression :: compileOperation(SyntaxNode node, SyntaxNode ObjectInfo loperand = compile(lnode, 0, EAttr::Parameter | EAttr::RetValExpected | EAttr::LookaheadExprMode, &updatedOuterArgs); ObjectInfo roperand = {}; - ObjectInfo ioperand = {}; ArgumentsInfo arguments; arguments.add(loperand); @@ -12924,52 +13237,33 @@ ObjectInfo Compiler::Expression :: compileBranchingOperands(SyntaxNode rnode, Sy ObjectInfo Compiler::Expression :: compileMessageOperationR(ObjectInfo target, SyntaxNode messageNode, bool propertyMode) { ArgumentsInfo arguments; - ArgumentsInfo updatedOuterArgs; switch (target.mode) { case TargetMode::Casting: { - bool dummy = false; - compileMessageArguments(messageNode, arguments, 0, EAttr::NoPrimitives, &updatedOuterArgs, dummy); - if (arguments.count() == 1 && !dummy) { - return convertObject(messageNode, arguments[0], compiler->retrieveStrongType(scope, target), false, true); + ArgumentListType argListType = ArgumentListType::Normal; + compileMessageArguments(messageNode, arguments, 0, EAttr::NoPrimitives, nullptr, argListType); + if (arguments.count() == 1) { + if (argListType == ArgumentListType::VariadicArgList) { + arguments[0].mode = TargetMode::UnboxingAndTypecastingVarArgument; + arguments[0].typeInfo = { V_ARGARRAY, compiler->retrieveStrongType(scope, target) }; + + return arguments[0]; + } + else return convertObject(messageNode, arguments[0], compiler->retrieveStrongType(scope, target), false, true); } else scope.raiseError(errInvalidOperation, messageNode); break; } default: { + ArgumentsInfo updatedOuterArgs; + // NOTE : the operation target shouldn't be a primitive type ObjectInfo source = validateObject(messageNode, target, 0, true, true, false); - mssg_t messageRef = compiler->mapMessage(scope, messageNode, propertyMode, false, false); - - mssg_t resolvedMessage = compiler->_logic->resolveSingleDispatch(*scope.moduleScope, - compiler->retrieveType(scope, source), messageRef); - - ref_t expectedSignRef = 0; - if (resolvedMessage) - scope.module->resolveAction(getAction(resolvedMessage), expectedSignRef); - - if (!test(messageRef, FUNCTION_MESSAGE)) { - arguments.add(source); - } - - bool withVariadicArg = false; - ref_t implicitSignatureRef = compileMessageArguments(messageNode, arguments, expectedSignRef, - EAttr::NoPrimitives, &updatedOuterArgs, withVariadicArg); - - EAttr opMode = EAttr::None; - if (withVariadicArg) { - messageRef |= VARIADIC_MESSAGE; - - opMode = EAttr::WithVariadicArg; - } - - return compileMessageOperation(messageNode, source, messageRef, - implicitSignatureRef, arguments, opMode, &updatedOuterArgs); - - break; + return compileMessageOperationR(messageNode, messageNode, source, arguments, &updatedOuterArgs, 0, + propertyMode, false, false, EAttr::None); } } @@ -13493,7 +13787,7 @@ void Compiler::Expression :: showContextInfo(mssg_t message, ref_t targetRef) void Compiler::Expression :: writeMessageArguments(ObjectInfo& target, mssg_t message, ArgumentsInfo& arguments, ObjectInfo& lenLocal, int& stackSafeAttr, - bool targetOverridden, bool found, bool argUnboxingRequired, bool stackSafe) + bool targetOverridden, bool found, ArgumentListType argType, bool stackSafe) { if (targetOverridden) { target = boxArgument(target, stackSafe, false, false); @@ -13503,7 +13797,7 @@ void Compiler::Expression :: writeMessageArguments(ObjectInfo& target, stackSafeAttr = 0; pos_t counter = arguments.count_pos(); - if (argUnboxingRequired) { + if (argType == ArgumentListType::VariadicArgListWithTypecasting || argType == ArgumentListType::VariadicArgList) { counter--; ObjectInfo lenLocal = declareTempLocal(scope.moduleScope->buildins.intReference, false); @@ -13515,10 +13809,25 @@ void Compiler::Expression :: writeMessageArguments(ObjectInfo& target, 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(); + if (argType == ArgumentListType::VariadicArgListWithTypecasting) { + // if we need to typecast the each item of the variadic argument list + ObjectInfo tempLocal = declareTempLocal(scope.moduleScope->buildins.intReference, false); + mssg_t typecastMssg = mapTypecasting(scope.module, arguments[counter].typeInfo.elementRef); + + writer->newNode(BuildKey::UnboxAndCallMessage, arguments[counter].argument); + writer->appendNode(BuildKey::Index, counter); + writer->appendNode(BuildKey::Length, lenLocal.reference); + writer->appendNode(BuildKey::TempVar, tempLocal.reference); + writer->appendNode(BuildKey::Message, typecastMssg); + writer->closeNode(); + + } + else { + 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 @@ -13532,7 +13841,7 @@ void Compiler::Expression :: writeMessageArguments(ObjectInfo& target, argMask <<= 1; } - if (isOpenArg(message) && !argUnboxingRequired) { + if (isOpenArg(message) && argType == ArgumentListType::Normal) { // NOTE : in case of unboxing variadic argument, the terminator is already copied arguments.add({ ObjectKind::Terminator }); counter++; @@ -13553,7 +13862,17 @@ bool Compiler::Expression :: resolveAutoType(ObjectInfo source, ObjectInfo& targ if (!compiler->_logic->validateAutoType(*scope.moduleScope, sourceRef)) return false; - return scope.resolveAutoType(target, source.typeInfo); + int size = 0; + int extra = 0; + if (compiler->_logic->isEmbeddableStruct(*scope.moduleScope, sourceRef)) { + // Bad luck : it is a auto structure, we have to reallocate the variable + size = align(compiler->_logic->defineStructSize(*scope.moduleScope, sourceRef).size, + scope.moduleScope->rawStackAlingment); + + extra = allocateLocalAddress(scope, size, false); + } + + return scope.resolveAutoType(target, { sourceRef }, size, extra); } ObjectInfo Compiler::Expression :: boxArgument(ObjectInfo info, bool stackSafe, bool boxInPlace, bool allowingRefArg, ref_t targetRef) diff --git a/elenasrc3/elc/compiler.h b/elenasrc3/elc/compiler.h index 05cf54fcd5..7817a77b2e 100644 --- a/elenasrc3/elc/compiler.h +++ b/elenasrc3/elc/compiler.h @@ -110,6 +110,7 @@ namespace elena_lang LocalUnboxingRequired, ArrayContent, UnboxingVarArgument, + UnboxingAndTypecastingVarArgument, BoxingPtr, Conditional, ConditionalUnboxingRequired, @@ -413,10 +414,10 @@ namespace elena_lang else return {}; } - virtual bool resolveAutoType(ObjectInfo& info, TypeInfo typeInfo) + virtual bool resolveAutoType(ObjectInfo& info, TypeInfo typeInfo, int size, int extra) { if (parent) { - return parent->resolveAutoType(info, typeInfo); + return parent->resolveAutoType(info, typeInfo, size, extra); } else return false; } @@ -676,11 +677,14 @@ namespace elena_lang { // the reference to the proper class info (used for resolving class constants) ClassInfo* classInfo; + ref_t classInfoRef; public: + ref_t getProperClassRef() { return classInfoRef; } + ObjectInfo mapField(ustr_t identifier, ExpressionAttribute attr) override; - ClassClassScope(Scope* parent, ref_t reference, Visibility visibility, ClassInfo* classInfo); + ClassClassScope(Scope* parent, ref_t reference, Visibility visibility, ClassInfo* classInfo, ref_t classInfoRef); }; struct MethodScope : Scope @@ -729,7 +733,7 @@ namespace elena_lang ObjectInfo mapIdentifier(ustr_t identifier, bool referenceOne, ExpressionAttribute attr) override; ObjectInfo mapParameter(ustr_t identifier, ExpressionAttribute attr); - ObjectInfo mapSelf(bool memberMode = true); + ObjectInfo mapSelf(bool memberMode = true, bool ownerClass = false); ObjectInfo mapSuper(); bool isPrivate() const @@ -860,7 +864,7 @@ namespace elena_lang return scope ? scope->isExtension : false; } - bool resolveAutoType(ObjectInfo& info, TypeInfo typeInfo) override; + bool resolveAutoType(ObjectInfo& info, TypeInfo typeInfo, int size, int extra) override; void markAsAssigned(ObjectInfo object) override; @@ -947,11 +951,11 @@ namespace elena_lang return scope ? scope->reference : 0; } - ObjectInfo mapSelf() + ObjectInfo mapSelf(bool ownerClass = false) { MethodScope* scope = Scope::getScope(*this, ScopeLevel::Method); if (scope) { - return scope->mapSelf(!scope->isExtension); + return scope->mapSelf(!scope->isExtension, ownerClass); } else return {}; } @@ -1052,7 +1056,7 @@ namespace elena_lang void declareNamespace(SyntaxNode node, bool ignoreImport = false, bool ignoreExtensions = false); void declareMemberIdentifiers(SyntaxNode node); - void declareMembers(SyntaxNode node); + bool declareMembers(SyntaxNode node, bool& repeatMode, bool forced); public: NamespaceScope scope; @@ -1092,6 +1096,11 @@ namespace elena_lang public: SymbolScope scope; + bool isDeclared() + { + return scope.moduleScope->isSymbolDeclared(scope.reference); + } + Symbol(Namespace& ns, ref_t reference, Visibility visibility); Symbol(Compiler* compiler, NamespaceScope* parent, ref_t reference, Visibility visibility); }; @@ -1108,8 +1117,17 @@ namespace elena_lang void declareClassClass(ClassScope& classClassScope, SyntaxNode node, ref_t parentRef); public: + bool isParentDeclared(SyntaxNode node); + + bool isDeclared() + { + return scope.moduleScope->isDeclared(scope.reference); + } + void declare(SyntaxNode node); + void load(); + Class(Compiler* compiler, Scope* parent, ref_t reference, Visibility visibility); Class(Namespace& ns, ref_t reference, Visibility visibility); }; @@ -1122,7 +1140,10 @@ namespace elena_lang MethodScope scope; public: + void compile(BuildTreeWriter& writer, SyntaxNode current); + Method(Class& cls); + Method(Compiler* compiler, ClassScope& classScope); }; class Code @@ -1140,10 +1161,19 @@ namespace elena_lang { friend class Compiler; + enum class ArgumentListType : int + { + Normal = 0, + VariadicArgList = 1, + VariadicArgListWithTypecasting = 2, + }; + Compiler* compiler; ExprScope scope; BuildTreeWriter* writer; + bool isDirectMethodCall(SyntaxNode& node); + ObjectInfo compileLookAhead(SyntaxNode node, ref_t targetRef, ExpressionAttribute attrs); @@ -1153,6 +1183,7 @@ namespace elena_lang ObjectInfo compileOperation(SyntaxNode node, int operatorId, ref_t expectedRef, ExpressionAttribute mode); ObjectInfo compileSpecialOperation(SyntaxNode node, int operatorId, ref_t expectedRef); ObjectInfo compileAssignOperation(SyntaxNode node, int operatorId, ref_t expectedRef); + ObjectInfo compileIndexAssignOperation(SyntaxNode lnode, SyntaxNode rnode, int operatorId, ref_t expectedRef); ObjectInfo compileBoolOperation(SyntaxNode node, int operatorId); ObjectInfo compileIndexerOperation(SyntaxNode node, int operatorId, ref_t expectedRef); ObjectInfo compileBranchingOperation(SyntaxNode node, int operatorId, bool retValExpected, bool withoutDebugInfo); @@ -1165,6 +1196,8 @@ namespace elena_lang ObjectInfo compileAssigning(SyntaxNode loperand, SyntaxNode roperand, ExpressionAttribute mode); ObjectInfo compileMessageOperationR(ObjectInfo target, SyntaxNode node, bool propertyMode); + ObjectInfo compileMessageOperationR(SyntaxNode node, SyntaxNode messageNode, ObjectInfo source, ArgumentsInfo& arguments, + ArgumentsInfo* updatedOuterArgs, ref_t expectedRef, bool propertyMode, bool probeMode, bool ignoreVariadics, ExpressionAttribute attrs); ObjectInfo compileLoop(SyntaxNode node, ExpressionAttribute mode); ObjectInfo compileExtern(SyntaxNode node, ExpressionAttribute mode); @@ -1201,7 +1234,7 @@ namespace elena_lang SyntaxNode r2node, int operatorId, ArgumentsInfo* updatedOuterArgs, bool retValExpected, bool withoutDebugInfo); ref_t compileMessageArguments(SyntaxNode current, ArgumentsInfo& arguments, ref_t expectedSignRef, ExpressionAttribute mode, - ArgumentsInfo* updatedOuterArgs, bool& variadicArgList); + ArgumentsInfo* updatedOuterArgs, ArgumentListType& argListType); MessageResolution resolveByRefHandler(ObjectInfo source, ref_t expectedRef, mssg_t weakMessage, ref_t& signatureRef, bool noExtensions); MessageResolution resolveMessageAtCompileTime(ObjectInfo target, mssg_t weakMessage, ref_t implicitSignatureRef, bool ignoreExtensions, @@ -1244,7 +1277,7 @@ namespace elena_lang void showContextInfo(mssg_t message, ref_t targetRef); void writeMessageArguments(ObjectInfo& target, mssg_t message, ArgumentsInfo& arguments, ObjectInfo& lenLocal, - int& stackSafeAttr, bool targetOverridden, bool found, bool argUnboxingRequired, bool stackSafe); + int& stackSafeAttr, bool targetOverridden, bool found, ArgumentListType argType, bool stackSafe); void convertIntLiteralForOperation(SyntaxNode node, int operatorId, ArgumentsInfo& messageArguments); @@ -1279,6 +1312,7 @@ namespace elena_lang friend class Namespace; friend class Class; + friend class Method; friend class Symbol; friend class Expression; @@ -1297,6 +1331,7 @@ namespace elena_lang bool _evaluateOp; bool _verbose; bool _noValidation; + bool _withDebugInfo; void loadMetaData(ModuleScopeBase* moduleScope, ForwardResolverBase* forwardResolver, ustr_t name); @@ -1373,6 +1408,8 @@ namespace elena_lang static int allocateLocalAddress(Scope& scope, int size, bool binaryArray); + static bool isClassClassOperation(Scope& scope, ObjectInfo target); + ref_t declareMultiType(Scope& scope, SyntaxNode& node, ref_t elementRef); void declareClassAttributes(ClassScope& scope, SyntaxNode node, ref_t& fldeclaredFlagsags); @@ -1462,7 +1499,7 @@ namespace elena_lang void copyParentNamespaceExtensions(NamespaceScope& source, NamespaceScope& target); void declareModuleIdentifiers(ModuleScopeBase* moduleScope, SyntaxNode node, ExtensionMap* outerExtensionList); - void declareModule(ModuleScopeBase* moduleScope, SyntaxNode node, ExtensionMap* outerExtensionList); + bool declareModule(ModuleScopeBase* moduleScope, SyntaxNode node, ExtensionMap* outerExtensionList, bool& repeatMode, bool forced); void inheritStaticMethods(ClassScope& scope, SyntaxNode classNode); @@ -1613,6 +1650,8 @@ namespace elena_lang bool injectVirtualStrongTypedMultimethod(SyntaxNode classNode, SyntaxKey methodType, ModuleScopeBase& scope, mssg_t message, mssg_t resendMessage, ref_t outputRef, Visibility visibility, bool isExtension); + bool injectVirtualStrongTypedVariadicMultimethod(SyntaxNode classNode, SyntaxKey methodType, ModuleScopeBase& scope, + mssg_t message, mssg_t resendMessage, ref_t outputRef, Visibility visibility, bool isExtension); void injectVirtualMultimethod(SyntaxNode classNode, SyntaxKey methodType, ModuleScopeBase& scope, ref_t targetRef, ClassInfo& classInfo, mssg_t message, bool inherited, ref_t outputRef, Visibility visibility); @@ -1673,6 +1712,11 @@ namespace elena_lang _noValidation = true; } + void setDebugMode(bool debugMode) + { + _withDebugInfo = debugMode; + } + void prepare(ModuleScopeBase* moduleScope, ForwardResolverBase* forwardResolver, ManifestInfo& manifestInfo); void declare(ModuleScopeBase* moduleScope, SyntaxTree& input, ExtensionMap* outerExtensionList); diff --git a/elenasrc3/elc/compilerlogic.cpp b/elenasrc3/elc/compilerlogic.cpp index b914fa5530..2bc3f7071a 100644 --- a/elenasrc3/elc/compilerlogic.cpp +++ b/elenasrc3/elc/compilerlogic.cpp @@ -1314,7 +1314,7 @@ bool CompilerLogic :: isEmbeddableAndReadOnly(ClassInfo& info) return isReadOnly(info) && isEmbeddable(info); } -bool CompilerLogic :: isEmbeddableAndReadOnly(ModuleScopeBase& scope, ref_t reference) +bool CompilerLogic::isEmbeddableAndReadOnly(ModuleScopeBase& scope, ref_t reference) { if (scope.cachedEmbeddableReadonlys.exist(reference)) return scope.cachedEmbeddableReadonlys.get(reference); @@ -1331,6 +1331,18 @@ bool CompilerLogic :: isEmbeddableAndReadOnly(ModuleScopeBase& scope, ref_t refe return false; } +bool CompilerLogic :: isEmbeddableStruct(ModuleScopeBase& scope, ref_t reference) +{ + ClassInfo info; + if (defineClassInfo(scope, info, reference, true)) { + auto retVal = isEmbeddableStruct(info); + + return retVal; + } + + return false; +} + bool CompilerLogic :: isStacksafeArg(ClassInfo& info) { if (test(info.header.flags, elDynamicRole)) { @@ -2085,6 +2097,10 @@ mssg_t CompilerLogic :: resolveMultimethod(ModuleScopeBase& scope, mssg_t weakMe if (!implicitSignatureRef && ((weakMessage & PREFIX_MESSAGE_MASK) != VARIADIC_MESSAGE)) return 0; + if (!implicitSignatureRef) { + implicitSignatureRef = mapWeakSignature(scope, getArgCount(weakMessage)); + } + ref_t signatures[ARG_COUNT]; size_t signatureLen = scope.module->resolveSignature(implicitSignatureRef, signatures); @@ -2293,6 +2309,41 @@ bool CompilerLogic :: checkMethod(ModuleScopeBase& scope, ref_t classRef, mssg_t else return false; } +bool CompilerLogic :: isMessageSupported(ClassInfo& info, mssg_t message) +{ + CheckMethodResult dummy = {}; + + return isMessageSupported(info, message, dummy); +} + +bool CompilerLogic :: isMessageSupported(ClassInfo& info, mssg_t message, CheckMethodResult& result) +{ + if (!checkMethod(info, message, result)) { + if (checkMethod(info, message | STATIC_MESSAGE, result)) { + result.visibility = Visibility::Private; + + return true; + } + mssg_t protectedMessage = info.attributes.get({ message, ClassAttribute::ProtectedAlias }); + if (protectedMessage) { + if (checkMethod(info, protectedMessage, result)) { + result.visibility = Visibility::Protected; + return true; + } + } + mssg_t internalMessage = info.attributes.get({ message, ClassAttribute::InternalAlias }); + if (internalMessage) { + if (checkMethod(info, internalMessage, result)) { + result.visibility = Visibility::Internal; + return true; + } + } + } + else return true; + + return false; +} + bool CompilerLogic :: resolveCallType(ModuleScopeBase& scope, ref_t classRef, mssg_t message, CheckMethodResult& result) { @@ -2307,28 +2358,7 @@ bool CompilerLogic :: resolveCallType(ModuleScopeBase& scope, ref_t classRef, ms else if (test(info.header.flags, elWithCustomDispatcher)) result.withCustomDispatcher = true; - if (!checkMethod(info, message, result)) { - if (checkMethod(info, message | STATIC_MESSAGE, result)) { - result.visibility = Visibility::Private; - - return true; - } - mssg_t protectedMessage = info.attributes.get({ message, ClassAttribute::ProtectedAlias }); - if (protectedMessage) { - if(checkMethod(info, protectedMessage, result)) { - result.visibility = Visibility::Protected; - return true; - } - } - mssg_t internalMessage = info.attributes.get({ message, ClassAttribute::InternalAlias }); - if (internalMessage) { - if (checkMethod(info, internalMessage, result)) { - result.visibility = Visibility::Internal; - return true; - } - } - } - else return true; + return isMessageSupported(info, message, result); } return false; diff --git a/elenasrc3/elc/compilerlogic.h b/elenasrc3/elc/compilerlogic.h index f32410a567..860c3ef3a3 100644 --- a/elenasrc3/elc/compilerlogic.h +++ b/elenasrc3/elc/compilerlogic.h @@ -123,6 +123,7 @@ namespace elena_lang bool isEmbeddableArray(ModuleScopeBase& scope, ref_t reference); bool isEmbeddableStruct(ClassInfo& info); + bool isEmbeddableStruct(ModuleScopeBase& scope, ref_t reference); bool isEmbeddableAndReadOnly(ModuleScopeBase& scope, ref_t reference); bool isEmbeddableAndReadOnly(ClassInfo& info); @@ -185,6 +186,10 @@ namespace elena_lang bool checkMethod(ClassInfo& info, mssg_t message, CheckMethodResult& result); bool checkMethod(ModuleScopeBase& scope, ref_t reference, mssg_t message, CheckMethodResult& result); + // check if internal / protected / private / public message is declared + bool isMessageSupported(ClassInfo& info, mssg_t message, CheckMethodResult& result); + bool isMessageSupported(ClassInfo& info, mssg_t message); + bool resolveCallType(ModuleScopeBase& scope, ref_t classRef, mssg_t message, CheckMethodResult& result); diff --git a/elenasrc3/elc/compiling.cpp b/elenasrc3/elc/compiling.cpp index ea6f81dfb3..93480d2b09 100644 --- a/elenasrc3/elc/compiling.cpp +++ b/elenasrc3/elc/compiling.cpp @@ -3,7 +3,7 @@ // // This file contains the compiling processor body // -// (C)2021-2023, by Aleksey Rakov +// (C)2021-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #include "elena.h" @@ -144,6 +144,20 @@ bool CompilingProcess::TemplateGenerator :: importCodeTemplate(ModuleScopeBase& return true; } +bool CompilingProcess::TemplateGenerator :: importExpressionTemplate(ModuleScopeBase& moduleScope, ref_t templateRef, + SyntaxNode target, List& arguments, List& parameters) +{ + auto sectionInfo = moduleScope.getSection( + moduleScope.module->resolveReference(templateRef), mskSyntaxTreeRef, true); + + if (!sectionInfo.section) + return false; + + _processor.importExpressionTemplate(sectionInfo.section, target, arguments, parameters); + + return true; +} + size_t getLengthSkipPostfix(ustr_t name) { size_t len = name.length(); @@ -276,7 +290,8 @@ ref_t CompilingProcess::TemplateGenerator :: generateClassTemplate(ModuleScopeBa // --- CompilingProcess --- -CompilingProcess :: CompilingProcess(PathString& appPath, path_t modulePrologName, path_t prologName, path_t epilogName, +CompilingProcess :: CompilingProcess(PathString& appPath, path_t exeExtension, + path_t modulePrologName, path_t prologName, path_t epilogName, PresenterBase* presenter, ErrorProcessor* errorProcessor, pos_t codeAlignment, JITSettings defaultCoreSettings, @@ -285,6 +300,7 @@ CompilingProcess :: CompilingProcess(PathString& appPath, path_t modulePrologNam _templateGenerator(this), _forwards(nullptr) { + _exeExtension = exeExtension; _modulePrologName = modulePrologName; _prologName = prologName; _epilogName = epilogName; @@ -648,6 +664,7 @@ void CompilingProcess :: link(Project& project, LinkerBase& linker, bool withTLS imageInfo.type = project.Platform(); imageInfo.codeAlignment = _codeAlignment; imageInfo.autoClassSymbol = project.BoolSetting(ProjectOption::ClassSymbolAutoLoad, _defaultCoreSettings.classSymbolAutoLoad); + imageInfo.autoModuleExtension = project.BoolSetting(ProjectOption::ModuleExtensionAutoLoad, false); imageInfo.coreSettings.mgSize = project.IntSetting(ProjectOption::GCMGSize, _defaultCoreSettings.mgSize); imageInfo.coreSettings.ygSize = project.IntSetting(ProjectOption::GCYGSize, _defaultCoreSettings.ygSize); imageInfo.coreSettings.stackReserved = project.IntSetting(ProjectOption::StackReserved, _defaultCoreSettings.stackReserved); @@ -662,7 +679,7 @@ void CompilingProcess :: link(Project& project, LinkerBase& linker, bool withTLS TargetImage code(project.SystemTarget(), &project, &_libraryProvider, _jitCompilerFactory, imageInfo, addressMapper); - auto result = linker.run(project, code, uiType); + auto result = linker.run(project, code, uiType, _exeExtension); _presenter->print(ELC_SUCCESSFUL_LINKING); @@ -702,7 +719,8 @@ void CompilingProcess :: cleanUp(ProjectBase& project) path_t output = project.PathSetting(ProjectOption::TargetPath); if (!output.empty()) { PathString exePath(output); - exePath.changeExtension("exe"); + if (!_exeExtension.empty()) + exePath.changeExtension(_exeExtension); PathUtil::removeFile(*exePath); diff --git a/elenasrc3/elc/compiling.h b/elenasrc3/elc/compiling.h index 557ac13196..a03b63c560 100644 --- a/elenasrc3/elc/compiling.h +++ b/elenasrc3/elc/compiling.h @@ -3,7 +3,7 @@ // // This file contains the compiling processor header // -// (C)2021-2023, by Aleksey Rakov +// (C)2021-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #ifndef COMPLING_H @@ -58,11 +58,16 @@ namespace elena_lang bool importCodeTemplate(ModuleScopeBase& moduleScope, ref_t templateRef, SyntaxNode target, List& arguments, List& parameters) override; + bool importExpressionTemplate(ModuleScopeBase& moduleScope, ref_t templateRef, SyntaxNode target, + List& arguments, List& parameters) override; + TemplateGenerator(CompilingProcess* process); }; path_t _modulePrologName, _prologName, _epilogName; + path_t _exeExtension; + PresenterBase* _presenter; ErrorProcessor* _errorProcessor; LibraryProvider _libraryProvider; @@ -143,7 +148,8 @@ namespace elena_lang _compiler->setVerboseOn(); } - CompilingProcess(PathString& appPath, path_t modulePrologName, path_t prologName, path_t epilogName, + CompilingProcess(PathString& appPath, path_t exeExtension, + path_t modulePrologName, path_t prologName, path_t epilogName, PresenterBase* presenter, ErrorProcessor* errorProcessor, pos_t codeAlignment, JITSettings defaultCoreSettings, diff --git a/elenasrc3/elc/derivation.cpp b/elenasrc3/elc/derivation.cpp index 656b96f22a..4c3459028d 100644 --- a/elenasrc3/elc/derivation.cpp +++ b/elenasrc3/elc/derivation.cpp @@ -226,6 +226,58 @@ void SyntaxTreeBuilder :: generateTemplateStatement(SyntaxTreeWriter& writer, Sc } +void SyntaxTreeBuilder :: generateTemplateExpression(SyntaxTreeWriter& writer, Scope& scope, SyntaxNode node) +{ + List arguments({}); + List parameters({}); + + IdentifierString templateName(INLINEEXPR_PREFIX); + + SyntaxNode identNode = node.findChild(SyntaxKey::identifier); + templateName.append(identNode.identifier()); + + node.setKey(SyntaxKey::Object); + + // generate template arguments + SyntaxTree tempTree; + SyntaxTreeWriter tempWriter(tempTree); + tempWriter.newNode(SyntaxKey::Idle); + + flushExpression(tempWriter, scope, node.firstChild(SyntaxKey::ScopeMask)); + parameters.add(tempWriter.CurrentNode().firstChild()); + tempWriter.closeNode(); + + SyntaxNode current = identNode.nextNode(); + while (current != SyntaxKey::None) { + switch (current.key) { + case SyntaxKey::TemplateArg: + tempWriter.newNode(SyntaxKey::Idle); + flushTemplateArg(tempWriter, scope, current, true); + arguments.add(tempWriter.CurrentNode().firstChild()); + tempWriter.closeNode(); + break; + default: + break; + } + current = current.nextNode(); + } + + templateName.append('#'); + templateName.appendInt(arguments.count()); + templateName.append('#'); + templateName.appendInt(parameters.count()); + + ref_t templateRef = _moduleScope->operations.get(*templateName); + + if (_templateProcessor->importExpressionTemplate(*_moduleScope, templateRef, writer.CurrentNode(), + arguments, parameters)) + { + } + else { + _errorProcessor->raiseTerminalError(errInvalidOperation, retrievePath(node), node); + } +} + void SyntaxTreeBuilder :: flushIdentifier(SyntaxTreeWriter& writer, SyntaxNode identNode, bool ignoreTerminalInfo) { SyntaxTree::copyNewNode(writer, identNode); @@ -571,6 +623,10 @@ void SyntaxTreeBuilder :: flushExpressionMember(SyntaxTreeWriter& writer, Scope& writer.CurrentNode().setKey(SyntaxKey::CodeBlock); generateTemplateStatement(writer, scope, current); break; + case SyntaxKey::TemplateExpression: + writer.CurrentNode().setKey(SyntaxKey::Expression); + generateTemplateExpression(writer, scope, current); + break; case SyntaxKey::TemplateOperation: generateTemplateOperation(writer, scope, current); break; @@ -1356,6 +1412,33 @@ void SyntaxTreeBuilder :: flushInlineTemplatePostfixes(SyntaxTreeWriter& writer, } } +void SyntaxTreeBuilder :: flushExpressionTemplate(SyntaxTreeWriter& writer, Scope& scope, SyntaxNode node) +{ + scope.type = ScopeType::ExpressionTemplate; + scope.ignoreTerminalInfo = true; + + flushClassMemberPostfixes(writer, scope, node); + + SyntaxNode current = node.firstChild(); + while (current != SyntaxKey::None) { + switch (current.key) { + case SyntaxKey::TemplateArg: + flushTemplateArgDescr(writer, scope, current); + break; + case SyntaxKey::Parameter: + flushParameterArgDescr(writer, scope, current); + break; + case SyntaxKey::ReturnExpression: + flushTemplateCode(writer, scope, current); + break; + default: + break; + } + + current = current.nextNode(); + } +} + void SyntaxTreeBuilder :: flushInlineTemplate(SyntaxTreeWriter& writer, Scope& scope, SyntaxNode node) { scope.type = ScopeType::InlineTemplate; @@ -1564,7 +1647,12 @@ void SyntaxTreeBuilder :: flushDeclaration(SyntaxTreeWriter& writer, SyntaxNode else writer.CurrentNode().setKey(SyntaxKey::Template); flushTemplate(writer, scope, node); break; + case SyntaxKey::ReturnExpression: + writer.CurrentNode().setKey(SyntaxKey::InlineTemplateExpr); + flushExpressionTemplate(writer, scope, node); + break; default: + assert(false); break; } @@ -1834,6 +1922,9 @@ void TemplateProssesor :: generate(SyntaxTreeWriter& writer, TemplateScope& scop case Type::Class: copyClassMembers(writer, scope, root); break; + case Type::ExpressionTemplate: + copyChildren(writer, scope, root.findChild(SyntaxKey::ReturnExpression)); + break; default: break; } @@ -1919,6 +2010,12 @@ void TemplateProssesor :: importCodeTemplate(MemoryBase* templateSection, importTemplate(Type::CodeTemplate, templateSection, target, &arguments, ¶meters); } +void TemplateProssesor :: importExpressionTemplate(MemoryBase* templateSection, + SyntaxNode target, List& arguments, List& parameters) +{ + importTemplate(Type::ExpressionTemplate, templateSection, target, &arguments, ¶meters); +} + void TemplateProssesor :: copyField(SyntaxTreeWriter& writer, TemplateScope& scope, SyntaxNode node) { writer.newNode(node.key); diff --git a/elenasrc3/elc/derivation.h b/elenasrc3/elc/derivation.h index 0c9038a4b1..318bea59c6 100644 --- a/elenasrc3/elc/derivation.h +++ b/elenasrc3/elc/derivation.h @@ -3,7 +3,7 @@ // // This file contains Syntax Tree Builder class declaration // -// (C)2021-2022, by Aleksey Rakov +// (C)2021-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #ifndef DERIVATION_H @@ -25,7 +25,8 @@ namespace elena_lang InlineTemplate, ClassTemplate, PropertyTemplate, - ExtensionTemplate + ExtensionTemplate, + ExpressionTemplate, }; struct Scope @@ -49,6 +50,7 @@ namespace elena_lang { switch (type) { case ScopeType::InlineTemplate: + case ScopeType::ExpressionTemplate: { ref_t index = arguments.get(node.identifier()); if (index) { @@ -122,6 +124,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 generateTemplateExpression(SyntaxTreeWriter& writer, Scope& scope, SyntaxNode node); void generateTemplateOperation(SyntaxTreeWriter& writer, Scope& scope, SyntaxNode node); void loadMetaSection(SyntaxNode node); @@ -179,11 +182,13 @@ namespace elena_lang bool typeDescriptor = false); void flushClass(SyntaxTreeWriter& writer, Scope& scope, SyntaxNode node, bool functionMode); void flushInlineTemplate(SyntaxTreeWriter& writer, Scope& scope, SyntaxNode node); + void flushExpressionTemplate(SyntaxTreeWriter& writer, Scope& scope, SyntaxNode node); void flushDeclaration(SyntaxTreeWriter& writer, SyntaxNode node); void flushDictionary(SyntaxTreeWriter& writer, SyntaxNode node); void flushNamespace(SyntaxTreeWriter& writer, SyntaxNode node); void flush(SyntaxTreeWriter& writer, SyntaxNode node); + public: void newNode(parse_key_t key) override; void newNode(parse_key_t key, ustr_t arg) override; @@ -228,7 +233,8 @@ namespace elena_lang Inline, CodeTemplate, Class, - InlineProperty + InlineProperty, + ExpressionTemplate }; typedef Map NodeMap; @@ -285,6 +291,8 @@ namespace elena_lang void importInlinePropertyTemplate(MemoryBase* section, SyntaxNode target, List& parameters); void importCodeTemplate(MemoryBase* templateSection, SyntaxNode target, List& arguments, List& parameters); + void importExpressionTemplate(MemoryBase* templateSection, + SyntaxNode target, List& arguments, List& parameters); void generateClassTemplate(ModuleScopeBase* moduleScope, ref_t classRef, SyntaxTreeWriter& writer, MemoryBase* sectionBody, List& args); diff --git a/elenasrc3/elc/linux/elc.cpp b/elenasrc3/elc/linux/elc.cpp index da46908d3a..8a04e2b000 100644 --- a/elenasrc3/elc/linux/elc.cpp +++ b/elenasrc3/elc/linux/elc.cpp @@ -3,7 +3,7 @@ // // This file contains the main body of the Linux command-line compiler // -// (C)2021-2023, by Aleksey Rakov +// (C)2021-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #include "elena.h" @@ -171,7 +171,7 @@ int main(int argc, char* argv[]) ErrorProcessor errorProcessor(&Presenter::getInstance()); Project project(*dataPath, CURRENT_PLATFORM, &Presenter::getInstance()); LinuxLinker linker(&errorProcessor, &LinuxImageFormatter::getInstance(&project)); - CompilingProcess process(dataPath, "", "", "", + CompilingProcess process(dataPath, nullptr, "", "", "", &Presenter::getInstance(), &errorProcessor, VA_ALIGNMENT, defaultCoreSettings, createJITCompiler); diff --git a/elenasrc3/elc/linux/elflinker.cpp b/elenasrc3/elc/linux/elflinker.cpp index a90eb78679..9794a85d2f 100644 --- a/elenasrc3/elc/linux/elflinker.cpp +++ b/elenasrc3/elc/linux/elflinker.cpp @@ -3,7 +3,7 @@ // // This file contains ELENA Executive Linker class implementation // Supported platforms: Linux -// (C)2021-2022, by Aleksey Rakov +// (C)2021-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #include "elflinker.h" @@ -108,7 +108,7 @@ void ElfLinker :: prepareElfImage(ImageProviderBase& provider, ElfExecutableImag image.withDebugInfo); } -LinkResult ElfLinker :: run(ProjectBase& project, ImageProviderBase& provider, PlatformType) +LinkResult ElfLinker :: run(ProjectBase& project, ImageProviderBase& provider, PlatformType, path_t) { bool withDebugMode = project.BoolSetting(ProjectOption::DebugMode, true); ElfExecutableImage image(withDebugMode); diff --git a/elenasrc3/elc/linux/elflinker.h b/elenasrc3/elc/linux/elflinker.h index f3db8c82c1..0558e64d56 100644 --- a/elenasrc3/elc/linux/elflinker.h +++ b/elenasrc3/elc/linux/elflinker.h @@ -3,7 +3,7 @@ // // This header contains ELENA Executive Linker class declaration // Supported platforms: Linux -// (C)2021, by Aleksey Rakov +// (C)2021+2024, by Aleksey Rakov //--------------------------------------------------------------------------- #ifndef ELFLINKER_H @@ -56,7 +56,8 @@ namespace elena_lang virtual void prepareElfImage(ImageProviderBase& provider, ElfExecutableImage& image, unsigned int headerSize); public: - LinkResult run(ProjectBase& project, ImageProviderBase& code, PlatformType uiType) override; + LinkResult run(ProjectBase& project, ImageProviderBase& code, PlatformType uiType, + path_t exeExtension) override; ElfLinker(ErrorProcessorBase* errorProcessor, ImageFormatter* imageFormatter) : LinkerBase(errorProcessor) diff --git a/elenasrc3/elc/modulescope.cpp b/elenasrc3/elc/modulescope.cpp index 1ce40f5810..263d182430 100644 --- a/elenasrc3/elc/modulescope.cpp +++ b/elenasrc3/elc/modulescope.cpp @@ -395,6 +395,11 @@ bool ModuleScope :: isDeclared(ref_t reference) return mapSection(reference | mskMetaClassInfoRef, true) != nullptr; } +bool ModuleScope :: isSymbolDeclared(ref_t reference) +{ + return mapSection(reference | mskMetaSymbolInfoRef, true) != nullptr; +} + Visibility ModuleScope :: retrieveVisibility(ref_t reference) { ustr_t referenceName = module->resolveReference(reference); diff --git a/elenasrc3/elc/modulescope.h b/elenasrc3/elc/modulescope.h index 12c6391b1f..27a4186b3a 100644 --- a/elenasrc3/elc/modulescope.h +++ b/elenasrc3/elc/modulescope.h @@ -76,6 +76,7 @@ class ModuleScope : public ModuleScopeBase bool includeNamespace(IdentifierList& importedNs, ustr_t name, bool& duplicateInclusion) override; bool isDeclared(ref_t reference) override; + bool isSymbolDeclared(ref_t reference) override; Visibility retrieveVisibility(ref_t reference) override; diff --git a/elenasrc3/elc/project.cpp b/elenasrc3/elc/project.cpp index 51c0581e48..9567e5b55c 100644 --- a/elenasrc3/elc/project.cpp +++ b/elenasrc3/elc/project.cpp @@ -282,6 +282,13 @@ void Project :: loadConfig(ConfigFile& config, path_t configPath, ConfigFile::No loadConfig(config, configPath, profileRoot); } + else { + // if no profile was specified - use if available default profile + ConfigFile::Node profileRoot = getProfileRoot(config, root, "default"); + if (!profileRoot.isNotFound()) + loadConfig(config, configPath, profileRoot); + + } } void Project :: loadConfig(ConfigFile& config, path_t configPath, ConfigFile::Node& root) @@ -319,6 +326,8 @@ void Project :: loadConfig(ConfigFile& config, path_t configPath, ConfigFile::No loadPathSetting(config, root, OUTPUT_PATH, ProjectOption::OutputPath, configPath); loadPathSetting(config, root, TARGET_PATH, ProjectOption::TargetPath, configPath); + loadBoolSetting(config, root, AUTOEXTENSION_PATH, ProjectOption::ModuleExtensionAutoLoad); + loadParserTargets(config, root, PARSER_TARGET_CATEGORY); copySetting(config, root, MANIFEST_NAME, ProjectOption::ManifestName); diff --git a/elenasrc3/elc/vs/elc.vcxproj b/elenasrc3/elc/vs/elc.vcxproj index d4ed0d6db2..685b2af70f 100644 --- a/elenasrc3/elc/vs/elc.vcxproj +++ b/elenasrc3/elc/vs/elc.vcxproj @@ -183,6 +183,7 @@ + diff --git a/elenasrc3/elc/windows/elc.cpp b/elenasrc3/elc/windows/elc.cpp index 548acca1c8..0d1430ad49 100644 --- a/elenasrc3/elc/windows/elc.cpp +++ b/elenasrc3/elc/windows/elc.cpp @@ -122,8 +122,6 @@ JITCompilerBase* createJITCompiler(LibraryLoaderBase* loader, PlatformType platf int main() { - long long l = 0; - try { bool cleanMode = false; @@ -135,7 +133,7 @@ int main() ErrorProcessor errorProcessor(&Presenter::getInstance()); Project project(*appPath, CURRENT_PLATFORM, &Presenter::getInstance()); WinLinker linker(&errorProcessor, &WinImageFormatter::getInstance(&project)); - CompilingProcess process(appPath, L"", L"", L"", + CompilingProcess process(appPath, L"exe", L"", L"", L"", &Presenter::getInstance(), &errorProcessor, VA_ALIGNMENT, defaultCoreSettings, createJITCompiler); @@ -232,6 +230,9 @@ int main() else if (argv[i][2] == 'e') { project.addBoolSetting(ProjectOption::EvaluateOp, argv[i][3] != '-'); } + else if (argv[i][2] == 'm') { + project.addBoolSetting(ProjectOption::ModuleExtensionAutoLoad, argv[i][3] != '-'); + } else if (argv[i][2] == 'p') { project.addBoolSetting(ProjectOption::GenerateParamNameInfo, argv[i][3] != '-'); } diff --git a/elenasrc3/elc/windows/ntlinker.cpp b/elenasrc3/elc/windows/ntlinker.cpp index b843dcca60..4e347e8736 100644 --- a/elenasrc3/elc/windows/ntlinker.cpp +++ b/elenasrc3/elc/windows/ntlinker.cpp @@ -188,7 +188,7 @@ void WinNtLinker :: prepareNtImage(ImageProviderBase& provider, WinNtExecutableI image.headerSize += IMAGE_SIZEOF_SECTION_HEADER * image.imageSections.headers.count(); } -LinkResult WinNtLinker :: run(ProjectBase& project, ImageProviderBase& provider, PlatformType uiType) +LinkResult WinNtLinker :: run(ProjectBase& project, ImageProviderBase& provider, PlatformType uiType, path_t exeExtension) { bool withDebugMode = project.BoolSetting(ProjectOption::DebugMode, true); // !! temporally by default the debug mode is on @@ -198,7 +198,7 @@ LinkResult WinNtLinker :: run(ProjectBase& project, ImageProviderBase& provider, prepareNtImage(provider, image, uiType); PathString exePath(project.PathSetting(ProjectOption::TargetPath)); - exePath.changeExtension(L"exe"); + exePath.changeExtension(exeExtension); if (!createExecutable(image, *exePath, project.PathSetting(ProjectOption::BasePath))) { _errorProcessor->raisePathError(errCannotCreate, project.PathSetting(ProjectOption::TargetPath)); diff --git a/elenasrc3/elc/windows/ntlinker.h b/elenasrc3/elc/windows/ntlinker.h index d1d73e3c03..1a4dcca515 100644 --- a/elenasrc3/elc/windows/ntlinker.h +++ b/elenasrc3/elc/windows/ntlinker.h @@ -73,7 +73,7 @@ namespace elena_lang bool createDebugFile(ImageProviderBase& provider, WinNtExecutableImage& image, path_t debugFilePath); public: - LinkResult run(ProjectBase& project, ImageProviderBase& code, PlatformType uiType) override; + LinkResult run(ProjectBase& project, ImageProviderBase& code, PlatformType uiType, path_t exeExtension) override; WinNtLinker(ErrorProcessorBase* errorProcessor, ImageFormatter* imageFormatter) : LinkerBase(errorProcessor) diff --git a/elenasrc3/elena-tests/bt_optimization.cpp b/elenasrc3/elena-tests/bt_optimization.cpp index 79c899cf0b..1f3dbf645b 100644 --- a/elenasrc3/elena-tests/bt_optimization.cpp +++ b/elenasrc3/elena-tests/bt_optimization.cpp @@ -42,6 +42,28 @@ constexpr auto Struct_Declaration1 = "namespace (class ( nameattr (identifier \" constexpr auto Struct_Declaration2 = "namespace (class ( nameattr (identifier \"Object\" ())) class (attribute -2147479550 () nameattr (identifier \"IntNumber\" ()) field (attribute -2147475454 () attribute -2147481597 () nameattr ( identifier \"_value\" ()) dimension ( integer \"4\" ()))) class (attribute -2147479550 () nameattr (identifier \"ByteNumber\" ()) field (attribute -2147475454 () attribute -2147481596 () nameattr (identifier \"_value\" ()) dimension (integer \"1\" ())))class (attribute -2147479550 () nameattr 60 (identifier \"ShortNumber\" ()) field (attribute -2147475454 () attribute -2147481597 ()nameattr ( identifier \"_value\" ()) dimension ( integer \"2\" ()))) class (attribute -2147479550 ()nameattr (identifier \"LongNumber\" ())field (attribute -2147475454 () attribute -2147481597 () nameattr ( identifier \"_value\" ()) dimension (integer \"8\" ()))) class (attribute -2147479508 () nameattr (identifier \"Aligned\" ())field (type (identifier \"byte\" ())nameattr (identifier \"b\" ()) ) field (type (identifier \"short\" ())nameattr (identifier \"w\" ())) field (type (identifier \"byte\" ())nameattr (identifier \"b2\" ())) field (type (identifier \"int\" ())nameattr (identifier \"n\" ())) field (type (identifier \"byte\" ())nameattr (identifier \"b3\" ()))field (type (identifier \"long\" ()) nameattr (identifier \"l\" ()))))"; constexpr auto Struct_Declaration3 = "namespace (class ( nameattr (identifier \"Object\" ())) class (attribute -2147479550 () nameattr (identifier \"IntNumber\" ()) field (attribute -2147475454 () attribute -2147481597 () nameattr ( identifier \"_value\" ()) dimension ( integer \"4\" ()))) class (attribute -2147479550 () nameattr (identifier \"ByteNumber\" ()) field (attribute -2147475454 () attribute -2147481596 () nameattr (identifier \"_value\" ()) dimension (integer \"1\" ())))class (attribute -2147479550 () nameattr 60 (identifier \"ShortNumber\" ()) field (attribute -2147475454 () attribute -2147481597 ()nameattr ( identifier \"_value\" ()) dimension ( integer \"2\" ()))) class (attribute -2147479550 ()nameattr (identifier \"LongNumber\" ())field (attribute -2147475454 () attribute -2147481597 () nameattr ( identifier \"_value\" ()) dimension (integer \"8\" ()))) class (attribute -2147479550 () nameattr (identifier \"Aligned\" ())field (type (identifier \"byte\" ())nameattr (identifier \"b\" ()) ) field (type (identifier \"short\" ())nameattr (identifier \"w\" ())) field (type (identifier \"byte\" ())nameattr (identifier \"b2\" ())) field (type (identifier \"int\" ())nameattr (identifier \"n\" ()))) class (attribute -2147479550 () nameattr (identifier \"Complex\" ())field (type (identifier \"byte\" ())nameattr (identifier \"f1\" ()) ) field (type (identifier \"Aligned\" ())nameattr (identifier \"f2\" ()))))"; +constexpr auto S1_DefaultNamespace = "namespace (class (nameattr (identifier \"Object\" ())) class (nameattr (identifier \"B\" ())) $1)"; +constexpr auto S1_IntNumber = "class (attribute -2147467263 () attribute -2147475455 () attribute -2147479550 () nameattr (identifier \"IntNumber\" ()) field (attribute -2147475454 () attribute -2147481597 () nameattr (identifier \"_value\" ())dimension (integer \"4\" ())))"; +constexpr auto S1_VariadicTemplates = " class (attribute -2147467263 ()attribute -2147471359 ()attribute -2147479542 ()nameattr (identifier \"VariadicArray\" ())field (attribute -2147475454 ()attribute -2147481599 ()array_type (type (identifier \"Object\" ()))nameattr (identifier \"array\" ()))) class (attribute -2147467263 ()attribute -2147471359 ()attribute -2147479542 ()nameattr (identifier \"VariadicBArray\" ())field (attribute -2147475454 ()attribute -2147481599 ()array_type (type (identifier \"B\" ()))nameattr (identifier \"array\" ())))"; + +constexpr auto S1_VariadicSingleDispatch_1 = "class (attribute -2147479546 () nameattr (identifier \"E\" ()) method (nameattr (identifier \"load\" ()) parameter (attribute -2147475445 () array_type (type (identifier \"B\" ())) nameattr (identifier \"o\" ())) code ()))"; +constexpr auto S1_VariadicSingleDispatch_2 = "class (attribute -2147467263 () nameattr (identifier \"program\" ()) attribute -2147479546 () method 2592 (attribute -2147479540 ()code ( expression (assign_operation (object (attribute -2147479539 () identifier \"b\" ())expression (message_operation (object (attribute -2147479534 () identifier \"B\" ()))))) expression (assign_operation (object (attribute -2147479539 () identifier \"c\" ()) expression (message_operation (object (attribute -2147479534 ()identifier \"C\" ()))))) expression (message_operation (object (identifier \"E\" ())message (identifier \"load\" ())expression (object (identifier \"b\" ()))expression (object (identifier \"c\" ()))))))) class (nameattr (identifier \"C\" ()) method (type (identifier \"B\" ())attribute -2147479535 () returning (expression (message_operation (object (attribute -2147479534 () identifier \"B\" ())))))"; + +constexpr auto S1_VariadicSingleDispatch_3a = "class (nameattr(identifier \"C\" ())parent (type (identifier \"B\" ())))class (nameattr (identifier \"D\" ())parent (type (identifier \"B\" ())))"; +constexpr auto S1_VariadicSingleDispatch_3b = "class (attribute -2147467263 ()nameattr (identifier \"program\" ())attribute -2147479546 ()method (attribute -2147479540 ()code (expression (message_operation (object (identifier \"E\" ())message (identifier \"load\" ())expression (message_operation (object (attribute -2147479534 ()identifier \"C\" ())))expression (message_operation (object (attribute -2147479534 ()identifier \"D\" ()))))))))"; + +constexpr auto S1_DirectCall_1 = "class (nameattr (identifier \"myMethod\" ())attribute -2147479546 ()method (attribute -2147479540 ()parameter (type (identifier \"B\" ())nameattr (identifier \"arg\" ()))code ()))"; +constexpr auto S1_DirectCall_2 = "class (attribute -2147479546 ()nameattr (identifier \"TestHelper\" ())method (nameattr (identifier \"myMethodInvoker\" ())code (expression (message_operation (object (identifier \"myMethod\" ())expression (message_operation (object (attribute -2147479534 ()identifier \"B\" ())))))))method (nameattr (identifier \"myMethod\" ())parameter (type (identifier \"B\" ())nameattr (identifier \"arg\" ()))code ()))"; + +constexpr auto S1_DirectCall_3 = "class (attribute -2147479546 ()nameattr (identifier \"TestHelper\" ())method (nameattr (identifier \"myMethodInvoker\" ())code (expression (assign_operation (object (attribute -2147479539 ()identifier \"b1\" ())expression (message_operation (object (attribute -2147479534 ()identifier \"B\" ())))))expression (assign_operation (object (attribute -2147479539 ()identifier \"b2\" ())expression (message_operation (object (attribute -2147479534 ()identifier \"B\" ())))))expression (message_operation (object (identifier \"myMethod\" ())expression (object (identifier \"b1\" ()))expression (object (identifier \"b2\" ()))))))method (nameattr (identifier \"myMethod\" ())parameter (attribute -2147475445 ()array_type (type (identifier \"B\" ()))nameattr (identifier \"arg\" ()))code ()))"; + +constexpr auto S1_VariadicConstructorSingleDispatch_1 = "class (attribute -2147479546 ()nameattr (identifier \"Tester\" ())method (nameattr (identifier \"test\" ())parameter (attribute -2147475445 ()array_type (type (identifier \"Object\" ()))nameattr (identifier \"args\" ()))code (returning (expression (message_operation (object (identifier \"X\" ())message (identifier \"load\" ())expression (object (attribute -2147475445 ()identifier \"args\" ())))))))) class (nameattr (identifier \"X\" ()) method (attribute -2147479548 ()nameattr (identifier \"load\" ())parameter (attribute -2147475445 ()array_type (type (identifier \"B\" ()))nameattr (identifier \"args\" ()))code ()))"; + +// S2 Scenarion : lmbda +constexpr auto S2_DefaultNamespace = "namespace (class (nameattr (identifier \"Object\" ()) method (nameattr (identifier \"dispatch\" ())redirect (expression (object (identifier \"nil\" ()))))) $1)"; +constexpr auto S2_Func = "class (attribute -2147467263 ()attribute -2147479545 ()nameattr (identifier \"Func\" ())method (attribute -2147471358 ()nameattr (identifier \"function\" ())no_body ()))"; +constexpr auto S2_Scenario1 = "class (attribute -2147479546 ()nameattr (identifier \"E\" ())method (nameattr (identifier \"callFromLambda\" ())code (expression (assign_operation (object (attribute -2147479539 ()identifier \"f\" ())expression (closure (code (expression (message_operation (object (identifier \"callMe\" ()))))))))expression (message_operation (object (identifier \"f\" ())))))method (attribute -2147467262 ()nameattr (identifier \"callMe\" ())code ()))"; + #ifdef _M_IX86 constexpr auto BuildTree1_1 = "byrefmark -8 () local_address -8 () saving_stack 1 () class_reference 4 () saving_stack () argument () direct_call_op 2050 (type 4 ()) local_address -8 () copying -4 (size 4 ())"; @@ -52,6 +74,18 @@ constexpr auto OptimizedBuildTree1_1 = "local_address -4 () saving_stack 1 () cl constexpr auto OptimizedBuildTree1_2 = "local_address -4 () saving_stack 1 () class_reference 4 () saving_stack () argument () direct_call_op 2242 (type 4 ()) local_address -4 ()"; constexpr auto OptimizedBuildTree2 = "saving_int - 4 (size 4 ()value 2 ())"; +constexpr auto BuildTree_VariadicSingleDispatch_1 = "tape(sealed_dispatching 256 (message 3202 ()) open_frame() assigning 1 () local_reference -2 () saving_stack() varg_sop 6 (index -4 ()) unbox_call_message -2 (index 1 () length -4 () temp_var -8 () message 1089 ()) local 1 () saving_stack() argument() direct_call_op 3202 (type 5 ()) loading_index() free_varstack() close_frame() exit()) reserved 3 ()reserved_n 8 ())"; +constexpr auto BuildTree_VariadicSingleDispatch_2 = "tape(open_frame() assigning 1 () class_reference 2 () direct_call_op 544 (type 10 ()) assigning 2 () class_reference 8 () direct_call_op 544 (type 14 ()) assigning 3 () local 2 () saving_stack() argument() call_op 1089 () assigning 4 () local 3 () saving_stack() argument() call_op 1089 () assigning 5 () terminator() saving_stack 3 () local 5 () saving_stack 2 () local 4 () saving_stack 1 () class_reference 5 () saving_stack() argument() direct_call_op 3202 (type 5 ()) local 1 () close_frame() exit()) reserved 9 ()"; + +constexpr auto BuildTree_VariadicSingleDispatch_3 = "tape(open_frame()assigning 1 ()local_reference - 2 ()saving_stack()varg_sop 6 (index - 4 ())unbox_call_message - 2 (index 1 ()length - 4 ()temp_var - 8 ()message 1601 ())class_reference 6 ()saving_stack()argument()direct_call_op 5250 (type 12 ())loading_index() free_varstack() going_to_eop() close_frame()exit())reserved 3 ()reserved_n 8 ())"; + +constexpr auto BuildTree_VariadicSingleDispatch_4 = "tape (open_frame ()assigning 1 ()class_reference 8 ()direct_call_op 544 (type 15 ())assigning 2 ()class_reference 9 ()direct_call_op 544 (type 16 ())assigning 3 ()terminator ()saving_stack 3 ()local 3 ()saving_stack 2 ()local 2 ()saving_stack 1 ()class_reference 7 ()saving_stack ()argument ()direct_call_op 4226 (type 7 ())local 1 ()close_frame ()exit ())reserved 7 ())"; + +constexpr auto BuildTree_CallMethodWithoutTarget = "tape (open_frame ()assigning 1 ()class_reference 2 ()direct_call_op 544 (type 6 ())assigning 2 ()local 2 ()saving_stack 1 ()local 1 ()saving_stack ()argument ()direct_call_op 3586 (type 4 ())local 1 ()close_frame ()exit ())reserved 4 ()"; +constexpr auto BuildTree_CallVariadicMethodWithoutTarget = "tape(open_frame()assigning 1 ()class_reference 2 ()direct_call_op 544 (type 8 ())assigning 2 ()class_reference 2 ()direct_call_op 544 (type 8 ())assigning 3 ()local 2 ()saving_stack()argument()call_op 1089 ()assigning 4 ()local 3 ()saving_stack()argument()call_op 1089 ()assigning 5 ()terminator()saving_stack 3 ()local 5 ()saving_stack 2 ()local 4 ()saving_stack 1 ()local 1 ()saving_stack()argument()direct_call_op 3714 (type 4 ())local 1 ()close_frame()exit())reserved 9 ()"; + +constexpr auto BuildTree_LambdaCallPrivate = "tape (open_frame ()assigning 1 ()local 1 ()field ()saving_stack ()argument ()direct_call_op 3329 (type 3 ())close_frame ()exit ())reserved 2 ()"; + constexpr auto PackedStructSize = 20; constexpr auto ComplexStructOffset2 = 4; @@ -67,6 +101,18 @@ constexpr auto OptimizedBuildTree1_1 = "local_address -8 () saving_stack 1 () cl constexpr auto OptimizedBuildTree1_2 = "local_address -8 () saving_stack 1 () class_reference 4 () saving_stack () argument () direct_call_op 2242 (type 4 ()) local_address -8 ()"; constexpr auto OptimizedBuildTree2 = "saving_int - 8 (size 4 ()value 2 ())"; +constexpr auto BuildTree_VariadicSingleDispatch_1 = "tape(sealed_dispatching 256 (message 3202 ()) open_frame() assigning 1 () local_reference -2 () saving_stack() varg_sop 6 (index -8 ()) unbox_call_message -2 (index 1 () length -8 () temp_var -24 () message 1089 ()) local 1 () saving_stack() argument() direct_call_op 3202 (type 5 ()) loading_index() free_varstack() close_frame() exit()) reserved 4 ()reserved_n 32 ())"; +constexpr auto BuildTree_VariadicSingleDispatch_2 = "tape(open_frame() assigning 1 () class_reference 2 () direct_call_op 544 (type 10 ()) assigning 2 () class_reference 8 () direct_call_op 544 (type 14 ()) assigning 3 () local 2 () saving_stack() argument() call_op 1089 () assigning 4 () local 3 () saving_stack() argument() call_op 1089 () assigning 5 () terminator() saving_stack 3 () local 5 () saving_stack 2 () local 4 () saving_stack 1 () class_reference 5 () saving_stack() argument() direct_call_op 3202 (type 5 ()) local 1 () close_frame() exit()) reserved 10 ()"; + +constexpr auto BuildTree_VariadicSingleDispatch_3 = "tape(open_frame()assigning 1 ()local_reference -2 ()saving_stack()varg_sop 6 (index -8 ())unbox_call_message -2 (index 1 ()length -8 ()temp_var -24 ()message 1601 ())class_reference 6 ()saving_stack()argument()direct_call_op 5250 (type 12 ())loading_index() free_varstack() going_to_eop() close_frame()exit())reserved 4 ()reserved_n 32 ())"; + +constexpr auto BuildTree_VariadicSingleDispatch_4 = "tape (open_frame ()assigning 1 ()class_reference 8 ()direct_call_op 544 (type 15 ())assigning 2 ()class_reference 9 ()direct_call_op 544 (type 16 ())assigning 3 ()terminator ()saving_stack 3 ()local 3 ()saving_stack 2 ()local 2 ()saving_stack 1 ()class_reference 7 ()saving_stack ()argument ()direct_call_op 4226 (type 7 ())local 1 ()close_frame ()exit ())reserved 8 ())"; + +constexpr auto BuildTree_CallMethodWithoutTarget = "tape (open_frame ()assigning 1 ()class_reference 2 ()direct_call_op 544 (type 6 ())assigning 2 ()local 2 ()saving_stack 1 ()local 1 ()saving_stack ()argument ()direct_call_op 3586 (type 4 ())local 1 ()close_frame ()exit ())reserved 4 ()"; +constexpr auto BuildTree_CallVariadicMethodWithoutTarget = "tape(open_frame()assigning 1 ()class_reference 2 ()direct_call_op 544 (type 8 ())assigning 2 ()class_reference 2 ()direct_call_op 544 (type 8 ())assigning 3 ()local 2 ()saving_stack()argument()call_op 1089 ()assigning 4 ()local 3 ()saving_stack()argument()call_op 1089 ()assigning 5 ()terminator()saving_stack 3 ()local 5 ()saving_stack 2 ()local 4 ()saving_stack 1 ()local 1 ()saving_stack()argument()direct_call_op 3714 (type 4 ())local 1 ()close_frame()exit())reserved 10 ()"; + +constexpr auto BuildTree_LambdaCallPrivate = "tape (open_frame ()assigning 1 ()local 1 ()field ()saving_stack ()argument ()direct_call_op 3329 (type 3 ())close_frame ()exit ())reserved 4 ()"; + constexpr auto PackedStructSize = 24; constexpr auto ComplexStructOffset2 = 8; @@ -338,4 +384,427 @@ void PrimitiveStructAlignment:: SetUp() expectedSize = 2; } +// --- Scenario1Test --- + +void Scenario1Test:: LoadDeclarationScenario(ustr_t common, ustr_t descr1, ustr_t descr2) +{ + IdentifierString descr(descr1, " ", descr2); + + DynamicUStr syntax(common); + + size_t index = common.findStr("$1"); + if (index != NOTFOUND_POS) { + syntax.cut(index, 2); + syntax.insert(*descr, index); + } + + SyntaxTreeSerializer::load(syntax.str(), declarationNode); +} + +void Scenario1Test :: LoadDeclarationScenario(ustr_t common, ustr_t descr1, ustr_t descr2, ustr_t descr3) +{ + DynamicUStr syntax(common); + + size_t index = common.findStr("$1"); + if (index != NOTFOUND_POS) { + syntax.cut(index, 2); + + syntax.insert(descr3, index); + syntax.insert(" ", index); + syntax.insert(descr2, index); + syntax.insert(" ", index); + syntax.insert(descr1, index); + } + + SyntaxTreeSerializer::load(syntax.str(), declarationNode); +} + +void Scenario1Test :: LoadDeclarationScenario(ustr_t common, ustr_t descr1, ustr_t descr2, ustr_t descr3, ustr_t descr4) +{ + DynamicUStr syntax(common); + + size_t index = common.findStr("$1"); + if (index != NOTFOUND_POS) { + syntax.cut(index, 2); + + syntax.insert(descr4, index); + syntax.insert(" ", index); + syntax.insert(descr3, index); + syntax.insert(" ", index); + syntax.insert(descr2, index); + syntax.insert(" ", index); + syntax.insert(descr1, index); + } + + SyntaxTreeSerializer::load(syntax.str(), declarationNode); +} + +void Scenario1Test :: LoadDeclarationScenario(ustr_t common, ustr_t descr1, ustr_t descr2, ustr_t descr3, ustr_t descr4, ustr_t descr5) +{ + DynamicUStr syntax(common); + + size_t index = common.findStr("$1"); + if (index != NOTFOUND_POS) { + syntax.cut(index, 2); + + syntax.insert(descr5, index); + syntax.insert(" ", index); + syntax.insert(descr4, index); + syntax.insert(" ", index); + syntax.insert(descr3, index); + syntax.insert(" ", index); + syntax.insert(descr2, index); + syntax.insert(" ", index); + syntax.insert(descr1, index); + } + + SyntaxTreeSerializer::load(syntax.str(), declarationNode); +} + +// --- DispatchTest --- + +void DispatchTest :: SetUp() +{ + SyntaxTreeWriter writer(syntaxTree); + writer.appendNode(SyntaxKey::Root); + + BuildTreeWriter buildWriter(buildTree); + buildWriter.appendNode(BuildKey::Root); + + declarationNode = syntaxTree.readRoot().appendChild(SyntaxKey::Idle, 1); + + controlOutputNode = buildTree.readRoot().appendChild(BuildKey::Tape); +} + +SyntaxNode DispatchTest :: findClassNode() +{ + return SyntaxTree::gotoChild(declarationNode.firstChild(), SyntaxKey::Class, targetRef); +} + +SyntaxNode DispatchTest :: findAutoGenerated(SyntaxNode classNode) +{ + SyntaxNode current = classNode.firstChild(); + while (current != SyntaxKey::None) { + if (current == SyntaxKey::Method && current.existChild(SyntaxKey::Autogenerated)) + return current; + + current = current.nextNode(); + } + + return {}; +} + +void DispatchTest :: runTest(bool withProtectedConstructor) +{ + // Arrange + ModuleScopeBase* moduleScope = env.createModuleScope(true, false); + moduleScope->buildins.superReference = 1; + moduleScope->buildins.intReference = intNumberRef; + moduleScope->buildins.argArrayTemplateReference = argArrayRef; + moduleScope->buildins.constructor_message = + encodeMessage(moduleScope->module->mapAction(CONSTRUCTOR_MESSAGE, 0, false), + 0, FUNCTION_MESSAGE); + if (withProtectedConstructor) + moduleScope->buildins.protected_constructor_message = + encodeMessage(moduleScope->module->mapAction(CONSTRUCTOR_MESSAGE2, 0, false), + 0, FUNCTION_MESSAGE); + + env.setUpTemplateMockup(argArrayRef, 1, genericVargRef); + env.setUpTemplateMockup(argArrayRef, 2, targetVargRef); + Compiler* compiler = env.createCompiler(); + + BuildTree output; + BuildTreeWriter writer(output); + Compiler::Namespace nsScope(compiler, moduleScope, TestErrorProcessor::getInstance(), nullptr, nullptr); + + // Act + nsScope.declare(declarationNode.firstChild(), true); + + Compiler::Class classHelper(nsScope, targetRef, Visibility::Public); + classHelper.load(); + Compiler::Method methodHelper(classHelper); + + SyntaxNode methodNode = findTargetNode(); + if (methodNode != SyntaxKey::None) + methodHelper.compile(writer, methodNode); + + // Assess + bool matched = BuildTree::compare(output.readRoot(), controlOutputNode, true); + EXPECT_TRUE(matched); + + freeobj(compiler); + freeobj(moduleScope); +} + +// --- VariadicRuntimeSingleDispatch --- + +SyntaxNode VariadicRuntimeSingleDispatch :: findTargetNode() +{ + return findAutoGenerated(findClassNode()); +} + +void VariadicRuntimeSingleDispatch :: SetUp() +{ + DispatchTest::SetUp(); + + LoadDeclarationScenario(S1_DefaultNamespace, S1_VariadicTemplates, S1_VariadicSingleDispatch_1, S1_IntNumber); + + BuildTreeSerializer::load(BuildTree_VariadicSingleDispatch_1, controlOutputNode); + + argArrayRef = 0x80; + genericVargRef = 3; + targetVargRef = 4; + targetRef = 5; + intNumberRef = 6; +} + +// --- VariadicCompiletimeSingleDispatch --- + +SyntaxNode VariadicCompiletimeSingleDispatch :: findTargetNode() +{ + return findClassNode().findChild(SyntaxKey::Method); +} + +void VariadicCompiletimeSingleDispatch :: SetUp() +{ + DispatchTest::SetUp(); + + LoadDeclarationScenario(S1_DefaultNamespace, S1_VariadicTemplates, S1_VariadicSingleDispatch_1, S1_IntNumber, S1_VariadicSingleDispatch_2); + + BuildTreeSerializer::load(BuildTree_VariadicSingleDispatch_2, controlOutputNode); + + argArrayRef = 0x80; + genericVargRef = 3; + targetVargRef = 4; + targetRef = 7; + intNumberRef = 6; +} + +// --- VariadicCompiletimeSingleDispatch_WithDifferentArgs --- + +SyntaxNode VariadicCompiletimeSingleDispatch_WithDifferentArgs :: findTargetNode() +{ + return findClassNode().findChild(SyntaxKey::Method); +} + +void VariadicCompiletimeSingleDispatch_WithDifferentArgs :: SetUp() +{ + DispatchTest::SetUp(); + + LoadDeclarationScenario(S1_DefaultNamespace, S1_VariadicTemplates, S1_VariadicSingleDispatch_3b, S1_IntNumber, S1_VariadicSingleDispatch_1, S1_VariadicSingleDispatch_3a); + + BuildTreeSerializer::load(BuildTree_VariadicSingleDispatch_4, controlOutputNode); + + argArrayRef = 0x80; + genericVargRef = 3; + targetVargRef = 4; + targetRef = 5; + intNumberRef = 6; +} + +// --- MethodCallTest --- + +SyntaxNode MethodCallTest :: findClassNode() +{ + return SyntaxTree::gotoChild(declarationNode.firstChild(), SyntaxKey::Class, targetRef); +} + +SyntaxNode MethodCallTest :: findTargetNode() +{ + return findClassNode().findChild(SyntaxKey::Method); +} + +void MethodCallTest :: SetUp() +{ + SyntaxTreeWriter writer(syntaxTree); + writer.appendNode(SyntaxKey::Root); + + BuildTreeWriter buildWriter(buildTree); + buildWriter.appendNode(BuildKey::Root); + + declarationNode = syntaxTree.readRoot().appendChild(SyntaxKey::Idle, 1); + + controlOutputNode = buildTree.readRoot().appendChild(BuildKey::Tape); +} + +void MethodCallTest :: runTest(bool withVariadic) +{ + // Arrange + ModuleScopeBase* moduleScope = env.createModuleScope(true, false); + moduleScope->buildins.superReference = 1; + moduleScope->buildins.constructor_message = + encodeMessage(moduleScope->module->mapAction(CONSTRUCTOR_MESSAGE, 0, false), + 0, FUNCTION_MESSAGE); + + if (withVariadic) { + moduleScope->buildins.argArrayTemplateReference = argArrayRef; + + env.setUpTemplateMockup(argArrayRef, 1, genericVargRef); + env.setUpTemplateMockup(argArrayRef, 2, targetVargRef); + } + + Compiler* compiler = env.createCompiler(); + + BuildTree output; + BuildTreeWriter writer(output); + Compiler::Namespace nsScope(compiler, moduleScope, TestErrorProcessor::getInstance(), nullptr, nullptr); + + // Act + nsScope.declare(declarationNode.firstChild(), true); + + Compiler::Class classHelper(nsScope, targetRef, Visibility::Public); + classHelper.load(); + Compiler::Method methodHelper(classHelper); + + SyntaxNode methodNode = findTargetNode(); + if (methodNode != SyntaxKey::None) + methodHelper.compile(writer, methodNode); + + // Assess + bool matched = BuildTree::compare(output.readRoot(), controlOutputNode, true); + EXPECT_TRUE(matched); + + freeobj(compiler); + freeobj(moduleScope); +} + +// --- CallMethodWithoutTarget --- + +void CallMethodWithoutTarget :: SetUp() +{ + MethodCallTest::SetUp(); + + targetRef = 4; + + LoadDeclarationScenario(S1_DefaultNamespace, S1_DirectCall_1, S1_DirectCall_2); + + BuildTreeSerializer::load(BuildTree_CallMethodWithoutTarget, controlOutputNode); +} + +// --- CallVariadocMethodWithoutTarget --- + +void CallVariadocMethodWithoutTarget :: SetUp() +{ + MethodCallTest::SetUp(); + + argArrayRef = 0x80; + targetRef = 4; + genericVargRef = 5; + targetVargRef = 6; + + LoadDeclarationScenario(S1_DefaultNamespace, S1_DirectCall_1, S1_DirectCall_3, S1_VariadicTemplates); + + BuildTreeSerializer::load(BuildTree_CallVariadicMethodWithoutTarget, controlOutputNode); +} + +// --- VariadicCompiletimeConstructorSingleDispatch --- + +void VariadicCompiletimeConstructorSingleDispatch :: SetUp() +{ + DispatchTest::SetUp(); + + LoadDeclarationScenario(S1_DefaultNamespace, S1_VariadicTemplates, S1_VariadicConstructorSingleDispatch_1, S1_IntNumber); + + BuildTreeSerializer::load(BuildTree_VariadicSingleDispatch_3, controlOutputNode); + + argArrayRef = 0x80; + genericVargRef = 3; + targetVargRef = 4; + targetRef = 5; + intNumberRef = 7; +} + +SyntaxNode VariadicCompiletimeConstructorSingleDispatch :: findTargetNode() +{ + return findClassNode().findChild(SyntaxKey::Method); +} + +// --- LambdaTest --- + +SyntaxNode LambdaTest :: findClassNode() +{ + return SyntaxTree::gotoChild(declarationNode.firstChild(), SyntaxKey::Class, targetRef); +} + +SyntaxNode LambdaTest :: findTargetNode() +{ + return findClassNode().findChild(SyntaxKey::Method); +} + +BuildNode LambdaTest :: findOutput(BuildNode root) +{ + return BuildTree::gotoChild(root, BuildKey::Class, outputRef).findChild(BuildKey::Method); +} + +void LambdaTest :: SetUp() +{ + SyntaxTreeWriter writer(syntaxTree); + writer.appendNode(SyntaxKey::Root); + + BuildTreeWriter buildWriter(buildTree); + buildWriter.appendNode(BuildKey::Root); + + declarationNode = syntaxTree.readRoot().appendChild(SyntaxKey::Idle, 1); + + controlOutputNode = buildTree.readRoot().appendChild(BuildKey::Idle); +} + +void LambdaTest :: runTest() +{ + // Arrange + ModuleScopeBase* moduleScope = env.createModuleScope(true, false, true); + moduleScope->buildins.superReference = 1; + moduleScope->buildins.dispatch_message = encodeMessage( + moduleScope->module->mapAction(DISPATCH_MESSAGE, 0, false), 1, 0); + moduleScope->buildins.constructor_message = + encodeMessage(moduleScope->module->mapAction(CONSTRUCTOR_MESSAGE, 0, false), + 0, FUNCTION_MESSAGE); + + moduleScope->buildins.closureTemplateReference = funcRef; + + //env.setUpTemplateMockup(argArrayRef, 1, genericVargRef); + + Compiler* compiler = env.createCompiler(); + + BuildTree output; + BuildTreeWriter writer(output); + Compiler::Namespace nsScope(compiler, moduleScope, TestErrorProcessor::getInstance(), nullptr, nullptr); + + // Act + nsScope.declare(declarationNode.firstChild(), true); + + Compiler::Class classHelper(nsScope, targetRef, Visibility::Public); + classHelper.load(); + Compiler::Method methodHelper(classHelper); + + SyntaxNode methodNode = findTargetNode(); + if (methodNode != SyntaxKey::None) { + writer.newNode(BuildKey::Root); + writer.newNode(BuildKey::Class); + methodHelper.compile(writer, methodNode); + writer.closeNode(); + writer.closeNode(); + } + + // Assess + bool matched = BuildTree::compare(findOutput(output.readRoot()), controlOutputNode, true); + EXPECT_TRUE(matched); + + freeobj(compiler); + freeobj(moduleScope); +} + +// --- Lambda_CallingPrivateMethod --- + +void Lambda_CallingPrivateMethod :: SetUp() +{ + LambdaTest::SetUp(); + + LoadDeclarationScenario(S2_DefaultNamespace, S2_Func, S2_Scenario1); + + BuildTreeSerializer::load(BuildTree_LambdaCallPrivate, controlOutputNode); + funcRef = 2; + targetRef = 3; + outputRef = 0x100; +} \ No newline at end of file diff --git a/elenasrc3/elena-tests/bt_optimization.h b/elenasrc3/elena-tests/bt_optimization.h index 7e7087c91c..b4e52db6ce 100644 --- a/elenasrc3/elena-tests/bt_optimization.h +++ b/elenasrc3/elena-tests/bt_optimization.h @@ -63,6 +63,44 @@ namespace elena_lang } }; + class Scenario1Test : public testing::Test + { + protected: + SyntaxTree syntaxTree; + BuildTree buildTree; + + SyntaxNode declarationNode; + + BuildNode controlOutputNode; + + CompilerEnvironment env; + + void LoadDeclarationScenario(ustr_t common, ustr_t descr1, ustr_t descr2); + void LoadDeclarationScenario(ustr_t common, ustr_t descr1, ustr_t descr2, ustr_t descr3); + void LoadDeclarationScenario(ustr_t common, ustr_t descr1, ustr_t descr2, ustr_t descr3, ustr_t descr4); + void LoadDeclarationScenario(ustr_t common, ustr_t descr1, ustr_t descr2, ustr_t descr3, ustr_t descr4, ustr_t descr5); + }; + + class DispatchTest : public Scenario1Test + { + protected: + ref_t genericVargRef; + ref_t targetVargRef; + ref_t targetRef; + ref_t argArrayRef; + ref_t intNumberRef; + + SyntaxNode findAutoGenerated(SyntaxNode classNode); + SyntaxNode findClassNode(); + + virtual SyntaxNode findTargetNode() = 0; + + void SetUp() override; + + public: + void runTest(bool withProtectedConstructor = false); + }; + // Optimization #2 (byRefOp) : "a := b.get()" => "b.get(ref a)" class BTOptimization1_1 : public BTOptimization { @@ -118,6 +156,91 @@ namespace elena_lang protected: void SetUp() override; }; + + class VariadicRuntimeSingleDispatch : public DispatchTest + { + protected: + SyntaxNode findTargetNode() override; + + void SetUp() override; + }; + + class VariadicCompiletimeSingleDispatch : public DispatchTest + { + protected: + SyntaxNode findTargetNode() override; + + void SetUp() override; + }; + + class VariadicCompiletimeSingleDispatch_WithDifferentArgs : public DispatchTest + { + protected: + SyntaxNode findTargetNode() override; + + void SetUp() override; + }; + + class VariadicCompiletimeConstructorSingleDispatch : public DispatchTest + { + protected: + SyntaxNode findTargetNode() override; + + void SetUp() override; + }; + + class MethodCallTest : public Scenario1Test + { + protected: + ref_t targetRef; + ref_t argArrayRef; + ref_t genericVargRef; + ref_t targetVargRef; + + SyntaxNode findClassNode(); + virtual SyntaxNode findTargetNode(); + + void SetUp() override; + + public: + void runTest(bool withVariadic); + }; + + class CallMethodWithoutTarget : public MethodCallTest + { + protected: + void SetUp() override; + }; + + class CallVariadocMethodWithoutTarget : public MethodCallTest + { + protected: + void SetUp() override; + }; + + class LambdaTest : public Scenario1Test + { + protected: + ref_t targetRef; + ref_t funcRef; + ref_t outputRef; + + BuildNode findOutput(BuildNode root); + + SyntaxNode findClassNode(); + virtual SyntaxNode findTargetNode(); + + void SetUp() override; + + public: + void runTest(); + }; + + class Lambda_CallingPrivateMethod : public LambdaTest + { + protected: + void SetUp() override; + }; } #endif diff --git a/elenasrc3/elena-tests/compiler_tests.cpp b/elenasrc3/elena-tests/compiler_tests.cpp index d0e9856cdb..fdefeaaecd 100644 --- a/elenasrc3/elena-tests/compiler_tests.cpp +++ b/elenasrc3/elena-tests/compiler_tests.cpp @@ -36,7 +36,38 @@ TEST_F(PackedStructAlignment, CompilerTest) runTest(); } -TEST_F(ComplexStructAlignment, CompilerTest) +TEST_F(VariadicRuntimeSingleDispatch, CompilerTest) { runTest(); -} \ No newline at end of file +} + +TEST_F(VariadicCompiletimeSingleDispatch, CompilerTest) +{ + runTest(); +} + +TEST_F(CallMethodWithoutTarget, CompilerTest) +{ + runTest(false); +} + +TEST_F(CallVariadocMethodWithoutTarget, CompilerTest) +{ + runTest(false); +} + +TEST_F(VariadicCompiletimeConstructorSingleDispatch, CompilerTest) +{ + runTest(true); +} + +// Test scenario : E.load(new C(), new D()); where: class E { constructor load(params B[] args) {}}, C:B and D:B +TEST_F(VariadicCompiletimeSingleDispatch_WithDifferentArgs, CompilerTest) +{ + runTest(); +} + +TEST_F(Lambda_CallingPrivateMethod, CompilerTest) +{ + runTest(); +} diff --git a/elenasrc3/elena-tests/tests_common.cpp b/elenasrc3/elena-tests/tests_common.cpp index f1362c82d1..94e163d87e 100644 --- a/elenasrc3/elena-tests/tests_common.cpp +++ b/elenasrc3/elena-tests/tests_common.cpp @@ -37,7 +37,7 @@ TestModuleScope::TestModuleScope(bool tapeOptMode, bool threadFriendly) : ModuleScopeBase(new Module(), nullptr, DEFAULT_STACKALIGNMENT, DEFAULT_RAW_STACKALIGNMENT, DEFAULT_EHTABLE_ENTRY_SIZE, MINIMAL_ARG_LIST, sizeof(uintptr_t), tapeOptMode, threadFriendly) { - + _anonymousRef = 0x100; } bool TestModuleScope :: isStandardOne() @@ -52,7 +52,7 @@ bool TestModuleScope :: withValidation() ref_t TestModuleScope :: mapAnonymous(ustr_t prefix) { - return 0; + return _anonymousRef++; } ref_t TestModuleScope :: mapNewIdentifier(ustr_t ns, ustr_t identifier, Visibility visibility) @@ -164,6 +164,11 @@ bool TestModuleScope :: isDeclared(ref_t reference) return false; } +bool TestModuleScope :: isSymbolDeclared(ref_t reference) +{ + return false; +} + Visibility TestModuleScope :: retrieveVisibility(ref_t reference) { return Visibility::Private; @@ -174,6 +179,10 @@ Visibility TestModuleScope :: retrieveVisibility(ref_t reference) ref_t TestTemplateProssesor :: generateClassTemplate(ModuleScopeBase& moduleScope, ustr_t ns, ref_t templateRef, List& parameters, bool declarationMode, ExtensionMap* outerExtensionList) { + ref_t mapping = _mapping.get({ templateRef, parameters.get(1).arg.reference}); + if (mapping) + return mapping; + return templateRef; } @@ -201,17 +210,28 @@ bool TestTemplateProssesor :: importCodeTemplate(ModuleScopeBase& moduleScope, r return false; } +bool TestTemplateProssesor :: importExpressionTemplate(ModuleScopeBase& moduleScope, ref_t templateRef, SyntaxNode target, + List& arguments, List& parameters) +{ + return false; +} + // --- CompilerEnvironment --- CompilerEnvironment :: CompilerEnvironment() + : _templateMapping(0) { } -ModuleScopeBase* CompilerEnvironment :: createModuleScope(bool tapeOptMode, bool threadFriendly) +ModuleScopeBase* CompilerEnvironment :: createModuleScope(bool tapeOptMode, bool threadFriendly, bool withAttributes) { auto scope = new TestModuleScope(tapeOptMode, threadFriendly); + if (withAttributes) { + scope->attributes.add("dispatch", V_DISPATCHER); + } + return scope; } @@ -225,11 +245,17 @@ void CompilerEnvironment :: initializeOperators(ModuleScopeBase* scope) 1, PROPERTY_MESSAGE); } +void CompilerEnvironment :: setUpTemplateMockup(ref_t templateRef, ref_t elementRef, ref_t reference) +{ + _templateMapping.add({ templateRef, elementRef }, reference); +} + Compiler* CompilerEnvironment :: createCompiler() { - auto compiler = new Compiler(nullptr, nullptr, TestTemplateProssesor::getInstance(), CompilerLogic::getInstance()); + auto compiler = new Compiler(nullptr, TestErrorProcessor::getInstance(), TestTemplateProssesor::getInstance(&_templateMapping), CompilerLogic::getInstance()); compiler->setNoValidation(); + compiler->setDebugMode(false); return compiler; } \ No newline at end of file diff --git a/elenasrc3/elena-tests/tests_common.h b/elenasrc3/elena-tests/tests_common.h index 484a70ad5e..6214ace964 100644 --- a/elenasrc3/elena-tests/tests_common.h +++ b/elenasrc3/elena-tests/tests_common.h @@ -12,9 +12,61 @@ namespace elena_lang { + class TestErrorProcessor : public ErrorProcessor + { + TestErrorProcessor() + : ErrorProcessor(nullptr) + { + setWarningLevel(WarningLevel::Level0); + } + + public: + void info(int code, ustr_t arg) override + { + } + + void info(int code, ustr_t arg, ustr_t arg2) override + { + } + + void raiseError(int code, ustr_t arg) override + { + } + + void raisePathError(int code, path_t arg) override + { + } + + void raisePathWarning(int code, path_t arg) override + { + } + + void raiseInternalError(int code) override + { + } + + void raiseTerminalError(int code, ustr_t pathArg, SyntaxNode node) + { + } + + void raiseTerminalWarning(int level, int code, ustr_t pathArg, SyntaxNode node) + { + } + + static ErrorProcessor* getInstance() + { + static TestErrorProcessor instance; + + return &instance; + } + + }; + // --- TestModuleScope --- class TestModuleScope : public ModuleScopeBase { + ref_t _anonymousRef; + public: bool isStandardOne() override; bool withValidation() override; @@ -66,6 +118,7 @@ namespace elena_lang bool includeNamespace(IdentifierList& importedNs, ustr_t name, bool& duplicateInclusion) override; bool isDeclared(ref_t reference) override; + bool isSymbolDeclared(ref_t reference) override; Visibility retrieveVisibility(ref_t reference) override; @@ -74,6 +127,14 @@ namespace elena_lang class TestTemplateProssesor : public TemplateProssesorBase { + Map, ref_t> _mapping; + + TestTemplateProssesor() + : _mapping(0) + { + + } + public: ref_t generateClassTemplate(ModuleScopeBase& moduleScope, ustr_t ns, ref_t templateRef, List& parameters, bool declarationMode, ExtensionMap* outerExtensionList) override; @@ -86,10 +147,17 @@ namespace elena_lang List& parameters) override; bool importCodeTemplate(ModuleScopeBase& moduleScope, ref_t templateRef, SyntaxNode target, List& arguments, List& parameters) override; + bool importExpressionTemplate(ModuleScopeBase& moduleScope, ref_t templateRef, SyntaxNode target, + List& arguments, List& parameters) override; - static TemplateProssesorBase* getInstance() + static TemplateProssesorBase* getInstance(Map, ref_t>* mapping = nullptr) { static TestTemplateProssesor instance; + if (mapping) { + for (auto it = mapping->start(); !it.eof(); ++it) { + instance._mapping.add(it.key(), *it); + } + } return &instance; } @@ -98,10 +166,14 @@ namespace elena_lang // --- CompilerEnvironment --- class CompilerEnvironment { + Map, ref_t> _templateMapping; + public: void initializeOperators(ModuleScopeBase* scope); - ModuleScopeBase* createModuleScope(bool tapeOptMode, bool threadFriendly); + ModuleScopeBase* createModuleScope(bool tapeOptMode, bool threadFriendly, bool withAttributes = false); + + void setUpTemplateMockup(ref_t templateRef, ref_t elementRef, ref_t reference); Compiler* createCompiler(); diff --git a/elenasrc3/elenasm/vmparser.cpp b/elenasrc3/elenasm/vmparser.cpp index e651cbc57c..5254f0f614 100644 --- a/elenasrc3/elenasm/vmparser.cpp +++ b/elenasrc3/elenasm/vmparser.cpp @@ -49,7 +49,7 @@ bool VMTapeParser :: parseDirective(ScriptEngineReaderBase& reader, MemoryDump* ScriptBookmark bm = reader.read(); if (reader.compare("preloaded")) { bm = reader.read(); - if (bm.state == dfaIdentifier) { + if (bm.state == dfaQuote) { writer.write(VM_PRELOADED_CMD, reader.lookup(bm)); } else throw SyntaxError("Invalid directive", bm.lineInfo); diff --git a/elenasrc3/elenavm/elenavmmachine.cpp b/elenasrc3/elenavm/elenavmmachine.cpp index 26f936ac4c..f5d0e2363f 100644 --- a/elenasrc3/elenavm/elenavmmachine.cpp +++ b/elenasrc3/elenavm/elenavmmachine.cpp @@ -116,9 +116,11 @@ void ELENAVMMachine :: init(JITLinker& linker, SystemEnv* exeEnv) _configuration->initLoader(_libraryProvider); - _compiler->populatePreloaded( - (uintptr_t)exeEnv->th_table, - (uintptr_t)exeEnv->th_single_content); + if (_standAloneMode) { + _compiler->populatePreloaded( + (uintptr_t)exeEnv->th_table, + (uintptr_t)exeEnv->th_single_content); + } linker.setCompiler(_compiler); @@ -224,7 +226,7 @@ void ELENAVMMachine :: fillPreloadedSymbols(JITLinker& jitLinker, MemoryWriter& { ModuleInfoList symbolList({}); for (auto it = _preloadedList.start(); !it.eof(); ++it) { - jitLinker.copyMetaList(*it, symbolList); + jitLinker.copyPreloadedMetaList(*it, symbolList, false); } _preloadedList.clear(); @@ -437,7 +439,7 @@ addr_t ELENAVMMachine :: interprete(SystemEnv* env, void* tape, pos_t size, else jitLinker->setCompiler(_compiler); } - if (_initialized && compileVMTape(reader, tapeSymbol, *jitLinker, dummyModule)) { + if (_initialized && jitLinker && compileVMTape(reader, tapeSymbol, *jitLinker, dummyModule)) { void* address = (void*)jitLinker->resolveTemporalByteCode(tapeSymbol, dummyModule); resumeVM(*jitLinker, env, (void*)criricalHandler); @@ -447,7 +449,7 @@ addr_t ELENAVMMachine :: interprete(SystemEnv* env, void* tape, pos_t size, return execute(env, address); } - if (_initialized && !_standAloneMode) { + if (_initialized && jitLinker && !_standAloneMode) { resumeVM(*jitLinker, env, (void*)criricalHandler); } @@ -474,6 +476,16 @@ addr_t ELENAVMMachine :: evaluate(void* tape) return interprete(_env, tape, INVALID_POS, nullptr, false); } +bool ELENAVMMachine :: evaluateAndReturn(void* tape, char* output, size_t maxLength, size_t& copied) +{ + auto result = evaluate(tape); + if (result) { + return SystemRoutineProvider::CopyResult(result, output, maxLength, copied); + } + + return false; +} + void ELENAVMMachine :: Exit(int exitCode) { __routineProvider.Exit(exitCode); diff --git a/elenasrc3/elenavm/elenavmmachine.h b/elenasrc3/elenavm/elenavmmachine.h index 33508a373d..a9a0dff0f3 100644 --- a/elenasrc3/elenavm/elenavmmachine.h +++ b/elenasrc3/elenavm/elenavmmachine.h @@ -16,9 +16,6 @@ namespace elena_lang { - constexpr auto ELENAVM_GREETING = "ELENA VM %d.%d.%d (C)2022-2024 by Aleksey Rakov"; - constexpr auto ELENAVM_INITIALIZING = "Initializing..."; - // --- ELENAVMConfiguration --- class ELENAVMConfiguration : public XmlProjectBase @@ -110,6 +107,8 @@ namespace elena_lang addr_t evaluate(void* tape); + bool evaluateAndReturn(void* tape, char* output, size_t maxLength, size_t& copied); + size_t loadMessageName(mssg_t messageRef, char* buffer, size_t length); size_t loadAddressInfo(addr_t retPoint, char* lineInfo, size_t length); diff --git a/elenasrc3/elenavm/vmcommon.h b/elenasrc3/elenavm/vmcommon.h index 5596e78f68..6956f30bd3 100644 --- a/elenasrc3/elenavm/vmcommon.h +++ b/elenasrc3/elenavm/vmcommon.h @@ -9,6 +9,13 @@ #ifndef VMCOMMON_H #define VMCOMMON_H -#define ELENAVM_REVISION_NUMBER 0x0022 +#define ELENAVM_REVISION_NUMBER 0x0025 + +namespace elena_lang +{ + constexpr auto ELENAVM_GREETING = "ELENA VM %d.%d.%d (C)2022-2024 by Aleksey Rakov"; + + constexpr auto ELENAVM_INITIALIZING = "Initializing..."; +} #endif diff --git a/elenasrc3/elenavm/windows/dllmain.cpp b/elenasrc3/elenavm/windows/dllmain.cpp index bcb5a22421..72ebbfee12 100644 --- a/elenasrc3/elenavm/windows/dllmain.cpp +++ b/elenasrc3/elenavm/windows/dllmain.cpp @@ -201,6 +201,100 @@ EXTERN_DLL_EXPORT int EvaluateVMLA(void* tape) return retVal; } +EXTERN_DLL_EXPORT int PrepareVMLA(const char* configName, const char* ns, const char* path, const char* exceptionHandler) +{ +#ifdef DEBUG_OUTPUT + printf("PrepareVMLA\n"); +#endif + + IdentifierString package(ns, "=", path); + + auto env = new SystemEnv(); + env->gc_yg_size = 0x15000; + env->gc_mg_size = 0x54000; + env->th_single_content = new ThreadContent(); + + MemoryDump tape; + MemoryWriter tapeWriter(&tape); + + tapeWriter.writeDWord(VM_TERMINAL_CMD); + + tapeWriter.writeDWord(VM_CONFIG_CMD); + tapeWriter.writeString(configName); // vm_client + + tapeWriter.writeDWord(VM_PACKAGE_CMD); + tapeWriter.writeString(*package); // "embedded1=." + + tapeWriter.writeDWord(VM_INIT_CMD); + tapeWriter.writeDWord(VM_ENDOFTAPE_CMD); + + return InitializeVMSTLA(env, tape.get(0), exceptionHandler); +} + +EXTERN_DLL_EXPORT int ExecuteVMLA(const char* target, const char* arg, char* output, size_t maxLength) +{ +#ifdef DEBUG_OUTPUT + printf("ExecuteVMLA.6\n"); +#endif + + MemoryDump tape; + MemoryWriter tapeWriter(&tape); + + tapeWriter.writeDWord(VM_ALLOC_CMD); + tapeWriter.writeDWord(2); + + tapeWriter.writeDWord(VM_STRING_CMD); + tapeWriter.writeString(arg); + + tapeWriter.writeDWord(VM_SET_ARG_CMD); + tapeWriter.writeDWord(0); + + tapeWriter.writeDWord(VM_CALLSYMBOL_CMD); + tapeWriter.writeString(target); + + tapeWriter.writeDWord(VM_SEND_MESSAGE_CMD); + tapeWriter.writeString("function:#invoke[1]"); + + tapeWriter.writeDWord(VM_ENDOFTAPE_CMD); + + int retVal = -1; + try + { + if (output) { + size_t copied = 0; + if (machine->evaluateAndReturn(tape.get(0), output, maxLength, copied)) + retVal = (int)copied; + } + else { + machine->evaluate(tape.get(0)); + retVal = 0; + } + } + catch (InternalError err) + { + printError(err.messageCode); + retVal = -1; + } + catch (JITUnresolvedException& e) + { + printError(errVMReferenceNotFound, e.referenceInfo.referenceName); + + retVal = -1; + } + catch (...) + { + printError(errVMBroken); + retVal = -1; + } + + return retVal; +} + +EXTERN_DLL_EXPORT int FreeVMLA() +{ + return -1; +} + EXTERN_DLL_EXPORT void ExitLA(int retVal) { if (retVal) { diff --git a/elenasrc3/elenavm/windows/elenawinvmachine.h b/elenasrc3/elenavm/windows/elenawinvmachine.h index 61c75a2854..a8823fe665 100644 --- a/elenasrc3/elenavm/windows/elenawinvmachine.h +++ b/elenasrc3/elenavm/windows/elenawinvmachine.h @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------- // E L E N A P r o j e c t: ELENA Windows VM declaration // -// (C)2022-2023, by Aleksey Rakov +// (C)2022-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #ifndef ELENAWINVMMACHINE_H @@ -15,9 +15,9 @@ namespace elena_lang constexpr auto TEXT_MAX_SIZE = 0x500000; constexpr auto RDATA_MAX_SIZE = 0x500000; -constexpr auto DATA_MAX_SIZE = 0x001000; +constexpr auto DATA_MAX_SIZE = 0x010000; constexpr auto STAT_MAX_SIZE = 0x010000; -constexpr auto ADATA_MAX_SIZE = 0x010000; +constexpr auto ADATA_MAX_SIZE = 0x100000; constexpr auto MDATA_MAX_SIZE = 0x100000; constexpr auto MBDATA_MAX_SIZE = 0x100000; constexpr auto DEBUG_MAX_SIZE = 0x500000; diff --git a/elenasrc3/elenavm/windows/winsection.cpp b/elenasrc3/elenavm/windows/winsection.cpp index 23de47bdbb..15d39e633f 100644 --- a/elenasrc3/elenavm/windows/winsection.cpp +++ b/elenasrc3/elenavm/windows/winsection.cpp @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------- // E L E N A P r o j e c t: ELENA Windows Image Section implementation // -// (C)2022-2023, by Aleksey Rakov +// (C)2022-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #include "elena.h" diff --git a/elenasrc3/elenavm/windows/winsection.h b/elenasrc3/elenavm/windows/winsection.h index 231a3c7a13..ac304954ea 100644 --- a/elenasrc3/elenavm/windows/winsection.h +++ b/elenasrc3/elenavm/windows/winsection.h @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------- // E L E N A P r o j e c t: ELENA Windows Image Section declaration // -// (C)2022-2023, by Aleksey Rakov +// (C)2022-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #ifndef WINSECTION_H diff --git a/elenasrc3/engine/armhelper.h b/elenasrc3/engine/armhelper.h index 469b0d015f..9db6ac704c 100644 --- a/elenasrc3/engine/armhelper.h +++ b/elenasrc3/engine/armhelper.h @@ -398,15 +398,15 @@ namespace elena_lang imm &= Mask; if (isShiftedMask_64(imm)) { - I = countTrailingZeros(imm); - CTO = countTrailingOnes(imm >> I); + I = (uint32_t)countTrailingZeros(imm); + CTO = (uint32_t)countTrailingOnes(imm >> I); } else { imm |= ~Mask; if (!isShiftedMask_64(~imm)) return false; - unsigned CLO = countLeadingOnes(imm); + unsigned CLO = countLeadingOnes((uint32_t)imm); I = 64 - CLO; CTO = CLO + (uint32_t)countTrailingOnes(imm) - (64 - Size); } diff --git a/elenasrc3/engine/bcwriter.cpp b/elenasrc3/engine/bcwriter.cpp index 5c54b6bd80..2032d0a26c 100644 --- a/elenasrc3/engine/bcwriter.cpp +++ b/elenasrc3/engine/bcwriter.cpp @@ -585,7 +585,6 @@ void intLongOp(CommandTape& tape, BuildNode& node, TapeScope&) default: throw InternalError(errFatalError); } - } void realIntOp(CommandTape& tape, BuildNode& node, TapeScope&) @@ -1821,7 +1820,7 @@ void unboxingMessage(CommandTape& tape, BuildNode& node, TapeScope&) // sub n:(index + 1) // alloc i:1 // store sp:0 - // set fp:arg + // swap sp:0 // dtrans // swap sp:0 @@ -1848,6 +1847,89 @@ void unboxingMessage(CommandTape& tape, BuildNode& node, TapeScope&) tape.write(ByteCode::XRefreshSI, 1); } +void unboxingAndCallMessage(CommandTape& tape, BuildNode& node, TapeScope&) +{ + int index = node.findChild(BuildKey::Index).arg.value; + int length = node.findChild(BuildKey::Length).arg.value; + int temp = node.findChild(BuildKey::TempVar).arg.value; + mssg_t message = node.findChild(BuildKey::Message).arg.value; + + // nsave dp:tmp, 0 + // load dp:length + // add n:index + // dalloc + // set sp:index + // + // alloc i:2 + // store sp:1 + + // nadd dp:length, -1 + // labStart: + // load dp:tmp + // xcmp dp:length + // jeq labEnd + + // set fp:arg + // xget + // store sp:0 + // mov m:typeMessage + // call vt:0 + // store sp:0 + + // load dp:tmp + // peek sp:1 + // xassign + + // nadd dp:tmp, 1 + // jump labStart + // labEnd: + + // xstore sp:0, -1 + // peek sp:1 + // xassign + // free i:2 + + tape.write(ByteCode::NSaveDPN, temp, 0); + tape.write(ByteCode::LoadDP, length); + tape.write(ByteCode::AddN, index); + tape.write(ByteCode::DAlloc); + tape.write(ByteCode::SetSP, index); + tape.write(ByteCode::AllocI, 2); + tape.write(ByteCode::StoreSI, 1); + tape.write(ByteCode::NAddDPN, length, -1); + + tape.newLabel(); // labStart + tape.setLabel(true); + tape.write(ByteCode::LoadDP, temp); + tape.write(ByteCode::XCmpDP, length); + tape.newLabel(); // labEnd + tape.write(ByteCode::Jeq, PseudoArg::CurrentLabel); + + tape.write(ByteCode::SetFP, node.arg.value); + tape.write(ByteCode::XGet); + tape.write(ByteCode::StoreSI, 0); + tape.write(ByteCode::MovM, message); + tape.write(ByteCode::CallVI, 0); + tape.write(ByteCode::StoreSI, 0); + tape.write(ByteCode::XRefreshSI, 1); // NOTE : sp[1] is not refreshed after the operation + + tape.write(ByteCode::LoadDP, temp); + tape.write(ByteCode::PeekSI, 1); + tape.write(ByteCode::XAssign); + + tape.write(ByteCode::NAddDPN, temp, 1); + tape.write(ByteCode::Jump, PseudoArg::PreviousLabel); + tape.setLabel(); + tape.releaseLabel(); + + tape.write(ByteCode::XStoreSIR, 0, -1); + tape.write(ByteCode::PeekSI, 1); + tape.write(ByteCode::XAssign); + tape.write(ByteCode::FreeI, 2); + tape.write(ByteCode::XRefreshSI, 0); // NOTE : sp[0] is not refreshed + tape.write(ByteCode::XRefreshSI, 1); // NOTE : sp[1] is not refreshed +} + void loadingSubject(CommandTape& tape, BuildNode& node, TapeScope&) { int index = node.findChild(BuildKey::Index).arg.value; @@ -2022,7 +2104,7 @@ ByteCodeWriter::Saver commands[] = copyingToAccExact, savingInt, addingInt, loadingAccToIndex, indexOp, savingIndexToAcc, continueOp, semiDirectCallOp, intRealOp, realIntOp, copyingToLocalArr, loadingStackDump, savingStackDump, savingFloatIndex, intCopyingToAccField, intOpWithConst, - uint8CondOp, uint16CondOp, intLongOp, distrConstant + uint8CondOp, uint16CondOp, intLongOp, distrConstant, unboxingAndCallMessage }; inline bool duplicateBreakpoints(BuildNode lastNode) @@ -2366,6 +2448,9 @@ inline bool nativeBranchingOp(BuildNode lastNode) case BuildKey::RealCondOp: branchNode.setKey(BuildKey::RealBranchOp); break; + case BuildKey::NilCondOp: + branchNode.setKey(BuildKey::NilRefBranchOp); + break; default: break; } @@ -2798,6 +2883,11 @@ void ByteCodeWriter :: saveNativeBranching(CommandTape& tape, BuildNode node, Ta tape.write(ByteCode::CmpN, valueNode.arg.value); break; } + case BuildKey::NilRefBranchOp: + // NOTE : sp[0] - loperand + tape.write(ByteCode::PeekSI, 0); + tape.write(ByteCode::CmpR); + break; default: assert(false); break; @@ -3331,6 +3421,7 @@ void ByteCodeWriter :: saveTape(CommandTape& tape, BuildNode node, TapeScope& ta case BuildKey::IntBranchOp: case BuildKey::IntConstBranchOp: case BuildKey::RealBranchOp: + case BuildKey::NilRefBranchOp: saveNativeBranching(tape, current, tapeScope, paths, tapeOptMode, loopMode); weakLoop = false; break; diff --git a/elenasrc3/engine/buildtree.h b/elenasrc3/engine/buildtree.h index 59a085cbe7..dd879f4080 100644 --- a/elenasrc3/engine/buildtree.h +++ b/elenasrc3/engine/buildtree.h @@ -159,8 +159,10 @@ namespace elena_lang UShortCondOp = 0x0081, IntLongOp = 0x0082, DistributedTypeList = 0x0083, + UnboxAndCallMessage = 0x0084, + NilRefBranchOp = 0x0085, - MaxOperationalKey = 0x0082, + MaxOperationalKey = 0x0085, Import = 0x0090, DictionaryOp = 0x0091, @@ -230,6 +232,8 @@ namespace elena_lang Special = 0x8010, LongMode = 0x8011, Source = 0x8012, + Length = 0x8013, + TempVar = 0x8014, Idle = 0x8FFF, @@ -332,6 +336,7 @@ namespace elena_lang map.add("local", BuildKey::Local); map.add("intcondop", BuildKey::IntCondOp); map.add("realcondop", BuildKey::RealCondOp); + map.add("nilcondop", BuildKey::NilCondOp); map.add("branchop", BuildKey::BranchOp); map.add("intbranchop", BuildKey::IntBranchOp); map.add("conversion_op", BuildKey::ConversionOp); @@ -347,6 +352,19 @@ namespace elena_lang map.add("open_statement", BuildKey::OpenStatement); map.add("end_statement", BuildKey::EndStatement); map.add("saving_int", BuildKey::SavingInt); + map.add("sealed_dispatching", BuildKey::SealedDispatchingOp); + map.add("local_reference", BuildKey::LocalReference); + map.add("varg_sop", BuildKey::VArgSOp); + map.add("unbox_call_message", BuildKey::UnboxAndCallMessage); + map.add("loading_index", BuildKey::LoadingIndex); + map.add("free_varstack", BuildKey::FreeVarStack); + map.add("exit", BuildKey::Exit); + map.add("parameter", BuildKey::Parameter); + map.add("call_op", BuildKey::CallOp); + map.add("terminator", BuildKey::TerminatorReference); + map.add("free_varstack", BuildKey::FreeVarStack); + map.add("going_to_eop", BuildKey::goingToEOP); + map.add("field", BuildKey::Field); map.add("value", BuildKey::Value); map.add("tape", BuildKey::Tape); @@ -357,6 +375,13 @@ namespace elena_lang map.add("variable_info", BuildKey::VariableInfo); map.add("column", BuildKey::Column); map.add("row", BuildKey::Row); + map.add("message", BuildKey::Message); + map.add("index", BuildKey::Index); + map.add("length", BuildKey::Length); + map.add("temp_var", BuildKey::TempVar); + map.add("message", BuildKey::Message); + map.add("reserved", BuildKey::Reserved); + map.add("reserved_n", BuildKey::ReservedN); } }; diff --git a/elenasrc3/engine/codescope.cpp b/elenasrc3/engine/codescope.cpp index 08b244e65c..1bdd93edbd 100644 --- a/elenasrc3/engine/codescope.cpp +++ b/elenasrc3/engine/codescope.cpp @@ -50,6 +50,7 @@ addr_t ReferenceMapper :: resolveReference(ustr_t referenceName, ref_t sectionMa case mskTypeListRef: case mskConstArray: case mskConstant: + case mskDistrTypeListRef: return _constReferences.get(referenceName); case mskExternalRef: return resolveExternal(referenceName); @@ -96,6 +97,7 @@ void ReferenceMapper :: mapReference(ustr_t referenceName, addr_t address, ref_t case mskTypeListRef: case mskConstArray: case mskConstant: + case mskDistrTypeListRef: _constReferences.add(referenceName, address); break; case mskMssgLiteralRef: diff --git a/elenasrc3/engine/elenaconst.h b/elenasrc3/engine/elenaconst.h index 6576b0e51f..595921f2cf 100644 --- a/elenasrc3/engine/elenaconst.h +++ b/elenasrc3/engine/elenaconst.h @@ -3,7 +3,7 @@ // // This file contains the common ELENA Compiler Engine templates, // classes, structures, functions and constants -// (C)2021-2023, by Aleksey Rakov +// (C)2021-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #ifndef ELENACONST_H @@ -17,7 +17,7 @@ namespace elena_lang 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 MESSAGE_LEN = 0x400; // the maximal message length // --- ELENA Standart message constants --- constexpr auto ACTION_ORDER = 9; @@ -120,6 +120,7 @@ namespace elena_lang // --- ELENA section prefixes constexpr auto META_PREFIX = "meta$"; constexpr auto INLINE_PREFIX = "inline$"; + constexpr auto INLINEEXPR_PREFIX = "expr$"; constexpr auto INLINE_PROPERTY_PREFIX = "prop$"; constexpr auto AUTO_GENERATED_PREFIX = "generated$"; diff --git a/elenasrc3/engine/elenamachine.cpp b/elenasrc3/engine/elenamachine.cpp index 6092790adb..bc4e26fb66 100644 --- a/elenasrc3/engine/elenamachine.cpp +++ b/elenasrc3/engine/elenamachine.cpp @@ -81,8 +81,6 @@ void SystemRoutineProvider :: Init(SystemEnv* env, SystemSettings settings) void SystemRoutineProvider :: InitSTA(SystemEnv* env) { - - SystemSettings settings; FillSettings(env, settings); diff --git a/elenasrc3/engine/elenamachine.h b/elenasrc3/engine/elenamachine.h index 1e0818f60f..f7506f0653 100644 --- a/elenasrc3/engine/elenamachine.h +++ b/elenasrc3/engine/elenamachine.h @@ -125,6 +125,8 @@ namespace elena_lang static void GCWaitForSignal(void* handle); static void GCWaitForSignals(size_t count, void* handles); + static bool CopyResult(addr_t value, char* output, size_t maxLength, size_t& copied); + static size_t LoadMessages(MemoryBase* msection, void* classPtr, mssg_t* output, size_t skip, size_t maxLength, bool vmMode); diff --git a/elenasrc3/engine/gcroutines.cpp b/elenasrc3/engine/gcroutines.cpp index 76e7484369..b664c821c9 100644 --- a/elenasrc3/engine/gcroutines.cpp +++ b/elenasrc3/engine/gcroutines.cpp @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------- // E L E N A P r o j e c t: GC System Routines // -// (C)2021-2023, by Aleksey Rakov +// (C)2021-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #include "elena.h" @@ -50,7 +50,7 @@ constexpr int size_mask = elObjectSizeMask64; constexpr int struct_mask = elStructMask64; constexpr int heap_inc = 0x54000; -constexpr int heapheader_inc = 0x0A800; +constexpr int heapheader_inc = 0x15000; typedef ObjectPage64 ObjectPage; @@ -520,3 +520,26 @@ void* SystemRoutineProvider :: GCRoutinePerm(GCTable* table, size_t size) return (void*)getObjectPtr(allocated); } + +bool SystemRoutineProvider :: CopyResult(addr_t value, char* output, size_t maxLength, size_t& copied) +{ + size_t size = getSize(value); + if (size < struct_mask) { + // ; if the object has fields + return false; + } + else if (size != struct_mask) { + size_t bytesToCopy = size; + bytesToCopy += (sizeof(uintptr_t) - 1); + bytesToCopy &= size_ceil; + if (bytesToCopy > maxLength) + return false; + + CopyObjectData(bytesToCopy, output, (void*)value); + + copied = bytesToCopy; + } + else copied = 0; + + return true; +} diff --git a/elenasrc3/engine/jitcompiler.cpp b/elenasrc3/engine/jitcompiler.cpp index 60b01520d5..72554f3c61 100644 --- a/elenasrc3/engine/jitcompiler.cpp +++ b/elenasrc3/engine/jitcompiler.cpp @@ -1522,6 +1522,16 @@ void elena_lang::loadFrameIndexROp(JITCompilerScope* scope) writer->writeWord((unsigned short)getFPOffset( scope->command.arg1 << scope->constants->indexPower, scope->frameOffset)); break; + case ARG12_1: + scope->compiler->writeImm12(writer, + getFPOffset(scope->command.arg1 << scope->constants->indexPower, scope->frameOffset), + 0); + break; + case INV_ARG12_1: + scope->compiler->writeImm12(writer, + -getFPOffset(scope->command.arg1 << scope->constants->indexPower, scope->frameOffset), + 0); + break; case PTR32_2: if (scope->command.arg2) scope->compiler->writeArgAddress(scope, scope->command.arg2, 0, mskRef32); @@ -1548,7 +1558,8 @@ void elena_lang::loadFrameIndexROp(JITCompilerScope* scope) break; case PTR32HI_2: { - scope->compiler->writeArgAddress(scope, scope->command.arg2, 0, mskRef32Hi); + if (scope->command.arg2) + scope->compiler->writeArgAddress(scope, scope->command.arg2, 0, mskRef32Hi); break; } case PTR32LO_2: @@ -2979,7 +2990,9 @@ void JITCompiler :: resolveLabelAddress(MemoryWriter* writer, ref_t mask, pos_t writer->Memory()->addReference(mskCodeRef32, position); break; case mskRef64: - MemoryBase::writeDWord(writer->Memory(), position, writer->position()); + //MemoryBase::writeDWord(writer->Memory(), position, writer->position()); + MemoryBase::writeQWord(writer->Memory(), position, + ptrToUInt64(writer->Memory()->get(writer->position()))); writer->Memory()->addReference(mskCodeRef64, position); break; default: diff --git a/elenasrc3/engine/jitlinker.cpp b/elenasrc3/engine/jitlinker.cpp index c1925232b1..76af187c74 100644 --- a/elenasrc3/engine/jitlinker.cpp +++ b/elenasrc3/engine/jitlinker.cpp @@ -1499,7 +1499,7 @@ void JITLinker :: copyDistributedSymbolList(ModuleInfo info, MemoryBase* target, } } -void JITLinker :: copyMetaList(ModuleInfo info, ModuleInfoList& output) +void JITLinker :: copyPreloadedMetaList(ModuleInfo info, ModuleInfoList& output, bool ignoreAutoLoadExtensions) { auto sectionInfo = _loader->getSection({ info.module, info.module->resolveReference(info.reference) }, mskTypeListRef, 0, true); if (!sectionInfo.module) @@ -1509,6 +1509,23 @@ void JITLinker :: copyMetaList(ModuleInfo info, ModuleInfoList& output) while (!bcReader.eof()) { ref_t symbolRef = bcReader.getRef(); + if (ignoreAutoLoadExtensions) { + auto classInfo = _loader->getClassSections( + { info.module, info.module->resolveReference(symbolRef & ~mskAnyRef) }, mskVMTRef, mskClassRef, true); + if (classInfo.vmtSection) { + MemoryReader vmtReader(classInfo.vmtSection); + + // skip record size + vmtReader.getPos(); + + // read VMT header + ClassHeader header; + vmtReader.read((void*)&header, sizeof(ClassHeader)); + + if (test(header.flags, elAutoLoaded | elExtension)) + continue; + } + } output.add({ info.module, symbolRef & ~mskAnyRef }); } @@ -1733,7 +1750,7 @@ ref_t JITLinker :: resolveAction(ustr_t actionName) return resolveWeakAction(actionName); } -void JITLinker :: loadPreloaded(ustr_t preloadedSection) +void JITLinker :: loadPreloaded(ustr_t preloadedSection, bool ignoreAutoLoadExtensions) { ModuleInfoList list({}); ModuleInfoList symbolList({}); @@ -1743,7 +1760,7 @@ void JITLinker :: loadPreloaded(ustr_t preloadedSection) // load preloaded symbols _loader->loadDistributedSymbols(*nameToResolve, list); for (auto it = list.start(); !it.eof(); ++it) { - copyMetaList(*it, symbolList); + copyPreloadedMetaList(*it, symbolList, ignoreAutoLoadExtensions); } // save preloaded symbols as auto symbols diff --git a/elenasrc3/engine/jitlinker.h b/elenasrc3/engine/jitlinker.h index 7cdfa0794f..c5894cf5b9 100644 --- a/elenasrc3/engine/jitlinker.h +++ b/elenasrc3/engine/jitlinker.h @@ -242,7 +242,7 @@ namespace elena_lang ref_t resolveAction(ustr_t actionName); - void loadPreloaded(ustr_t preloadedSection); + void loadPreloaded(ustr_t preloadedSection, bool ignoreAutoLoadExtensions); void prepare(); void setCompiler(JITCompilerBase* compiler) { @@ -255,7 +255,7 @@ namespace elena_lang void complete(JITCompilerBase* compiler, ustr_t superClass); - void copyMetaList(ModuleInfo info, ModuleInfoList& output); + void copyPreloadedMetaList(ModuleInfo info, ModuleInfoList& output, bool ignoreAutoLoadExtensions); JITLinker(ReferenceMapperBase* mapper, LibraryLoaderBase* loader, ForwardResolverBase* forwardResolver, diff --git a/elenasrc3/engine/langcommon.h b/elenasrc3/engine/langcommon.h index c1f1cf9598..7f83daa351 100644 --- a/elenasrc3/engine/langcommon.h +++ b/elenasrc3/engine/langcommon.h @@ -430,6 +430,7 @@ namespace elena_lang constexpr auto FILE_PROLOG = "project/prolog"; constexpr auto FILE_EPILOG = "project/epilog"; constexpr auto MODULE_PROLOG = "project/moduleProlog"; + constexpr auto AUTOEXTENSION_PATH = "project/autoextension"; constexpr auto PLATFORMTYPE_KEY = "system/platform"; diff --git a/elenasrc3/engine/projectbase.h b/elenasrc3/engine/projectbase.h index 7394cfc490..f0d931cc21 100644 --- a/elenasrc3/engine/projectbase.h +++ b/elenasrc3/engine/projectbase.h @@ -3,7 +3,7 @@ // // This file contains the project base class declaration // -// (C)2021-2022, by Aleksey Rakov +// (C)2021-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #ifndef PROJECTBASE_H @@ -51,6 +51,7 @@ namespace elena_lang LibPath, ClassSymbolAutoLoad, + ModuleExtensionAutoLoad, StackAlignment, RawStackAlignment, GCMGSize, diff --git a/elenasrc3/engine/syntaxtree.cpp b/elenasrc3/engine/syntaxtree.cpp index 2522fa8b21..78ef0cac74 100644 --- a/elenasrc3/engine/syntaxtree.cpp +++ b/elenasrc3/engine/syntaxtree.cpp @@ -78,10 +78,14 @@ void SyntaxTree :: loadTokens(TokenMap& map) map.add("property_parameter", SyntaxKey::PropertyOperation); map.add("import", SyntaxKey::Import); map.add("source_path", SyntaxKey::SourcePath); + map.add("parent", SyntaxKey::Parent); + map.add("no_body", SyntaxKey::WithoutBody); + map.add("redirect", SyntaxKey::Redirect); map.add("attribute", SyntaxKey::Attribute); map.add("autogenerated", SyntaxKey::Autogenerated); map.add("type", SyntaxKey::Type); + map.add("array_type", SyntaxKey::ArrayType); map.add("output_type", SyntaxKey::OutputType); map.add("column", SyntaxKey::Column); map.add("row", SyntaxKey::Row); diff --git a/elenasrc3/engine/syntaxtree.h b/elenasrc3/engine/syntaxtree.h index a4c84090a9..795ccbdd6a 100644 --- a/elenasrc3/engine/syntaxtree.h +++ b/elenasrc3/engine/syntaxtree.h @@ -60,6 +60,7 @@ namespace elena_lang CodeBlock = 0x001C10, WithoutBody = 0x001C11, Importing = 0x001C12, + InlineTemplateExpr = 0x001013, MetaDictionary = 0x001020, MetaExpression = 0x001021, IncludeStatement = 0x001022, diff --git a/elenasrc3/engine/x86_64compiler.h b/elenasrc3/engine/x86_64compiler.h index 9d6fc9b5df..03c5ebae90 100644 --- a/elenasrc3/engine/x86_64compiler.h +++ b/elenasrc3/engine/x86_64compiler.h @@ -31,6 +31,12 @@ namespace elena_lang friend void x86_64compileExtOpenIN(JITCompilerScope* scope); public: + int calcFrameOffset(int argument, bool extMode) override + { + // NOTE : for the external frame we have to store all nonvolatile registers (rsi, rdi, rbx, r12, r13, r14, r15) + return (extMode ? 104 : 8) + (argument > 0 ? align(argument + 16, 16) : 0); + } + void writeImm9(MemoryWriter* writer, int value, int type) override; void writeImm12(MemoryWriter* writer, int value, int type) override; diff --git a/elenasrc3/engine/xmlprojectbase.cpp b/elenasrc3/engine/xmlprojectbase.cpp index e70c00170b..f004526c72 100644 --- a/elenasrc3/engine/xmlprojectbase.cpp +++ b/elenasrc3/engine/xmlprojectbase.cpp @@ -156,6 +156,24 @@ void XmlProjectBase :: loadPathSetting(ConfigFile& config, ConfigFile::Node& con } } +void XmlProjectBase :: loadBoolSetting(ConfigFile& config, ConfigFile::Node& configRoot, ustr_t xpath, + ProjectOption key) +{ + auto configNode = config.selectNode(configRoot, xpath); + if (!configNode.isNotFound()) { + DynamicString strValue; + configNode.readContent(strValue); + + bool value = ustr_t(strValue.str()).compare("-1"); + + ProjectNode node = _root.findChild(key); + if (node == ProjectOption::None) { + _root.appendChild(key, value ? "-1" : "0"); + } + else node.setStrArgument(value ? "-1" : "0"); + } +} + void XmlProjectBase :: loadKeyCollection(ConfigFile& config, ConfigFile::Node& root, ustr_t xpath, ProjectOption collectionKey, ProjectOption itemKey, ustr_t prefix) { diff --git a/elenasrc3/engine/xmlprojectbase.h b/elenasrc3/engine/xmlprojectbase.h index 798299eef9..e600efd7e8 100644 --- a/elenasrc3/engine/xmlprojectbase.h +++ b/elenasrc3/engine/xmlprojectbase.h @@ -205,6 +205,9 @@ namespace elena_lang void loadPathSetting(ConfigFile& config, ConfigFile::Node& configRoot, ustr_t xpath, ProjectOption key, path_t configPath); + void loadBoolSetting(ConfigFile& config, ConfigFile::Node& configRoot, ustr_t xpath, + ProjectOption key); + void loadForwards(ConfigFile& config, ConfigFile::Node& root, ustr_t xpath); ustr_t resolveKey(ProjectOption category, ProjectOption item, ustr_t key); diff --git a/elenasrc3/gui/document.cpp b/elenasrc3/gui/document.cpp index 348126db54..4a3e379c7c 100644 --- a/elenasrc3/gui/document.cpp +++ b/elenasrc3/gui/document.cpp @@ -71,7 +71,11 @@ void LexicalFormatter :: format() if (!reader.goTo((disp_t)length)) break; } - writer.writePos(style); + + if (_formatter->next(0, info, style)) { + writer.writePos(style); + } + else writer.writePos(0); writer.writePos(reader.position() + length); } diff --git a/elenasrc3/gui/guieditor.h b/elenasrc3/gui/guieditor.h index e86fac3b52..5ae1e08926 100644 --- a/elenasrc3/gui/guieditor.h +++ b/elenasrc3/gui/guieditor.h @@ -21,16 +21,16 @@ namespace elena_lang 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 + constexpr auto STYLE_KEYWORD = 6; + constexpr auto STYLE_OPERATOR = 7; + constexpr auto STYLE_COMMENT = 8; + constexpr auto STYLE_NUMBER = 9; + constexpr auto STYLE_STRING = 10; //#define STYLE_MESSAGE 6 - //#define STYLE_NUMBER 7 - //#define STYLE_STRING 8 //#define STYLE_HINT 9 // !! not used //#define STYLE_TRACE 12 //#define STYLE_HIGHLIGHTED_BRACKET 14 - constexpr auto STYLE_MAX = 5; + constexpr auto STYLE_MAX = 10; // --- ClipboardBase ---- class ClipboardBase diff --git a/elenasrc3/gui/windows/wincommon.cpp b/elenasrc3/gui/windows/wincommon.cpp index 4848d6cf11..ff132f0d8f 100644 --- a/elenasrc3/gui/windows/wincommon.cpp +++ b/elenasrc3/gui/windows/wincommon.cpp @@ -82,6 +82,11 @@ void ControlBase :: refresh() ::UpdateWindow(_handle); } +void ControlBase :: invalidate() +{ + ::InvalidateRect(_handle, nullptr, true); +} + bool ControlBase :: visible() { return ::IsWindowVisible(_handle) ? true : false; diff --git a/elenasrc3/gui/windows/wincommon.h b/elenasrc3/gui/windows/wincommon.h index 591be7b40e..8944cc6333 100644 --- a/elenasrc3/gui/windows/wincommon.h +++ b/elenasrc3/gui/windows/wincommon.h @@ -168,6 +168,7 @@ namespace elena_lang void setFocus() override; void refresh() override; + void invalidate(); virtual void onDrawItem(DRAWITEMSTRUCT* item) {} virtual void onSelChanged() {} diff --git a/elenasrc3/ide/debugcontroller.cpp b/elenasrc3/ide/debugcontroller.cpp index fcc0b01431..cf64c11bfc 100644 --- a/elenasrc3/ide/debugcontroller.cpp +++ b/elenasrc3/ide/debugcontroller.cpp @@ -873,11 +873,13 @@ void DebugController :: loadDebugSection(StreamReader& reader, bool starting) } void DebugController :: readObjectContent(ContextBrowserBase* watch, void* item, addr_t address, int level, - DebugLineInfo* info) + DebugLineInfo* info, addr_t vmtAddress) { WatchContext context = { item, address }; - addr_t vmtAddress = _process->getClassVMT(address); + if (!vmtAddress) + vmtAddress = _process->getClassVMT(address); + int flags = _process->getClassFlags(vmtAddress); int type = flags & elDebugMask; @@ -895,7 +897,7 @@ void DebugController :: readObjectContent(ContextBrowserBase* watch, void* item, { char value[DEBUG_MAX_STR_LENGTH + 1]; size_t length = _min(_process->getArrayLength(address), DEBUG_MAX_STR_LENGTH); - _process->readDump(address, value, length); + _process->readDump(address, value, (pos_t)length); value[length] = 0; watch->populateString(&context, value); break; @@ -904,7 +906,7 @@ void DebugController :: readObjectContent(ContextBrowserBase* watch, void* item, { wide_c value[DEBUG_MAX_STR_LENGTH + 1]; size_t length = _min(_process->getArrayLength(address), DEBUG_MAX_STR_LENGTH) >> 1; - _process->readDump(address, (char*)value, length << 1); + _process->readDump(address, (char*)value, (pos_t)(length << 1)); value[length] = 0; watch->populateWideString(&context, value); break; @@ -944,7 +946,7 @@ void* DebugController :: readObject(ContextBrowserBase* watch, void* parent, add void* item = watch->addOrUpdate(&context, name, *classNameStr); if (level > 0) - readObjectContent(watch, item, address, level, info); + readObjectContent(watch, item, address, level, info, vmtAddress); return item; } @@ -1078,6 +1080,17 @@ void* DebugController :: readUIntLocal(ContextBrowserBase* watch, void* parent, else return nullptr; } +void* DebugController :: readByteLocal(ContextBrowserBase* watch, void* parent, addr_t address, ustr_t name, int level) +{ + if (level > 0) { + unsigned int value = _process->getBYTE(address); + + WatchContext context = { parent, address }; + return watch->addOrUpdateDWORD(&context, name, value); + } + else return nullptr; +} + void* DebugController :: readLongLocal(ContextBrowserBase* watch, void* parent, addr_t address, ustr_t name, int level) { if (level > 0) { @@ -1124,6 +1137,12 @@ void* DebugController :: readFieldValue(ContextBrowserBase* watch, void* parent, if (size == 4) { return readUIntLocal(watch, parent, address, name, level); } + else if (size == 1) { + return readByteLocal(watch, parent, address, name, level); + } + else if (size == 8) { + return readLongLocal(watch, parent, address, name, level); + } else { WatchContext context = { parent, address }; void* item = watch->addOrUpdate(&context, name, className); @@ -1176,7 +1195,7 @@ void DebugController :: readContext(ContextBrowserBase* watch, void* parentItem, IdentifierString className; DebugLineInfo* info = _provider.seekClassInfo(address, className, vmtAddress, flags); - readObjectContent(watch, parentItem, address, level, info); + readObjectContent(watch, parentItem, address, level, info, vmtAddress); } } diff --git a/elenasrc3/ide/debugcontroller.h b/elenasrc3/ide/debugcontroller.h index a5563b2633..5164d43d2e 100644 --- a/elenasrc3/ide/debugcontroller.h +++ b/elenasrc3/ide/debugcontroller.h @@ -247,12 +247,13 @@ namespace elena_lang void onStop(); void readObjectContent(ContextBrowserBase* watch, void* item, addr_t address, int level, - DebugLineInfo* info); + DebugLineInfo* info, addr_t vmtAddress); void readFields(ContextBrowserBase* watch, void* parent, addr_t address, int level, DebugLineInfo* info); void readObjectArray(ContextBrowserBase* watch, void* parent, addr_t address, int level, DebugLineInfo* info); void* readObject(ContextBrowserBase* watch, void* parent, addr_t address, ustr_t name, int level, ustr_t className = nullptr, addr_t vmtAddress = 0); void* readFieldValue(ContextBrowserBase* watch, void* parent, addr_t address, ustr_t name, int level, int size, ustr_t className = nullptr); + void* readByteLocal(ContextBrowserBase* watch, void* parent, addr_t address, ustr_t name, int level); 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); diff --git a/elenasrc3/ide/eng/messages.h b/elenasrc3/ide/eng/messages.h index e37b90855b..8b6bc2a640 100644 --- a/elenasrc3/ide/eng/messages.h +++ b/elenasrc3/ide/eng/messages.h @@ -22,6 +22,8 @@ namespace elena_lang constexpr auto INFO_RUN_OUT_OF_DATE = _T("The project modules are out of date\nPlease recompile the project"); constexpr auto INFO_RUN_UNSAVED_PROJECT = _T("The project files are not saved\nPlease save them and recompile the project"); + constexpr auto INFO_NEED_TARGET = _T("A project has no target specified. It cannot be started\nPlease specify the project target"); + constexpr auto INFO_RUN_NEED_RECOMPILE = _T("A program cannot be started\nPlease re-compile the project"); constexpr auto NOT_FOUND_TEXT = _T("Search string not found"); constexpr auto REPLACE_TEXT = _T("Replace this occurence?"); diff --git a/elenasrc3/ide/ide.cpp b/elenasrc3/ide/ide.cpp deleted file mode 100644 index d72d9d751e..0000000000 --- a/elenasrc3/ide/ide.cpp +++ /dev/null @@ -1,16 +0,0 @@ -//--------------------------------------------------------------------------- -// E L E N A P r o j e c t: ELENA IDE -// IDEApp class main body -// (C)2021, by Aleksey Rakov -//--------------------------------------------------------------------------- - -#include "ide.h" - -using namespace elena_lang; - -//// --- IDEApp --- -// -//int IDEApp :: run() -//{ -// return _app->run(_mainView->window()); -//} diff --git a/elenasrc3/ide/ide.h b/elenasrc3/ide/ide.h deleted file mode 100644 index 854ce7211f..0000000000 --- a/elenasrc3/ide/ide.h +++ /dev/null @@ -1,58 +0,0 @@ -//--------------------------------------------------------------------------- -// E L E N A P r o j e c t: ELENA IDE -// IDEApp class header File -// (C)2021, by Aleksey Rakov -//--------------------------------------------------------------------------- - -#ifndef IDE_H -#define IDE_H - -#include "idecommon.h" - -namespace elena_lang -{ - - //// --- IDEApp --- - //class IDEApp : App - //{ - // GUIApp* _app; - // View* _mainView; - // GUIWindowBase* _mainWindow; - - //public: - // View* getView(); - - // int run(); - - // IDEApp(GUIFactoryBase* factory) - // { - // _app = factory->createApp(); - // _mainView = factory->createView(_app); - // _mainWindow = factory->createMainWindow(_app); - // } - - // virtual ~IDEApp() - // { - // freeobj(_mainView); - // freeobj(_app); - // } - //}; - -//class IDEController -//{ -// -//}; -// -//class IDEView -//{ -// -//}; -// -//class IDEWorkspace -//{ -// -//}; - -} // elena:lang - -#endif // IDE_H diff --git a/elenasrc3/ide/idecontroller.cpp b/elenasrc3/ide/idecontroller.cpp index 03a3a0a6de..784a226aad 100644 --- a/elenasrc3/ide/idecontroller.cpp +++ b/elenasrc3/ide/idecontroller.cpp @@ -207,7 +207,7 @@ void ProjectController :: defineSourceName(ProjectModel* model, path_t path, Nam } } -bool ProjectController :: startDebugger(ProjectModel& model) +bool ProjectController :: startDebugger(ProjectModel& model, DebugActionResult& result) { ustr_t target = model.getTarget(); ustr_t arguments = model.getArguments(); @@ -223,7 +223,7 @@ bool ProjectController :: startDebugger(ProjectModel& model) bool debugMode = model.getDebugMode(); if (debugMode) { if (!_debugController.start(exePath.str(), commandLine.str(), debugMode/*, _breakpoints */)) { - //notifyCompletion(NOTIFY_DEBUGGER_RESULT, ERROR_DEBUG_FILE_NOT_FOUND_COMPILE); + result.noDebugFile = true; return false; } @@ -240,7 +240,7 @@ bool ProjectController :: startDebugger(ProjectModel& model) return true; } else { - //notifyCompletion(NOTIFY_DEBUGGER_RESULT, ERROR_RUN_NEED_TARGET); + result.targetMissing = true; return false; } @@ -280,12 +280,12 @@ bool ProjectController :: isOutaged(ProjectModel& projectModel, SourceViewModel& return true; } -bool ProjectController :: onDebugAction(ProjectModel& model, SourceViewModel& sourceModel, DebugAction action, bool& outaged) +bool ProjectController :: onDebugAction(ProjectModel& model, SourceViewModel& sourceModel, DebugAction action, DebugActionResult& result) { if (!_debugController.isStarted()) { bool toRecompile = model.autoRecompile; if (!isOutaged(model, sourceModel)) { - outaged = true; + result.outaged = true; if (toRecompile) { if (!doCompileProject(model, action)) @@ -293,7 +293,7 @@ bool ProjectController :: onDebugAction(ProjectModel& model, SourceViewModel& so } return false; } - if (!startDebugger(model)) + if (!startDebugger(model, result)) return false; } return true; @@ -352,10 +352,14 @@ bool ProjectController :: startVMConsole(ProjectModel& model) PathString cmdLine(*model.paths.vmTerminalPath); cmdLine.append(" \"[[ #use "); + path_t outputPath = model.getOutputPath(); + if (outputPath.empty()) + outputPath = *model.projectPath; + cmdLine.append(model.getPackage()); cmdLine.append(_T("=\"\"")); - cmdLine.append(*model.projectPath); - cmdLine.append(_T("\"")); + cmdLine.append(outputPath); + cmdLine.append(_T("=\"\"")); cmdLine.append("]]\""); cmdLine.append(" -i"); @@ -1339,7 +1343,7 @@ bool IDEController :: doCloseProject(FileDialogBase& dialog, FileDialogBase& pro { int projectStatus = STATUS_NONE; - if(closeProject(dialog, projectDialog, mssgDialog, model, projectStatus)) + if(!closeProject(dialog, projectDialog, mssgDialog, model, projectStatus)) return false; notifyOnModelChange(projectStatus); @@ -1521,8 +1525,8 @@ void IDEController :: doDebugAction(IDEModel* model, DebugAction action, Message if (model->running) return; - bool outaged = false; - if (projectController.onDebugAction(model->projectModel, model->sourceViewModel, action, outaged)) { + DebugActionResult result = {}; + if (projectController.onDebugAction(model->projectModel, model->sourceViewModel, action, result)) { model->running = true; model->sourceViewModel.setReadOnlyMode(true); @@ -1538,8 +1542,15 @@ void IDEController :: doDebugAction(IDEModel* model, DebugAction action, Message } else if (model->sourceViewModel.isAnyDocumentModified()) mssgDialog.info(INFO_RUN_UNSAVED_PROJECT); - else if (outaged) + else if (result.outaged) { mssgDialog.info(INFO_RUN_OUT_OF_DATE); + } + else if (result.targetMissing) { + mssgDialog.info(INFO_NEED_TARGET); + } + else if (result.noDebugFile) { + mssgDialog.info(INFO_RUN_NEED_RECOMPILE); + } } void IDEController :: doDebugStop(IDEModel* model) diff --git a/elenasrc3/ide/idecontroller.h b/elenasrc3/ide/idecontroller.h index 8539691b26..7ef1c25c90 100644 --- a/elenasrc3/ide/idecontroller.h +++ b/elenasrc3/ide/idecontroller.h @@ -43,6 +43,18 @@ namespace elena_lang RunTo }; + struct DebugActionResult + { + bool outaged; + bool targetMissing; + bool noDebugFile; + + DebugActionResult() + { + outaged = targetMissing = noDebugFile = false; + } + }; + typedef bool(*CompareFileDateTime)(path_t, path_t); // --- ProjectController --- @@ -69,7 +81,7 @@ namespace elena_lang bool isOutaged(ProjectModel& projectModel, SourceViewModel& sourceModel); - bool startDebugger(ProjectModel& model/*, bool stepMode*/); + bool startDebugger(ProjectModel& model, DebugActionResult& result); bool isIncluded(ProjectModel& model, ustr_t ns); @@ -106,7 +118,7 @@ namespace elena_lang bool startVMConsole(ProjectModel& model); void stopVMConsole(); - bool onDebugAction(ProjectModel& model, SourceViewModel& sourceModel, DebugAction action, bool& outaged); + bool onDebugAction(ProjectModel& model, SourceViewModel& sourceModel, DebugAction action, DebugActionResult& result); void doDebugAction(ProjectModel& model, SourceViewModel& sourceModel, DebugAction action); void doDebugStop(ProjectModel& model); diff --git a/elenasrc3/ide/ideversion.h b/elenasrc3/ide/ideversion.h index 70c8a97c7d..a3e167adc4 100644 --- a/elenasrc3/ide/ideversion.h +++ b/elenasrc3/ide/ideversion.h @@ -1,2 +1,2 @@ -#define IDE_REVISION_NUMBER 128 +#define IDE_REVISION_NUMBER 132 diff --git a/elenasrc3/ide/sourceformatter.cpp b/elenasrc3/ide/sourceformatter.cpp index 8bfd26c038..fc7ea43af8 100644 --- a/elenasrc3/ide/sourceformatter.cpp +++ b/elenasrc3/ide/sourceformatter.cpp @@ -14,44 +14,35 @@ using namespace elena_lang; // --- Lexical DFA Table --- const text_c lexStart = 'a'; -const text_c lexCommentStart = 'b'; -const text_c lexKeyword = 'c'; -const text_c lexOperator = 'd'; -const text_c lexBrackets = 'e'; -const text_c lexObject = 'f'; -const text_c lexCloseBracket = 'g'; -const text_c lexStick = 'h'; -const text_c lexDigit = 'i'; -const text_c lexHint = 'j'; -const text_c lexMessage = 'k'; -const text_c lexLookahead = 'l'; -const text_c lexLineComment = 'm'; -const text_c lexComment = 'n'; -const text_c lexComment2 = 'o'; -const text_c lexQuote = 'p'; -const text_c lexQuote2 = 'q'; -const text_c lexHint2 = 'r'; +const text_c lexKeyword = 'd'; +const text_c lexObject = 'e'; +const text_c lexOperator = 'g'; +const text_c lexComment = 'j'; +const text_c lexComment2 = 'n'; +const text_c lexDigit = 'p'; +const text_c lexQuote = 's'; const text_c* lexDFA[] = { - _T("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadpcaadfegdddddliiiiiiiiiiddddddaffffffffffffffffffffffffffeaedfaffffffffffffffffffffffffffehedf"), - _T("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadpcaadfegdddddliiiiiiiiiiddddddaffffffffffffffffffffffffffeaedfaffffffffffffffffffffffffffehedf"), - _T("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadpcaadfjgdddddliiiiiiiiiiddddddacccccccccccccccccccccccccceaedcaccccccccccccccccccccccccccehedc"), - _T("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadpcaadfegdddddliiiiiiiiiiddddddaffffffffffffffffffffffffffeaedfaffffffffffffffffffffffffffehedf"), - _T("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadpcaadfegdddddliiiiiiiiiiddddddaffffffffffffffffffffffffffeaedfaffffffffffffffffffffffffffehedf"), - _T("aaaaaaaaaakaakaaaaaaaaaaaaaaaaaakdpaaadfegdddddlffffffffffddddddaffffffffffffffffffffffffffeaedfaffffffffffffffffffffffffffehedf"), - _T("aaaaaaaaaakaakaaaaaaaaaaaaaaaaaakdpaaadfegdddddliiiiiiiiiiddddddaffffffffffffffffffffffffffeaedfaffffffffffffffffffffffffffehedf"), - _T("aaaaaaaaaakaakaaaaaaaaaaaaaaaaaakdpaaadaegdddddliiiiiiiiiiddddddakkkkkkkkkkkkkkkkkkkkkkkkkkeaedkakkkkkkkkkkkkkkkkkkkkkkkkkkehedk"), - _T("aaaaaaaaaakaakaaaaaaaaaaaaaaaaaakdpcaadfegdddddliiiiiiiiiiddddddaiiiiiikkkkkkkkkkkkkkkkkkkkeaedkaiiiiiikikkkikkkkkikkkkkkkkehedk"), - _T("ajjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjrjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj"), - _T("aaaaaaaaaakaakaaaaaaaaaaaaaaaaaakdpcaadkegdddddlkkkkkkkkkkddddddakkkkkkkkkkkkkkkkkkkkkkkkkkeaedkakkkkkkkkkkkkkkkkkkkkkkkkkkehedk"), - _T("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaddpcaadfagnddddmaaaaaaaaaaddddddaffffffffffffffffffffffffffeaedfaffffffffffffffffffffffffffehedf"), - _T("ammmmmmmmmammammmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm"), - _T("nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnonnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn"), - _T("nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnbnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn"), - _T("ppppppppppppppppppppppppppppppppppqppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp"), - _T("aaaaaaaaaakaakaaaaaaaaaaaaaaaaaakdpaaadaegdddddliiiiiiiiiiddddddakkkkkkkkkkkkkkkkkkkkkkkkkkeaedkakkkkkkkkkkkkkkkkkkkkkkkkkkehedk"), - _T("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadpcaadfjgddjddliiiiiiiiiiddddddaffffffffffffffffffffffffffeaedfaffffffffffffffffffffffffffehedf"), + _T("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaeqaaaaaeeeeeeehooooooooooeeeeeeabbbbbbbbbbbbbbbbbbbbbbbbbbaaaababbbbbbbbbbbbbbbbbbbbbbbbbbfefab"), + _T("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaceaaaaaaeeeeeeeaaaaaaaaaaaeeeeeeabbbbbbbbbbbbbbbbbbbbbbbbbbaaaababbbbbbbbbbbbbbbbbbbbbbbbbbaeaab"), + _T("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaceaaaaaaeeeeeeeaaaaaaaaaaaeeeeeeaddddddddddddddddddddddddddaaaadaddddddddddddddddddddddddddaeaad"), + _T("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaeeeeeeeaaaaaaaaaaaeeeeeeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + _T("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaaafffffffaaaaaaaaaaaffffffaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaaa"), + _T("gggggggggggggggggggggggggggggggggfggggggfffffffgggggggggggffffffgggggggggggggggggggggggggggggggggggggggggggggggggggggggggggfffgg"), + _T("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + _T("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaakaaaaiaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + _T("jiiiiiiiiijiijiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii"), + _T("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + _T("kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkklkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk"), + _T("kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkmkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk"), + _T("nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn"), + _T("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + _T("ppppppppppppppppppppppppppppppppppppppppppppppppoooooooooopppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp"), + _T("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaaafffffffaaaaaaaaaaaffffffaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaaa"), + _T("qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqrqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq"), + _T("ssssssssssssssssssssssssssssssssssqsssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"), + _T("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaaafffffffaaaaaaaaaaaffffffaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaaa"), }; pos_t defineStyle(text_c state, pos_t style) @@ -60,30 +51,19 @@ pos_t defineStyle(text_c state, pos_t style) case lexStart: case lexObject: return STYLE_DEFAULT; - //case lexKeyword: - // return STYLE_KEYWORD; - //case lexMessage: - // return STYLE_MESSAGE; - //case lexOperator: - //case lexBrackets: - //case lexStick: - //case lexCloseBracket: - //case lexLookahead: - // return STYLE_OPERATOR; - //case lexLineComment: - //case lexComment: - //case lexComment2: - //case lexCommentStart: - //case lexHint: // !! temporal, do hint needs its own style - //case lexHint2: - // return STYLE_COMMENT; - //case lexDigit: - // return STYLE_NUMBER; - //case lexQuote: - //case lexQuote2: - // return STYLE_STRING; + case lexKeyword: + return STYLE_KEYWORD; + case lexOperator: + return STYLE_OPERATOR; + case lexComment: + case lexComment2: + return STYLE_COMMENT; + case lexDigit: + return STYLE_NUMBER; + case lexQuote: + return STYLE_STRING; default: - return style; + return NOTFOUND_POS; } } @@ -101,22 +81,25 @@ void SourceFormatter :: start(FormatterInfo& info) info.style = STYLE_DEFAULT; } -bool SourceFormatter :: next(text_c ch, FormatterInfo& info, pos_t& lastStyle) +bool SourceFormatter :: next(text_c ch, FormatterInfo& info, pos_t& definedStyle) { info.state = makeStep(ch, info.state); - pos_t nextStyle = defineStyle(info.state, info.style); + pos_t currentStyle = defineStyle(info.state, info.style); bool retVal = false; - if (info.lookAhead) { - info.style = nextStyle; + /*if (info.lookAhead) { + info.style = currentStyle; } - else if (info.style != nextStyle || info.state == lexLookahead) { - lastStyle = info.style; - info.style = nextStyle; + else */if (currentStyle != NOTFOUND_POS/*info.style != currentStyle*//* || info.state == lexLookahead*/) { + info.style = currentStyle; + definedStyle = currentStyle; + + info.state = makeStep(ch, info.state); + retVal = true; } - info.lookAhead = info.state == lexLookahead; + //info.lookAhead = info.state == lexLookahead; return retVal; } diff --git a/elenasrc3/ide/vs/elide.vcxproj b/elenasrc3/ide/vs/elide.vcxproj index 0280228b33..f591cbee10 100644 --- a/elenasrc3/ide/vs/elide.vcxproj +++ b/elenasrc3/ide/vs/elide.vcxproj @@ -202,7 +202,6 @@ - @@ -251,7 +250,6 @@ - diff --git a/elenasrc3/ide/windows/factory.cpp b/elenasrc3/ide/windows/factory.cpp index f70f45ffd2..59f985c45c 100644 --- a/elenasrc3/ide/windows/factory.cpp +++ b/elenasrc3/ide/windows/factory.cpp @@ -74,17 +74,11 @@ StyleInfo defaultStyles[STYLE_MAX + 1] = { {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}, - //{Colour(0x40, 0x80, 0x80), Colour(0xFF, 0xFF, 0xFF), _T("Courier New"), IDE_CHARSET_ANSI, 10, true, false}, - //{Colour(0, 0x00, 0x80), Colour(0xFF, 0xFF, 0xFF), _T("Courier New"), IDE_CHARSET_ANSI, 10, true, false}, - //{Colour(0, 0x80, 0x80), 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}, - //{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(0), Colour(0xFF, 0xFF, 0xFF), _T("Courier New"), IDE_CHARSET_ANSI, 10, true, false} + {Color(0, 0, 0xFF), Color(0xFF, 0xFF, 0xFF), _T("Courier New"), IDE_CHARSET_ANSI, 10, false, false}, + {Color(0x40, 0x80, 0x80), Color(0xFF, 0xFF, 0xFF), _T("Courier New"), IDE_CHARSET_ANSI, 10, false, false}, + {Color(0, 0x80, 0), Color(0xFF, 0xFF, 0xFF), _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}, + {Color(0, 0x80, 0x80), Color(0xFF, 0xFF, 0xFF), _T("Courier New"), IDE_CHARSET_ANSI, 10, false, false}, }; StyleInfo classicStyles[STYLE_MAX + 1] = { @@ -94,16 +88,11 @@ StyleInfo classicStyles[STYLE_MAX + 1] = { {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(0, 0, 0x80), _T("Courier New"), IDE_CHARSET_ANSI, 10, false, false}, - //{Colour(0xC0, 0xC0, 0xC0), Colour(0, 0, 0x80), _T("Courier New"), IDE_CHARSET_ANSI, 10, false, false}, - //{Colour(0xC0, 0xC0, 0xC0), Colour(0, 0, 0x80), _T("Courier New"), IDE_CHARSET_ANSI, 10, false, false}, - //{Colour(0xFF, 0xFF, 0), Colour(0, 0, 0x80), _T("Courier New"), IDE_CHARSET_ANSI, 10, true, false}, - //{Colour(0, 0xFF, 0x80), Colour(0, 0, 0x80), _T("Courier New"), IDE_CHARSET_ANSI, 10, false, false}, - //{Colour(0, 0xFF, 0xFF), Colour(0, 0, 0x80), _T("Courier New"), IDE_CHARSET_ANSI, 10, false, false}, - //{Colour(0, 0, 0x80), Colour(0xC0, 0xC0, 0xC0), 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(0xFF, 0xFF, 0), Colour(0, 0, 0x80), _T("Courier New"), IDE_CHARSET_ANSI, 10, true, false} + {Color(0xFF, 0xFF, 0xFF), Color(0, 0, 0x80), _T("Courier New"), IDE_CHARSET_ANSI, 10, false, false}, + {Color(0xC0, 0xC0, 0xC0), Color(0, 0, 0x80), _T("Courier New"), IDE_CHARSET_ANSI, 10, false, false}, + {Color(0xC0, 0xC0, 0xC0), Color(0, 0, 0x80), _T("Courier New"), IDE_CHARSET_ANSI, 10, false, false}, + {Color(0, 0xFF, 0x80), Color(0, 0, 0x80), _T("Courier New"), IDE_CHARSET_ANSI, 10, false, false}, + {Color(0, 0xFF, 0xFF), Color(0, 0, 0x80), _T("Courier New"), IDE_CHARSET_ANSI, 10, false, false}, }; StyleInfo darkStyles[STYLE_MAX + 1] = { @@ -113,16 +102,11 @@ StyleInfo darkStyles[STYLE_MAX + 1] = { {Color(0xEF, 0xEF, 0xEF), Color(64, 128, 128), _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(0x80, 0x0, 0x0), _T("Courier New"), IDE_CHARSET_ANSI, 10, false, false}, - //{Colour(0xC0, 0xC0, 0xC0), Colour(0, 0, 0x80), _T("Courier New"), IDE_CHARSET_ANSI, 10, false, false}, - //{Colour(0xC0, 0xC0, 0xC0), Colour(0, 0, 0x80), _T("Courier New"), IDE_CHARSET_ANSI, 10, false, false}, - //{Colour(0xFF, 0xFF, 0), Colour(0, 0, 0x80), _T("Courier New"), IDE_CHARSET_ANSI, 10, true, false}, - //{Colour(0, 0xFF, 0x80), Colour(0, 0, 0x80), _T("Courier New"), IDE_CHARSET_ANSI, 10, false, false}, - //{Colour(0, 0xFF, 0xFF), Colour(0, 0, 0x80), _T("Courier New"), IDE_CHARSET_ANSI, 10, false, false}, - //{Colour(0, 0, 0x80), Colour(0xC0, 0xC0, 0xC0), 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(0xFF, 0xFF, 0), Colour(0, 0, 0x80), _T("Courier New"), IDE_CHARSET_ANSI, 10, true, false} + {Color(84, 255, 209), Color(50, 50, 50), _T("Courier New"), IDE_CHARSET_ANSI, 10, false, false}, + {Color(160, 160, 160), Color(50, 50, 50), _T("Courier New"), IDE_CHARSET_ANSI, 10, false, false}, + {Color(87, 166, 74), Color(50, 50, 50), _T("Courier New"), IDE_CHARSET_ANSI, 10, false, false}, + {Color(181, 230, 168), Color(50, 50, 50), _T("Courier New"), IDE_CHARSET_ANSI, 10, false, false}, + {Color(214, 157, 133), Color(50, 50, 50), _T("Courier New"), IDE_CHARSET_ANSI, 10, false, false}, }; constexpr auto STYLE_SCHEME_COUNT = 3; diff --git a/elenasrc3/ide/windows/main.cpp b/elenasrc3/ide/windows/main.cpp index 1ed506e1fa..a703797474 100644 --- a/elenasrc3/ide/windows/main.cpp +++ b/elenasrc3/ide/windows/main.cpp @@ -1,12 +1,11 @@ //--------------------------------------------------------------------------- // E L E N A P r o j e c t: ELENA IDE // WinAPI32 program entry -// (C)2021-2022, by Aleksey Rakov +// (C)2021-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #include "factory.h" #include "framework.h" -#include "ide.h" #include "ideview.h" #include "windows/wincommon.h" #include "windows/win32controller.h" diff --git a/elenasrc3/ide/windows/winide.cpp b/elenasrc3/ide/windows/winide.cpp index 53dffa998f..a046d0cb3c 100644 --- a/elenasrc3/ide/windows/winide.cpp +++ b/elenasrc3/ide/windows/winide.cpp @@ -497,9 +497,11 @@ void IDEWindow :: toggleWindow(int child_id) { if (child_id == _model->ideScheme.projectView) { if (!_children[_model->ideScheme.projectView]->visible()) { - openProject(); + _children[_model->ideScheme.projectView]->show(); } - else closeProject(); + else _children[_model->ideScheme.projectView]->hide(); + + onLayoutChange(); } } @@ -1176,8 +1178,10 @@ void IDEWindow :: onLayoutChange() onResize(); - if (!empty) - _children[_model->ideScheme.textFrameId]->refresh(); + //if (!empty) + // _children[_model->ideScheme.textFrameId]->refresh(); + + invalidate(); } void IDEWindow :: onStartup(ModelNMHDR* rec) diff --git a/elenasrc3/tools/asmc/armassembler.cpp b/elenasrc3/tools/asmc/armassembler.cpp index b7cd418744..5ea51e5b05 100644 --- a/elenasrc3/tools/asmc/armassembler.cpp +++ b/elenasrc3/tools/asmc/armassembler.cpp @@ -1262,6 +1262,19 @@ bool Arm64Assembler :: compileMOVZ(ScriptToken& tokenInfo, ARMOperand rt, ARMOpe return true; } +bool Arm64Assembler :: compileMOVN(ScriptToken& tokenInfo, ARMOperand rt, ARMOperand rn, MemoryWriter& writer) +{ + if (rt.isXR() && rn.type == ARMOperandType::Imm) { + writer.writeDWord(ARMHelper::makeImm16Opcode(1, 0, 0x25, 0, rn.imm, rt.type)); + + if (rn.reference) + writeReference(tokenInfo, rn.reference, writer, ASM_INVALID_SOURCE); + } + else return false; + + return true; +} + bool Arm64Assembler::compileMOVK(ScriptToken& tokenInfo, ARMOperand rt, ARMOperand rn, int lsl, MemoryWriter& writer) { if (rt.isXR() && rn.type == ARMOperandType::Imm) { @@ -2188,7 +2201,12 @@ void Arm64Assembler :: compileMOV(ScriptToken& tokenInfo, MemoryWriter& writer) valid = compileADDImm(tokenInfo, rd, rn, ARMOperand(ARMOperandType::Imm, 0), writer); } else if ((rd.isXR() && rn.type == ARMOperandType::Imm)) { - valid = compileMOVZ(tokenInfo, rd, rn, writer); + if (rn.imm < 0) { + // NOTE : + rn.imm = ~rn.imm; + valid = compileMOVN(tokenInfo, rd, rn, writer); + } + else valid = compileMOVZ(tokenInfo, rd, rn, writer); } if (!valid) @@ -2212,6 +2230,23 @@ void Arm64Assembler :: compileMVN(ScriptToken& tokenInfo, MemoryWriter& writer) throw SyntaxError(ASM_INVALID_COMMAND, tokenInfo.lineInfo); } +void Arm64Assembler :: compileMOVN(ScriptToken& tokenInfo, MemoryWriter& writer) +{ + ARMOperand rd = readOperand(tokenInfo, ASM_INVALID_SOURCE); + + checkComma(tokenInfo); + + ARMOperand rn = readOperand(tokenInfo, ASM_INVALID_TARGET); + + bool valid = false; + if (rd.isXR() && rn.type == ARMOperandType::Imm) { + valid = compileMOVN(tokenInfo, rd, rn, writer); + } + + if (!valid) + throw SyntaxError(ASM_INVALID_COMMAND, tokenInfo.lineInfo); +} + void Arm64Assembler :: compileMOVZ(ScriptToken& tokenInfo, MemoryWriter& writer) { ARMOperand rd = readOperand(tokenInfo, ASM_INVALID_SOURCE); @@ -2746,6 +2781,9 @@ bool Arm64Assembler::compileMOpCode(ScriptToken& tokenInfo, MemoryWriter& writer else if (tokenInfo.compare("movk")) { compileMOVK(tokenInfo, writer); } + else if (tokenInfo.compare("movn")) { + compileMOVN(tokenInfo, writer); + } else if (tokenInfo.compare("mul")) { compileMUL(tokenInfo, writer); } diff --git a/elenasrc3/tools/asmc/armassembler.h b/elenasrc3/tools/asmc/armassembler.h index ab91716539..5391ef075a 100644 --- a/elenasrc3/tools/asmc/armassembler.h +++ b/elenasrc3/tools/asmc/armassembler.h @@ -78,6 +78,7 @@ namespace elena_lang virtual bool compileLSRV(ARMOperand rd, ARMOperand rn, ARMOperand rm, MemoryWriter& writer); virtual bool compileMOVZ(ScriptToken& tokenInfo, ARMOperand rt, ARMOperand rn, MemoryWriter& writer); virtual bool compileMOVK(ScriptToken& tokenInfo, ARMOperand rt, ARMOperand rn, int lsl, MemoryWriter& writer); + virtual bool compileMOVN(ScriptToken& tokenInfo, ARMOperand rt, ARMOperand rn, MemoryWriter& writer); virtual bool compileMADD(ARMOperand rd, ARMOperand rn, ARMOperand rm, ARMOperand ra, MemoryWriter& writer); virtual bool compileORRShifted(ScriptToken& tokenInfo, ARMOperand rt, ARMOperand rx, ARMOperand ry, int shift, int ampount, MemoryWriter& writer); @@ -142,6 +143,7 @@ namespace elena_lang void compileLSR(ScriptToken& tokenInfo, MemoryWriter& writer); void compileMOV(ScriptToken& tokenInfo, MemoryWriter& writer); void compileMOVK(ScriptToken& tokenInfo, MemoryWriter& writer); + void compileMOVN(ScriptToken& tokenInfo, MemoryWriter& writer); void compileMOVZ(ScriptToken& tokenInfo, MemoryWriter& writer); void compileMUL(ScriptToken& tokenInfo, MemoryWriter& writer); void compileMVN(ScriptToken& tokenInfo, MemoryWriter& writer); diff --git a/elenasrc3/tools/asmc/asmconst.h b/elenasrc3/tools/asmc/asmconst.h index 12a1f72409..bec4cfe51b 100644 --- a/elenasrc3/tools/asmc/asmconst.h +++ b/elenasrc3/tools/asmc/asmconst.h @@ -12,7 +12,7 @@ namespace elena_lang { - #define ASM_REVISION_NUMBER 0x00CE + #define ASM_REVISION_NUMBER 0x00CF constexpr auto N_ARGUMENT1 = "__n_1"; constexpr auto N_ARGUMENT2 = "__n_2"; diff --git a/elenasrc3/tools/ecv/ecvconst.h b/elenasrc3/tools/ecv/ecvconst.h index 174e80c15d..88f7121644 100644 --- a/elenasrc3/tools/ecv/ecvconst.h +++ b/elenasrc3/tools/ecv/ecvconst.h @@ -11,7 +11,7 @@ namespace elena_lang { - #define ECV_REVISION_NUMBER 0x0051 + #define ECV_REVISION_NUMBER 0x0053 constexpr auto ECV_GREETING = "ELENA command line ByteCode Viewer %d.%d.%d (C)2021-24 by Aleksey Rakov\n"; diff --git a/elenasrc3/tools/ecv/ecviewer.cpp b/elenasrc3/tools/ecv/ecviewer.cpp index 8775bda903..5c297e8f17 100644 --- a/elenasrc3/tools/ecv/ecviewer.cpp +++ b/elenasrc3/tools/ecv/ecviewer.cpp @@ -145,8 +145,10 @@ void ByteCodeViewer :: printHelp() { _presenter->print("\n"); _presenter->print("list of commands\n"); - _presenter->print("? - list all classes\n"); + _presenter->print("? - list all classes / symbols\n"); + _presenter->print("?~ - list classes / symbols matching a filter\n"); _presenter->print(" - view class members\n"); + _presenter->print(".~ - view class members matching a filter\n"); _presenter->print(". - view a method byte codes\n"); _presenter->print(". - view a method specified by an index byte codes\n"); _presenter->print("# - view symbol byte codes\n"); @@ -674,6 +676,9 @@ void ByteCodeViewer :: printFlags(ref_t flags, int& row, int pageSize) if (test(flags, elAbstract)) { printLineAndCount("@flag ", "elAbstract", row, pageSize); } + if (test(flags, elAutoLoaded)) { + printLineAndCount("@flag ", "elAutoLoaded", row, pageSize); + } if (test(flags, elClassClass)) { printLineAndCount("@flag ", "elClassClass", row, pageSize); } @@ -1029,11 +1034,12 @@ struct BCVSessionInfo ByteCodeViewer* viewer; int row; int pageSize; + ustr_t filter; }; -void ByteCodeViewer :: listMembers() +void ByteCodeViewer :: listMembers(ustr_t filter) { - BCVSessionInfo info = { this, 1, _pageSize }; + BCVSessionInfo info = { this, 1, _pageSize, filter }; _module->forEachReference(&info, [](ModuleBase* module, ref_t reference, void* arg) { @@ -1042,6 +1048,9 @@ void ByteCodeViewer :: listMembers() BCVSessionInfo* info = (BCVSessionInfo*)arg; if (isWeakReference(referenceName)) { + if (!info->filter.empty() && referenceName.findStr(info->filter) == NOTFOUND_POS) + return; + if (module->mapSection(reference | mskVMTRef, true)) { info->viewer->printLineAndCount("class ", referenceName, info->row, info->pageSize); @@ -1077,8 +1086,8 @@ void ByteCodeViewer :: runSession() } if (buffer[0] == '?') { - if (buffer[1] == 0) { - listMembers(); + if (buffer[1] == 0 || buffer[1] == '~') { + listMembers(buffer[1] == 0 ? nullptr : buffer + 2); } else printHelp(); } diff --git a/elenasrc3/tools/ecv/ecviewer.h b/elenasrc3/tools/ecv/ecviewer.h index 07edff3246..871615677b 100644 --- a/elenasrc3/tools/ecv/ecviewer.h +++ b/elenasrc3/tools/ecv/ecviewer.h @@ -3,7 +3,7 @@ // // This is a main file containing ecode viewer code // -// (C)2021-2022, by Aleksey Rakov +// (C)2021-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #ifndef ECVIEWER_H @@ -63,7 +63,7 @@ namespace elena_lang void printLine(ustr_t arg1, ustr_t arg2); void printLineAndCount(ustr_t arg1, ustr_t arg2, int& row, int pageSize); - void listMembers(); + void listMembers(ustr_t filter); void addIArg(arg_t arg, IdentifierString& commandStr); diff --git a/elenasrc3/tools/ecv/windows/ecv.cpp b/elenasrc3/tools/ecv/windows/ecv.cpp index d64c1a48ab..dc5e7e8c2b 100644 --- a/elenasrc3/tools/ecv/windows/ecv.cpp +++ b/elenasrc3/tools/ecv/windows/ecv.cpp @@ -114,7 +114,7 @@ void getAppPath(PathString& appPath) int main() { - printf("ELENA command line ByteCode Viewer %d.%d.%d (C)2011-2023 by Aleksey Rakov\n", ENGINE_MAJOR_VERSION, ENGINE_MINOR_VERSION, ECV_REVISION_NUMBER); + printf(ECV_GREETING, ENGINE_MAJOR_VERSION, ENGINE_MINOR_VERSION, ECV_REVISION_NUMBER); // Reading command-line arguments... int argc; diff --git a/elenasrc3/tools/elt/eltconst.h b/elenasrc3/tools/elt/eltconst.h index 60f5e749b2..61b1645e5c 100644 --- a/elenasrc3/tools/elt/eltconst.h +++ b/elenasrc3/tools/elt/eltconst.h @@ -11,7 +11,7 @@ namespace elena_lang { - #define ELT_REVISION_NUMBER 0x000A + #define ELT_REVISION_NUMBER 0x000C constexpr auto ELT_GREETING = "ELENA command line VM terminal %d.%d.%d (C)2021-24 by Aleksey Rakov\n"; diff --git a/elenasrc3/tools/elt/vmsession.cpp b/elenasrc3/tools/elt/vmsession.cpp index cdfc3e23e8..bec329d270 100644 --- a/elenasrc3/tools/elt/vmsession.cpp +++ b/elenasrc3/tools/elt/vmsession.cpp @@ -136,7 +136,6 @@ bool VMSession :: connect(void* tape) { _env.gc_yg_size = 0x15000; _env.gc_mg_size = 0x54000; - _env.th_single_content = &_tcontext; int retVal = InitializeVMSTLA(&_env, tape, ELT_EXCEPTION_HANDLER); if (retVal != 0) { diff --git a/elenasrc3/tools/elt/vmsession.h b/elenasrc3/tools/elt/vmsession.h index 375a50331c..b9ed188c27 100644 --- a/elenasrc3/tools/elt/vmsession.h +++ b/elenasrc3/tools/elt/vmsession.h @@ -28,7 +28,6 @@ namespace elena_lang DynamicString _body; SystemEnv _env; - ThreadContent _tcontext; bool connect(void* tape); bool execute(void* tape); diff --git a/examples60/console/helloworld/helloworld.prj b/examples60/console/helloworld/helloworld.prj index 8f7f7f7d1a..4f61985af8 100644 --- a/examples60/console/helloworld/helloworld.prj +++ b/examples60/console/helloworld/helloworld.prj @@ -11,11 +11,20 @@ helloworld - helloworld.l + + + + + + + + + + \ No newline at end of file diff --git a/examples60/gui/c_a_g/c_area_gui.prj b/examples60/gui/c_a_g/c_area_gui.prj index 1852a801b9..e7853bf6bd 100644 --- a/examples60/gui/c_a_g/c_area_gui.prj +++ b/examples60/gui/c_a_g/c_area_gui.prj @@ -4,6 +4,11 @@ c_a_g.exe + + + c_a_g64.exe + + c_a_g diff --git a/examples60/net/chat/client/char_client.prj b/examples60/net/chat/client/char_client.prj new file mode 100644 index 0000000000..5c54fbd5b7 --- /dev/null +++ b/examples60/net/chat/client/char_client.prj @@ -0,0 +1,16 @@ + + + + chatclient.l + + + + + + chat_client + + + + ..\shared + + \ No newline at end of file diff --git a/examples60/net/chat/client/chatclient.l b/examples60/net/chat/client/chatclient.l new file mode 100644 index 0000000000..163d33e549 --- /dev/null +++ b/examples60/net/chat/client/chatclient.l @@ -0,0 +1,95 @@ +//import extensions; +import extensions'dynamic; +import net; +import system'net; + +import chat_shared; + +public sealed class ChatClient : BaseClient +{ + TcpClient _networkClient; + TcpClientWriter _networkWriter; + + string _address; + int _port; + string _userName; + + Func OnConnect : event; + Func OnError : event; + Func OnMessage: event; + + constructor new() + <= super new() + { + } + + constructor new(string ip, int port, string userName) + <= super new() + { + _networkClient := TcpClient.new(); + _networkWriter := TcpClientWriter.new(_networkClient); + + _address := ip; + _port := port; + _userName := userName + } + + sendNickname() + { + string json := new CommandDTO{ this Command := INTRODUCTION; this Value := _userName; }.toJson(); + int len := json.Length; + + _networkWriter.write(len); + _networkWriter.write(json); + } + + send(string text) + { + string json := new CommandDTO{ this Command := SEND; this Value := text; }.toJson(); + int len := json.Length; + + _networkWriter.write(len); + _networkWriter.write(json); + } + + start() + { + _networkClient.onConnect := (TcpClient client) + { + OnConnect?.(); + + sendNickname() + }; + + _networkClient.onError := (TcpClient client, SocketException e) + { + OnError?.(e.ErrorCode); + }; + + _networkClient.onReceived := (TcpClient client,byte[] buffer, int length) + { + self.write(buffer, length); + var command := self.readCommand(); + if (nil != command) + { + (command.Command) => + TRANSLATE + { + OnMessage?.(command.User, command.Value) + } + }; + }; + + _networkClient.connect(_address, _port); + + _networkClient.Blocking := false; + _networkClient.Nodelay := true; + + _networkClient.start() + } + + stop() + { + _networkClient.close() + } +} \ No newline at end of file diff --git a/examples60/net/chat/client_cui/client_console.prj b/examples60/net/chat/client_cui/client_console.prj new file mode 100644 index 0000000000..a92fb8ff19 --- /dev/null +++ b/examples60/net/chat/client_cui/client_console.prj @@ -0,0 +1,22 @@ + + + + common.l + main.l + + + + chat_client.exe + + client_console + + + + ..\client + ..\shared + + + extensions'programLoop + client_console'control + + \ No newline at end of file diff --git a/examples60/net/chat/client_cui/common.l b/examples60/net/chat/client_cui/common.l new file mode 100644 index 0000000000..7f466c740f --- /dev/null +++ b/examples60/net/chat/client_cui/common.l @@ -0,0 +1,3 @@ +public const string VERSION = "0.1"; + +const int DEFAULT_PORT = 6881; diff --git a/examples60/net/chat/client_cui/main.l b/examples60/net/chat/client_cui/main.l new file mode 100644 index 0000000000..2450a1aee0 --- /dev/null +++ b/examples60/net/chat/client_cui/main.l @@ -0,0 +1,51 @@ +import extensions; +import chat_client; + +class Client +{ + ChatClient _chatClient; + + start(string userName, string ip, int port) + { + _chatClient := ChatClient.new(ip, port, userName); + + _chatClient.OnError := (int err) { console.printLine("Exception #",err); }; + _chatClient.OnConnect := { console.writeLine("connected"); }; + _chatClient.OnMessage := (string user, string message){ console.printLine().printLine(user,":",message).print(">") }; + + _chatClient.start() + } +} + +class Controller +{ + Client _client; + string _ipAddress; + int _port; + + constructor() + { + _client := new Client(); + _ipAddress := "127.0.0.1"; + _port := DEFAULT_PORT; + } + + greeting() + { + console.printLine("ELENA Chat Client v.", VERSION); + + string userName := console.write("Enter nickname:").readLine(); + + try { + _client.start(userName, _ipAddress, _port); + } + catch(Exception ex) { + console.writeLine("Cannot esteblish connection!"); AbortException.raise() + }; + + ^ "Enter -q to exit the chat" + } + +} + +public static control = new Controller(); \ No newline at end of file diff --git a/examples60/net/chat/server/char_server.prj b/examples60/net/chat/server/char_server.prj new file mode 100644 index 0000000000..7997984860 --- /dev/null +++ b/examples60/net/chat/server/char_server.prj @@ -0,0 +1,17 @@ + + + + client.l + server.l + + + + + + chat_server + + + + ..\shared + + \ No newline at end of file diff --git a/examples60/net/chat/server/client.l b/examples60/net/chat/server/client.l new file mode 100644 index 0000000000..6aaa483072 --- /dev/null +++ b/examples60/net/chat/server/client.l @@ -0,0 +1,20 @@ +import chat_shared; +import net; + +public sealed class ChatMember : BaseClient +{ + ChatServer _server; + + constructor new(TcpRemoteClient owner, ChatServer server) + <= super new() + { +// theOwner := owner; +// + _server := server + } + + string Name : prop; + + ChatServer Server + = _server; +} \ No newline at end of file diff --git a/examples60/net/chat/server/server.l b/examples60/net/chat/server/server.l new file mode 100644 index 0000000000..81a28afb95 --- /dev/null +++ b/examples60/net/chat/server/server.l @@ -0,0 +1,119 @@ +import system'threading; +import system'net; +import extensions'dynamic; +import net; + +import chat_shared; + +public sealed ChatServer +{ + object _lock; + + TcpServer _networkServer; + TcpServerWriter _networkWriter; + + Thread _broadcastThread; + + Func OnConnect : event; + Func OnIntro : event; + Func OnMessage : event; + Func OnLeave : event; + Func OnError : event; + + + constructor new(int port) + { + _lock := new object(); + + _networkServer := TcpServer.new(port); + _networkServer.Blocking := false; + + _networkWriter := TcpServerWriter.new(_networkServer); + } + + private bool proceed() + { + foreach(TcpRemoteClient client; in _networkServer.Clients) { + lock(_lock) { + if (client.Parameter; is ChatMember member) + { + var command := member.readCommand(); + (command.Command) => + INTRODUCTION + { + member.Name := command.Value; + + OnIntro?.(member.Name); + } + SEND + { + OnMessage?.(member.Name, command.Value); + + member.Server.translate(new CommandDTO + { + this Command := TRANSLATE; + this Value := command.Value; + this User := member.Name; + }) + }; + } + } + }; + + ^ true + } + + translate(command) + { + string json := command.toJson(); + + _networkWriter.write(json.Length); + _networkWriter.write(json) + } + + start() + { + _networkServer.OnConnect := (TcpRemoteClient client) + { + lock (_lock) + { + OnConnect?.(); + + client.Parameter := ChatMember.new(client, self) + } + }; + + _networkServer.OnLeave := (TcpRemoteClient client) + { + lock (_lock) + { + OnLeave?.(client.Parameter.Name ?? "client"); + } + }; + + _networkServer.OnError := (TcpRemoteClient client, SocketException e) + { + lock (_lock) + { + OnError?.(e.ErrorCode) + } + }; + + _networkServer.OnReceived := (TcpRemoteClient client, byte[] data, int length) + { + lock (_lock) + { + (client.Parameter :as ChatMember).write(data, length) + } + }; + + _networkServer.start(); + + _broadcastThread := Thread.assign( + { + while (proceed()) {} + }); + + _broadcastThread.start() + } +} \ No newline at end of file diff --git a/examples60/net/chat/server_cui/common.l b/examples60/net/chat/server_cui/common.l new file mode 100644 index 0000000000..7f466c740f --- /dev/null +++ b/examples60/net/chat/server_cui/common.l @@ -0,0 +1,3 @@ +public const string VERSION = "0.1"; + +const int DEFAULT_PORT = 6881; diff --git a/examples60/net/chat/server_cui/main.l b/examples60/net/chat/server_cui/main.l new file mode 100644 index 0000000000..f3ff924164 --- /dev/null +++ b/examples60/net/chat/server_cui/main.l @@ -0,0 +1,20 @@ +import extensions; +import chat_server; + +public program() +{ + console.printLine("ELENA Chat Server v.", VERSION); + + auto server := ChatServer.new(DEFAULT_PORT); + + server.OnConnect := { console.writeLine("new client"); }; + server.OnLeave := (string name){ console.printLine(name, " just left"); }; + server.OnError := (int code){ console.printLine("exception #",code) }; + server.OnIntro := (string name){ console.printLine(name, " joined"); }; + server.OnMessage := (string name, string message){ console.printLine(name, ": ", message); }; + + server.start(); + + console.printLine("To quit, please press any key"); + console.readChar(); +} \ No newline at end of file diff --git a/examples60/net/chat/server_cui/server_console.prj b/examples60/net/chat/server_cui/server_console.prj new file mode 100644 index 0000000000..87edcaf2bc --- /dev/null +++ b/examples60/net/chat/server_cui/server_console.prj @@ -0,0 +1,18 @@ + + + + common.l + main.l + + + + chat_server.exe + + server_console + + + + ..\server + ..\shared + + \ No newline at end of file diff --git a/examples60/net/chat/shared/charcommon.l b/examples60/net/chat/shared/charcommon.l new file mode 100644 index 0000000000..2db09edd27 --- /dev/null +++ b/examples60/net/chat/shared/charcommon.l @@ -0,0 +1,59 @@ +import system'io; +import system'text; +import extensions'dynamic; + +public const int INTRODUCTION = 1; +public const int SEND = 2; +public const int TRANSLATE = 3; + +public const int DEFAULT_PORT = 6881; + +public class BaseClient +{ + MemoryBuffer _buffer; + + protected constructor new() + { + _buffer := MemoryBuffer.allocate() + } + + write(byte[] buffer, length) + { + _buffer.write(0, length, buffer) + } + + readCommand() + { + int len := _buffer.Length; + if (len > 0) + { + int package_len := _buffer.readInt32(0); + + if (package_len + 4 <= len) + { + string s := UTF8Encoding.toString(4, package_len, _buffer.Value); // !! should be optimized + +// int llen := s.Length; + + _buffer.delete(0, package_len + 4); + + ^ s.fromJson() +// +// var o := s.fromJson(); +// ^ o + } + }; + + ^ nil + } + +} + +public class CommandDTO +{ + int Command : dto_prop; + + string Value : dto_prop; + + string User : dto_prop; +} \ No newline at end of file diff --git a/examples60/net/chat/shared/chat_shared.prj b/examples60/net/chat/shared/chat_shared.prj new file mode 100644 index 0000000000..03877d937a --- /dev/null +++ b/examples60/net/chat/shared/chat_shared.prj @@ -0,0 +1,13 @@ + + + + charcommon.l + + + + + + chat_shared + + + \ No newline at end of file diff --git a/examples60/rosetta/simple_windowed_app/simple_windowed_app.prj b/examples60/rosetta/simple_windowed_app/simple_windowed_app.prj index cff3e62b45..94d4906a92 100644 --- a/examples60/rosetta/simple_windowed_app/simple_windowed_app.prj +++ b/examples60/rosetta/simple_windowed_app/simple_windowed_app.prj @@ -4,6 +4,11 @@ simple.exe + + + simple64.exe + + swapp diff --git a/src60/core/system.core_routines.esm b/src60/core/system.core_routines.esm index ff7650df5c..646c6fde0c 100644 --- a/src60/core/system.core_routines.esm +++ b/src60/core/system.core_routines.esm @@ -78,6 +78,13 @@ procedure __object_parentclass end +procedure __object_parent + + peek sp:0 + parent + +end + procedure __object_instanceOf peek sp:0 @@ -2680,15 +2687,15 @@ procedure thread_start(index) xhook dp:ex_struct, procedure:"system'core_routines'default_exception_handler" mov env - save dp:envptr + $save dp:envptr set dp:envptr store fp:arg1 call extern:StartThreadLA ( - *arg1, + *$arg1, procedure:"system'core_routines'critical_exception_handler", procedure:"system'core_routines'func_invoker", - *ptr) + *$ptr) unhook @@ -2706,12 +2713,12 @@ symbol sta_start xhook dp:ex_struct, procedure:"system'core_routines'default_exception_handler" mov env - save dp:envptr + $save dp:envptr set dp:envptr store fp:arg1 call extern:InitializeSTLA ( - *arg1, + *$arg1, symbol:"$auto'startUpSymbol", procedure:"system'core_routines'critical_exception_handler") @@ -2732,12 +2739,12 @@ symbol mta_start xhook dp:ex_struct, procedure:"system'core_routines'default_exception_handler" mov env - save dp:envptr + $save dp:envptr set dp:envptr store fp:arg1 call extern:InitializeMTLA ( - *arg1, + *$arg1, symbol:"$auto'startUpSymbol", procedure:"system'core_routines'critical_exception_handler") @@ -2754,12 +2761,12 @@ symbol vm_sta_start xhook dp:ex_struct, procedure:"system'core_routines'default_exception_handler" mov env - save dp:envptr + $save dp:envptr set dp:envptr store fp:arg1 call extern:InitializeVMSTLA ( - *arg1, + *$arg1, constdump:"$elena'meta$startUpTape", pstr:"system'core_routines'critical_exception_handler") diff --git a/src60/core/system.win_core_routines.esm b/src60/core/system.win_core_routines.esm index 35ceafe220..0bf9a5156a 100644 --- a/src60/core/system.win_core_routines.esm +++ b/src60/core/system.win_core_routines.esm @@ -31,11 +31,11 @@ procedure windProc (arg1,arg2,arg3,arg4) extopen (4),[arg],[hwnd,msg,wparam,lparam,ptr] xloadarg fp:arg3 - save dp:wparam + $save dp:wparam xloadarg fp:arg4 - save dp:lparam + $save dp:lparam xloadarg fp:arg1 - save dp:hwnd + $save dp:hwnd xloadarg fp:arg2 save dp:msg @@ -53,7 +53,7 @@ procedure windProc (arg1,arg2,arg3,arg4) jeq labClose labDefault: - call stdcall extern:USER32.DefWindowProcW(*hwnd,*msg,*wparam,*lparam) + call stdcall extern:USER32.DefWindowProcW(*$hwnd,*msg,*$wparam,*$lparam) jump labEnd2 labCreate: @@ -74,11 +74,11 @@ labCreate: jump labEnd labDestroy: - call stdcall extern:USER32.GetWindowLongW(*hwnd,GWL_USERDATA) + call stdcall extern:USER32.GetWindowLongW(*$hwnd,GWL_USERDATA) cmp n:0 jeq labDefault - save dp:ptr + $save dp:ptr set dp:hwnd store sp:1 @@ -92,11 +92,11 @@ labDestroy: jump labEnd labPaint: - call stdcall extern:USER32.GetWindowLongW(*hwnd,GWL_USERDATA) + call stdcall extern:USER32.GetWindowLongW(*$hwnd,GWL_USERDATA) cmp n:0 jeq labDefault - save dp:ptr + $save dp:ptr set dp:hwnd store sp:1 @@ -110,11 +110,11 @@ labPaint: jump labEnd labClose: - call stdcall extern:USER32.GetWindowLongW(*hwnd,GWL_USERDATA) + call stdcall extern:USER32.GetWindowLongW(*$hwnd,GWL_USERDATA) cmp n:0 jeq labDefault - save dp:ptr + $save dp:ptr set dp:hwnd store sp:1 @@ -128,11 +128,11 @@ labClose: jump labEnd labCommand: - call stdcall extern:USER32.GetWindowLongW(*hwnd,GWL_USERDATA) + call stdcall extern:USER32.GetWindowLongW(*$hwnd,GWL_USERDATA) cmp n:0 jeq labDefault - save dp:ptr + $save dp:ptr set dp:hwnd store sp:1 @@ -149,12 +149,12 @@ labCommand: jump labEnd labSize: - call stdcall extern:USER32.GetWindowLongW(*hwnd,GWL_USERDATA) + call stdcall extern:USER32.GetWindowLongW(*$hwnd,GWL_USERDATA) cmp n:0 jeq labDefault - save dp:ptr + $save dp:ptr set dp:lparam store sp:2 diff --git a/src60/extensions/dynamic/json.l b/src60/extensions/dynamic/json.l index b07b9c6846..d5fbf277b0 100644 --- a/src60/extensions/dynamic/json.l +++ b/src60/extensions/dynamic/json.l @@ -124,15 +124,16 @@ extension jsonSerializer : TextBuilder self.write("""").write(cast string(s)).write("""") } - serialize(object) + serializeDTO(object) { self.write("{"); - auto props := object.__getClass().__dto_properties(); -// if (nil == props) -// [ -// props := object __properties. -// ]. + var class := object.__getClass(); + auto props := class.__dto_properties() \ back(nil); + if (nil == props) + { + props := class.__getProperties(); + }; int len := props.Length; for (int i := 0; i < len; i++) @@ -158,6 +159,20 @@ extension jsonSerializer : TextBuilder }; self.write("}") + } + + serialize(object) + { + if (object.enumerator(); is Enumerator en) + { + ^ self.serialize(en) + }; + if (object.indexer(); is Indexer it) + { + ^ self.serialize(it) + }; + + ^ self.serializeDTO(object); } serialize(Array array) @@ -237,6 +252,9 @@ singleton helper { ^ token.toInt() } + else if (ch == $45 && token[1].isDigit()) { + ^ token.toInt() + } else { JsonException.raise() diff --git a/src60/extensions/extensions.prj b/src60/extensions/extensions.prj index aa729bba6e..d09bcce7a7 100644 --- a/src60/extensions/extensions.prj +++ b/src60/extensions/extensions.prj @@ -15,7 +15,7 @@ ELENA Extension Library - 6.0.1 + 6.0.3 Alex Rakov @@ -32,6 +32,7 @@ text\words.l math\functions.l math\matrix.l + io\bytearray.l routines\enumerating.l diff --git a/src60/extensions/extensions.project b/src60/extensions/extensions.project index e68d742dda..ab8476b00c 100644 --- a/src60/extensions/extensions.project +++ b/src60/extensions/extensions.project @@ -25,7 +25,7 @@ ELENA Extension Library - 6.0.1 + 6.0.2 Alex Rakov diff --git a/src60/extensions/io/bytearray.l b/src60/extensions/io/bytearray.l new file mode 100644 index 0000000000..eb265d954f --- /dev/null +++ b/src60/extensions/io/bytearray.l @@ -0,0 +1,126 @@ +import system'io; + +namespace io +{ + public sealed ByteArrayWriter : BinaryWriter + { + byte[] _buffer; + int _start; + int _end; + Reference _position; + + constructor new(byte[] buffer, int start, int length) + { + _buffer := buffer; + _start := start; + _end := start + length; + _position := start; + } + + constructor new(byte[] buffer) + <= new(buffer, 0, buffer.Length); + + object Source = _buffer; + + close() + { + _position := _end + } + + bool write(byte[] buffer, int length) + { + if (_end - _position < length) { + ^ false + }; + + Array.copyTo(_buffer, buffer, _position, length); + + _position += length; + + ^ true + } + } + + public sealed ByteArrayReader : BinaryReader + { + byte[] _buffer; + int _start; + int _end; + Reference _position; + + constructor new(byte[] buffer, int start, int length) + { + _buffer := buffer; + _start := start; + _end := start + length; + _position := start; + } + + constructor new(byte[] buffer) + <= new(buffer, 0, buffer.Length); + + object Source = _buffer; + + bool Available = _position < _end; + + close() + { + _position := _end + } + + read(byte[] array, ref int actualLength) + { + int remaining := _end - _position; + if (remaining < actualLength) { + actualLength := remaining + } + else remaining := actualLength; + + Array.copy(array, _buffer, _position, remaining); + } + } + + public struct BufferWriter : BinaryWriter + { + int _position; + byte _buffer[255]; + + object Source = _buffer; + + bool write(byte[] buffer, int length) + { + if (_position >= /*$len _buffer*/255) { + ^ false + }; + + Array.copyTo(_buffer, buffer, _position, length); + + _position += length; + + ^ true + } + + close() + { + _position := 255 + } + + private bool copyToStream(BinaryWriter externalWriter) + { + ^ externalWriter.write(_buffer, _position); + } + + internal static flush(BufferWriter bufferWriter, BinaryWriter externalWriter) + { + bufferWriter.copyToStream(externalWriter); + } + } + + public extension bufferWriterOp : BufferWriter + { + bool copyToStream(BinaryWriter externalWriter) + { + ^ BufferWriter.flush(self, externalWriter); + } + } +} \ No newline at end of file diff --git a/src60/extensions/text/words.l b/src60/extensions/text/words.l index b7b680a726..021a908c2d 100644 --- a/src60/extensions/text/words.l +++ b/src60/extensions/text/words.l @@ -87,7 +87,10 @@ namespace text { _newToken := false; _spaceMode := false; - _operatorMode := (letter || digit) ? false : true + if (ch == $45) { + _operatorMode := false; + } + else _operatorMode := (letter || digit) ? false : true } else if (letter || digit) { diff --git a/src60/net/win32_client.l b/src60/net/win32_client.l index ad091fcdad..32990972d6 100644 --- a/src60/net/win32_client.l +++ b/src60/net/win32_client.l @@ -1,5 +1,5 @@ import system'net; -import system'text; +import system'io; import system'threading; import extensions; @@ -13,9 +13,9 @@ public sealed class TcpClient int _maxLength; object _lock; - Func onConnect : event; - Func onReceived : event; - Func onError : event; + Func onConnect : event; + Func onReceived : event; + Func onError : event; constructor new() <= new(1024); @@ -31,23 +31,23 @@ public sealed class TcpClient connect(string address, int port) { //resolve server address and port - AddrInfo addrinfo := new AddrInfo(); + AddrInfo addrinfo := default; // set address info - addrinfo.Family := AF_UNSPEC; - addrinfo.SocketType := SOCK_STREAM; - addrinfo.Protocol := IPPROTO_TCP; + addrinfo.ai_family := AF_UNSPEC; + addrinfo.ai_socktype := SOCK_STREAM; + addrinfo.ai_protocol := IPPROTO_TCP; AddrInfoReader reader := new AddrInfoReader(address, port.toString(), addrinfo); while (reader.Available) { reader.read(addrinfo); - int ai_family := addrinfo.Family; - int ai_socktype := addrinfo.SocketType; - int ai_protocol := addrinfo.Protocol; - int ai_addrlen := addrinfo.AddressLen; - pointer ai_addrptr := addrinfo.Address; + int ai_family := addrinfo.ai_family; + int ai_socktype := addrinfo.ai_socktype; + int ai_protocol := addrinfo.ai_protocol; + int ai_addrlen := addrinfo.ai_addrlen; + pointer ai_addrptr := addrinfo.ai_addr; _socket := new Socket(ai_family, ai_socktype, ai_protocol); @@ -72,7 +72,7 @@ public sealed class TcpClient { int mode := val ? 0 : 1; - _socket.iocommand(FIONBIO, ref mode) + mode := _socket.iocommand(FIONBIO) } set Nodelay(bool val) @@ -93,7 +93,7 @@ public sealed class TcpClient lock (_lock) { if(nil != _socket) - { self.closeInternal() } + { closeInternal() } } } @@ -103,7 +103,7 @@ public sealed class TcpClient int err := e.ErrorCode; if(err == WSAECONNRESET) - { self.closeInternal() } + { closeInternal() } } private readServer() @@ -111,72 +111,36 @@ public sealed class TcpClient int received := 0; try { - _socket.read(_buffer, _maxLength, 0, ref received) + received := _socket.read(_buffer, _maxLength, 0) } catch(SocketException e) { - self.onError(e) + onError(e) }; if (received == 0) { - self.closeInternal() + closeInternal() } else { if (received > 0) - { onReceived(self, _buffer, received) } + { onReceived?.(self, _buffer, received) } } } - write(int index, byte[] buffer, int length) + write(byte[] buffer, int length) { - int sent := 0; - _socket.write(buffer, length, 0, ref sent) + int sent := _socket.write(buffer, length, 0) } - write(string s) - { - byte buffer[256]; - - int len := s.Length; - int buf_len := 256; - int index := 0; - while (len > 0) - { - if (len < 256) - { - buf_len := len - } - else - { - buf_len := 256 - }; - - UTF8Encoding.convert(index, buf_len, s, buffer); - - self.write(0, buffer, buf_len); - - len := len - buf_len; - index := index + buf_len - } - } - -// write(int n) -// { -// byte buffer[4]; -// byteArrayHelper.write(buffer, 0, n); -// -// self.write(0, buffer, 4) -// } - private proceed() { bool retVal := false; lock (_lock) { if (nil != _socket) - { self.readServer(); retVal := true } + { readServer(); retVal := true } }; ^ retVal @@ -186,9 +150,33 @@ public sealed class TcpClient { _thread := Thread.assign( { - while(self.proceed()){} + while(proceed()){} }); _thread.start() } } + +public class TcpClientWriter : BinaryWriter +{ + TcpClient _client; + + constructor new(TcpClient client) + { + _client := client; + } + + object Source = _client; + + bool write(byte[] buffer, int length) + { + _client.write(buffer, length); + + ^ true + } + + close() + { + _client.close() + } +} diff --git a/src60/net/win32_server.l b/src60/net/win32_server.l index 545062cf0b..55299d6ea0 100644 --- a/src60/net/win32_server.l +++ b/src60/net/win32_server.l @@ -2,6 +2,7 @@ import system'collections; import system'net; import system'threading; import system'text; +import system'io; public sealed class TcpRemoteClient { @@ -14,14 +15,14 @@ public sealed class TcpRemoteClient _socket := socket } - read(byte[] buffer, int maxLength, ref int recv) + int read(byte[] buffer, int maxLength) { - _socket.read(buffer, maxLength, 0, ref recv) + ^ _socket.read(buffer, maxLength, 0) } - write(byte[] buffer, int length) + int write(byte[] buffer, int length) { - _socket.write(buffer, length, 0, ref int sent); + ^ _socket.write(buffer, length, 0); } close() @@ -32,19 +33,19 @@ public sealed class TcpServer { Socket _listenSocket; List _clients; - Thread _listenThread; + Thread _listenThread; byte[] _buffer; int _maxLength; - Func OnConnect : event; - Func OnLeave : event; - Func OnReceived : event; + Func OnConnect : event; + Func OnLeave : event; + Func OnReceived : event; Func OnError : event; - constructor assign(int port) - <= assign(port, 1024); - - constructor assign(int port, int bufferSize) + constructor new(int port) + <= new(port, 1024); + + constructor new(int port, int bufferSize) { _maxLength := bufferSize; _buffer := new byte[](_maxLength); @@ -52,50 +53,42 @@ public sealed class TcpServer _clients := new List(); //resolve server address and port - AddrInfo addrinfo := new AddrInfo(); + AddrInfo addrinfo := default; // set address info - addrinfo.Family := AF_INET; - addrinfo.SocketType := SOCK_STREAM; - addrinfo.Protocol := IPPROTO_TCP; - addrinfo.Flags := AI_PASSIVE; + addrinfo.ai_family := AF_INET; + addrinfo.ai_socktype := SOCK_STREAM; + addrinfo.ai_protocol := IPPROTO_TCP; + addrinfo.ai_flags := AI_PASSIVE; // Create a SOCKET for connecting to server - AddrInfoReader reader := new AddrInfoReader(port.toPrintable(), addrinfo); - - reader.read(addrinfo); - int ai_family := addrinfo.Family; - int ai_socktype := addrinfo.SocketType; - int ai_protocol := addrinfo.Protocol; - int ai_addrlen := addrinfo.AddressLen; - pointer ai_addrptr := addrinfo.Address; + using(AddrInfoReader reader := new AddrInfoReader(port.toPrintable(), addrinfo)) { + reader.read(addrinfo); + int ai_family := addrinfo.ai_family; + int ai_socktype := addrinfo.ai_socktype; + int ai_protocol := addrinfo.ai_protocol; + int ai_addrlen := addrinfo.ai_addrlen; + pointer ai_addrptr := addrinfo.ai_addr; - _listenSocket := new Socket(ai_family, ai_socktype, ai_protocol); + _listenSocket := new Socket(ai_family, ai_socktype, ai_protocol); - _listenSocket.bind(ai_addrptr, ai_addrlen); + _listenSocket.bind(ai_addrptr, ai_addrlen); - reader.close(); + }; _listenSocket.listen(SOMAXCONN) } Enumerable Clients = new Enumerable { - /*embeddable dispatch => theClients.*/ - Enumerator enumerator() => _clients; }; set Blocking(bool val) { - int mode := 0; - - ifnot (val) - { - mode := 1 - }; + int mode := val ? 0 : 1; - _listenSocket.iocommand(FIONBIO, ref mode) + mode := _listenSocket.iocommand(FIONBIO) } private TcpRemoteClient newClient() @@ -105,12 +98,12 @@ public sealed class TcpServer if (nil != socket) { socket.option(IPPROTO_TCP, TCP_NODELAY, true); - + client := TcpRemoteClient.assign(socket); - + _clients.append(client) }; - + ^ client } @@ -119,19 +112,17 @@ public sealed class TcpServer _clients.remove(index); client.close(); - - if (nil != OnLeave) - { OnLeave(client) } + + OnLeave?.(client) } private handleError(SocketException e, TcpRemoteClient client, int n) { - if (nil != OnError) - { OnError(client, e) }; + OnError?.(client, e); int err := e.ErrorCode; if (err == WSAECONNRESET) - { self.closeClient(client, n) } + { closeClient(client, n) } } private readClients() @@ -143,23 +134,22 @@ public sealed class TcpServer int rcvd := 0; try { - client.read(_buffer, _maxLength, ref rcvd) + rcvd := client.read(_buffer, _maxLength) } catch(SocketException e) { - self.handleError(e, client, i) + handleError(e, client, i) }; if (rcvd == 0) { - self.closeClient(client, i) + closeClient(client, i) } else { if (rcvd > 0) { - if (nil != OnReceived) - { OnReceived(client,_buffer,rcvd) } + OnReceived?.(client,_buffer,rcvd) } } } @@ -167,14 +157,13 @@ public sealed class TcpServer private bool proceed() { - auto client := self.newClient(); + auto client := newClient(); if (nil != client) { - if(nil != OnConnect) - { OnConnect(client) } + OnConnect?.(client) }; - self.readClients(); + readClients(); ^ true } @@ -183,13 +172,13 @@ public sealed class TcpServer { _listenThread := Thread.assign( { - while (self.proceed()){} + while (proceed()){} }); _listenThread.start() } - TcpServer sendToAll(byte[] buffer, int length) + TcpServer broadcast(byte[] buffer, int length) { int counter := _clients.Length; @@ -201,44 +190,35 @@ public sealed class TcpServer } } - TcpServer sendToAll(string s) - { - byte buffer[256]; - int len := s.Length; - int buf_len := 256; - int index := 0; - while (len > 0) - { - if (len < 256) - { - buf_len := len - } - else - { - buf_len := 256 - }; - - UTF8Encoding.convert(index, buf_len, s, buffer); - - self.sendToAll(buffer, buf_len); - - len := len - buf_len; - index := index + buf_len - } - } - - TcpServer sendToAll(int n) - { - byte buffer[4]; - buffer.write(0, n); - - self.sendToAll(buffer, 4) - } - close() { _listenSocket.shutdown(SD_BOTH); _listenSocket.close() } -} \ No newline at end of file +} + +public class TcpServerWriter : BinaryWriter +{ + TcpServer _server; + + constructor new(TcpServer server) + { + _server := server; + } + + object Source = _server; + + bool write(byte[] buffer, int length) + { + _server.broadcast(buffer, length); + + ^ true + } + + close() + { + _server.close() + } +} + diff --git a/src60/system/app.l b/src60/system/app.l index 23520f5f24..f33306b354 100644 --- a/src60/system/app.l +++ b/src60/system/app.l @@ -1,3 +1,26 @@ +// --- startUp --- + +public sealed class StartUpEvents +{ + Func OnStop : event; + + Func1 OnError : event; + + internal constructor() {} + + internal stopping() + { + OnStop?.(); + } + + internal handlingError(e) + { + OnError?.(e) + } +} + +public static StartUpEvents startUpEvents = new StartUpEvents(); + entry() { try @@ -12,11 +35,17 @@ entry() function(Exception err) { + startUpEvents.handlingError(err); + console.writeLine(err); extern ExitLA(-1); } } + finally + { + startUpEvents.stopping() + } } gui_entry() @@ -33,11 +62,17 @@ gui_entry() function(Exception err) { + startUpEvents.handlingError(err); + forward program.error("ELENA", err); extern ExitLA(-1); } } + finally + { + startUpEvents.stopping() + } } private entrySymbol diff --git a/src60/system/extensions.l b/src60/system/extensions.l index eec168841d..439a6efae4 100644 --- a/src60/system/extensions.l +++ b/src60/system/extensions.l @@ -11,6 +11,9 @@ public extension objectOp __getParentClass() : external(system'core_routines'__object_parentclass), info("Returns the parent class"); + __getParent() : external(system'core_routines'__object_parent), + info("Returns the parent of the specified class"); + bool safeEqual(o) : info("Returns true if the parameter is equal to the object or false. It does not raise an exception if the objects are not compatible") = self.equal(o) \ back(false); @@ -37,7 +40,21 @@ public extension objectOp = action(self); bool instanceOf(type) : external(system'core_routines'__object_instanceOf), - info("Checks if the object is an instance of type"); + info("Checks if the object is an instance of type"); + + bool subsetOf(type) + { + var class := self.__getClass(); + while (class != nil) { + if (class == type) { + ^ true + }; + + class := class.__getParent() + }; + + ^ false + } } // --- valueOp --- diff --git a/src60/system/io/lnx_files.l b/src60/system/io/lnx_files.l index 16173e3d80..04dfaca013 100644 --- a/src60/system/io/lnx_files.l +++ b/src60/system/io/lnx_files.l @@ -96,63 +96,6 @@ namespace io } } - // --- StreamReader --- - public class TextStreamReader : TextReader - { - Stream _stream; - Encoder _encoder; - bool _open; - - constructor new(Stream stream, Encoder encoder) - { - _output := new TextBuilder(); - _newLineConstant := newLineConstant; - _newLineLength := _newLineConstant.Length; - - _stream := stream; - _encoder := encoder; - _open := true; - } - - constructor new(path) - <= new(FileStream.openForRead(path), UTF8Encoder); - - constructor new(string path, Encoder encoder) - <= new(FileStream.openForRead(path), encoder); - - bool Available = _open; - - Stream Stream = _stream; - - Encoder Encoder = _encoder; - - read(char[] output, ref int length) - { - int bufferLength := 64; - byte buffer[64]; - _stream.read(buffer, ref bufferLength); - if(bufferLength == 0) - { - _open := false; - length := 0; - } - else - { - int read := bufferLength; - - _encoder.convertFrom(buffer, 0, ref bufferLength, output, 0, ref length); - - if(read > bufferLength) - { _stream.reduceIndex(read - bufferLength) } - } - } - - close() - { - _stream.close() - } - } - singleton fileControl { TextReader newReader(path) = TextStreamReader.new(path); diff --git a/src60/system/io/streamreader.l b/src60/system/io/streamreader.l index 31a7901aea..85f43fd4e8 100644 --- a/src60/system/io/streamreader.l +++ b/src60/system/io/streamreader.l @@ -5,25 +5,14 @@ namespace io // --- BinaryReader --- public interface BinaryReader - { - Stream _stream; - int _length; - - read(byte[] array, ref int actualLength) - { - _stream.read(array, ref actualLength) - } + { + abstract read(byte[] array, ref int actualLength); - Stream Stream = _stream; + get abstract object Source(); - close() => _stream; + abstract close(); - get bool Available() - { - int position := _stream.Index; - - ^ position < _length - } + get abstract bool Available(); read(byte[] array, int length) { @@ -131,10 +120,28 @@ namespace io public sealed BinaryStreamReader : BinaryReader { + Stream _stream; + constructor(Stream stream) { _stream := stream } + + object Source = _stream; + + close() => _stream; + + get bool Available() + { + int position := _stream.Index; + + ^ position < _stream.Length + } + + read(byte[] array, ref int actualLength) + { + _stream.read(array, ref actualLength) + } } // --- TextReader --- @@ -146,7 +153,7 @@ namespace io abstract read(char[] array, ref int actualLength); - get abstract Stream Stream(); + get abstract object Source(); get abstract Encoder Encoder(); @@ -236,4 +243,61 @@ namespace io ^ line } } + + // --- StreamReader --- + public class TextStreamReader : TextReader + { + Stream _stream; + Encoder _encoder; + bool _open; + + constructor new(Stream stream, Encoder encoder) + { + _output := new TextBuilder(); + _newLineConstant := newLineConstant; + _newLineLength := _newLineConstant.Length; + + _stream := stream; + _encoder := encoder; + _open := true; + } + + constructor new(path) + <= new(FileStream.openForRead(path), UTF8Encoder); + + constructor new(string path, Encoder encoder) + <= new(FileStream.openForRead(path), encoder); + + bool Available = _open; + + object Source = _stream; + + Encoder Encoder = _encoder; + + read(char[] output, ref int length) + { + int bufferLength := 64; + byte buffer[64]; + _stream.read(buffer, ref bufferLength); + if(bufferLength == 0) + { + _open := false; + length := 0; + } + else + { + int read := bufferLength; + + _encoder.convertFrom(buffer, 0, ref bufferLength, output, 0, ref length); + + if(read > bufferLength) + { _stream.reduceIndex(read - bufferLength) } + } + } + + close() + { + _stream.close() + } + } } \ No newline at end of file diff --git a/src60/system/io/streamwriter.l b/src60/system/io/streamwriter.l index f4975efa90..d6dbea17c1 100644 --- a/src60/system/io/streamwriter.l +++ b/src60/system/io/streamwriter.l @@ -4,77 +4,117 @@ namespace io { public interface BinaryWriter { - Stream _stream; - - Stream Stream = _stream; + get abstract object Source(); - close() => _stream; + abstract close(); - write(byte[] array, int length) - { - _stream.write(array, length) - } + abstract bool write(byte[] array, int length); - write(byte int) + bool write(byte int) { byte buffer[4]; buffer[0] := int; - self.write(buffer, 1) + ^ self.write(buffer, 1) } - write(short n) + bool write(short n) { byte buffer[4]; buffer[0] := n.Low; buffer[1] := n.High; - self.write(buffer, 2) + ^ self.write(buffer, 2) } - write(char ch) + bool write(char ch) { int value := ch; - self.write(value); + ^ self.write(value); } - write(int int) + bool write(int int) { byte buffer[4]; PrimitiveLongOperations.saveToByteArray(int, buffer, 0); - self.write(buffer, 4) + ^ self.write(buffer, 4) } - write(long long) + bool write(long long) { byte buffer[8]; PrimitiveLongOperations.saveToByteArray(long, buffer, 0); - self.write(buffer, 8) + ^ self.write(buffer, 8) } - write(real r) + bool write(real r) { byte buffer[8]; PrimitiveRealOperations.saveToByteArray(r, buffer, 0); - self.write(buffer, 8) + ^ self.write(buffer, 8) + } + + bool write(string s) + { + byte buffer[256]; + int len := s.Length; + int buf_len := 256; + int s_len := 0; + int index := 0; + while (len > 0) + { + if (len < 256) + { + buf_len := len; + s_len := len; + } + else + { + buf_len := 256; + s_len := 256; + }; + + UTF8Encoder.toByteArray(s, index, ref s_len, buffer, 0, ref buf_len); + + write(buffer, buf_len); + + len := len - s_len; + index := index + s_len + }; + + ^ true } + } public sealed BinaryStreamWriter : BinaryWriter { + Stream _stream; + constructor(Stream stream) { _stream := stream } + + object Source = _stream; + + close() => _stream; + + bool write(byte[] array, int length) + { + _stream.write(array, length); + + ^ true + } } // --- TextWriter --- @@ -85,7 +125,7 @@ namespace io string _newLineConstant; int _newLineLength; - get abstract Stream Stream(); + get abstract object Source(); get abstract Encoder Encoder(); @@ -122,4 +162,64 @@ namespace io writeLine() <= write(_newLineConstant); } + + // --- StreamWriter --- + public class StreamWriter : TextWriter + { + Stream _stream; + Encoder _encoder; + + constructor new(Stream stream, Encoder encoder) + { + _buffer := new TextBuilder(); + _stream := stream; + _encoder := encoder; + + _newLineConstant := newLineConstant; + _newLineLength := _newLineConstant.Length; + } + + constructor new(path) + <= new(FileStream.openForReWrite(path), UTF8Encoder); + + constructor new(path, Encoder encoder) + <= new(FileStream.openForReWrite(path), encoder); + + object Source = _stream; + + Encoder Encoder = _encoder; + + write(char[] input, int length) + { + int total := length; + byte buffer[128]; + int blockLength := 0; + int bufferLength := 0; + int offset := 0; + + while (total > 0) + { + if(total < 32) + { + blockLength := total + } + else + { + blockLength := 32 + }; + + _encoder.convertTo(input, offset, ref blockLength, buffer, 0, ref bufferLength); + + _stream.write(buffer, bufferLength); + + total := total - blockLength; + offset := offset + blockLength + } + } + + close() + { + _stream.close() + } + } } \ No newline at end of file diff --git a/src60/system/io/win_files.l b/src60/system/io/win_files.l index 34d1562ef7..1452c082ce 100644 --- a/src60/system/io/win_files.l +++ b/src60/system/io/win_files.l @@ -131,63 +131,6 @@ namespace io } } - // --- StreamReader --- - public class TextStreamReader : TextReader - { - Stream _stream; - Encoder _encoder; - bool _open; - - constructor new(Stream stream, Encoder encoder) - { - _output := new TextBuilder(); - _newLineConstant := newLineConstant; - _newLineLength := _newLineConstant.Length; - - _stream := stream; - _encoder := encoder; - _open := true; - } - - constructor new(path) - <= new(FileStream.openForRead(path), UTF8Encoder); - - constructor new(string path, Encoder encoder) - <= new(FileStream.openForRead(path), encoder); - - bool Available = _open; - - Stream Stream = _stream; - - Encoder Encoder = _encoder; - - read(char[] output, ref int length) - { - int bufferLength := 64; - byte buffer[64]; - _stream.read(buffer, ref bufferLength); - if(bufferLength == 0) - { - _open := false; - length := 0; - } - else - { - int read := bufferLength; - - _encoder.convertFrom(buffer, 0, ref bufferLength, output, 0, ref length); - - if(read > bufferLength) - { _stream.reduceIndex(read - bufferLength) } - } - } - - close() - { - _stream.close() - } - } - singleton fileStreamHelper { Stream openForWrite(string path, bool appendMode) @@ -198,69 +141,6 @@ namespace io } } - // --- StreamWriter --- - public class StreamWriter : TextWriter - { - Stream _stream; - Encoder _encoder; - - constructor new(Stream stream, Encoder encoder) - { - _buffer := new TextBuilder(); - _stream := stream; - _encoder := encoder; - - _newLineConstant := newLineConstant; - _newLineLength := _newLineConstant.Length; - } - - constructor new(path) - <= new(FileStream.openForReWrite(path), UTF8Encoder); - - constructor new(path, Encoder encoder) - <= new(FileStream.openForReWrite(path), encoder); - - constructor new(string path, bool appendMode) - <= new(fileStreamHelper.openForWrite(path, appendMode), UTF8Encoder); - - Stream Stream = _stream; - - Encoder Encoder = _encoder; - - write(char[] input, int length) - { - int total := length; - byte buffer[128]; - int blockLength := 0; - int bufferLength := 0; - int offset := 0; - - while (total > 0) - { - if(total < 32) - { - blockLength := total - } - else - { - blockLength := 32 - }; - - _encoder.convertTo(input, offset, ref blockLength, buffer, 0, ref bufferLength); - - _stream.write(buffer, bufferLength); - - total := total - blockLength; - offset := offset + blockLength - } - } - - close() - { - _stream.close() - } - } - singleton fileControl { TextReader newReader(path) = TextStreamReader.new(path); diff --git a/src60/system/lnx_basic.l b/src60/system/lnx_basic.l deleted file mode 100644 index 772e09872f..0000000000 --- a/src60/system/lnx_basic.l +++ /dev/null @@ -1,110 +0,0 @@ - -// --- UnsafePointer --- - -public sealed const struct UnsafePointer -{ - embeddable __ptr _pointer; - - private clear() : external(system'core_routines'__clearPtr); - - constructor() - { - self.clear(); - } - - constructor(pointer ptr) - { - _pointer := ptr - } - - constructor(object obj) - { - self.assignPtr(obj); - } - - get constructor Default() - = new UnsafePointer(); - - private readIntPtr(ref int retVal) : external(system'core_routines'__readIntPtr); - - private assignPtr(wide str) : external(system'core_routines'__assignPtr); - - bool isUnassigned() - { - ^ _pointer == 0; - } - - // unsafe code - string cast() - { - int len := extern libc.strlen(self); - string s := String.allocate(len); - extern libc.strcpy(s, self); - - ^ s - } - - wide cast() - { - int len := extern libc.wcslen(self); - wide s := WideString.allocate(len); - extern libc.wcscpy(s, self); - - ^ s - } - - int cast() - { - self.readIntPtr(ref int retVal); - - ^ retVal - } - - copyTo(byte[] target, int len) : external(system'core_routines'__ptrCopyTo); -} - -// --- CallStack --- - -public sealed class CallStack - : info("A call stack") -{ - pointer[] stack; - - private load(pointer[] stack, int length, ref int retVal) : external(system'core_routines'__loadCallStack); - - constructor() - { - pointer stack[64]; - self.load(stack, 64, ref int length); - - 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") - { - byte buffer[512]; - int bufferLength := 0; - pointer address; - string callStackText := emptyString; - int length := stack.Length; - for (int i := 1; i < length; i += 1) { - address := stack[i]; - - bufferLength := extern LoadAddressInfoLM(address, buffer, 512); - if (bufferLength > 0) { - callStackText := callStackText + String.fromByteArray(0, bufferLength, buffer).add(newLineConstant) - }; - }; - - ^ callStackText - } -} diff --git a/src60/system/lnx_primitives.l b/src60/system/lnx_primitives.l new file mode 100644 index 0000000000..696f9d3b60 --- /dev/null +++ b/src60/system/lnx_primitives.l @@ -0,0 +1,21 @@ +// --- PrimitivePointerOperations --- +internal singleton PrimitivePointerOperations +{ + string readString(pointer ptr) + { + int len := extern libc.strlen(ptr); + string s := String.allocate(len); + extern libc.strcpy(s, ptr); + + ^ s + } + + wide readWideString(pointer ptr) + { + int len := extern libc.wcslen(ptr); + wide s := WideString.allocate(len); + extern libc.wcscpy(s, ptr); + + ^ s + } +} diff --git a/src60/system/net/win_common.l b/src60/system/net/win_common.l index 3ba7c621cd..b384e1f5b5 100644 --- a/src60/system/net/win_common.l +++ b/src60/system/net/win_common.l @@ -66,9 +66,6 @@ sealed packed WSADATA short iMaxUdpDg; int lpVendorInfo; - constructor init(int version, int highVersion) - <= init(cast byte(version), cast byte(highVersion)); - constructor init(byte version, byte highVersion) { short wVersionRequested := version * 10h + highVersion; diff --git a/src60/system/net/win_sockets.l b/src60/system/net/win_sockets.l index fa5e7b8777..fa2e51cf60 100644 --- a/src60/system/net/win_sockets.l +++ b/src60/system/net/win_sockets.l @@ -6,7 +6,7 @@ public sealed struct IN_ADDR { long addr; - set Value(LongNumber addr) + set Value(long addr) { this addr := addr } @@ -26,19 +26,8 @@ public sealed packed SOCKADDR_IN IN_ADDR sin_addr; byte sin_zero[4]; - set family(IntNumber n) - { - short n16 := n; - - family := n16 - } - - set port(IntNumber n) - { - short n16 := n; - - port := n16 - } + get constructor Default() + = default; set ip_address(string ip) { @@ -46,19 +35,6 @@ public sealed packed SOCKADDR_IN sin_addr.Value := addr } - - constructor() - { - family := 0; - port := 0; - - sin_zero[0]:=0; - sin_zero[1]:=0; - sin_zero[2]:=0; - sin_zero[3]:=0; - - sin_addr.clear() - } } const int SOCKADDR_IN_SIZE = 16; @@ -67,104 +43,14 @@ const int SOCKADDR_IN_SIZE = 16; public packed AddrInfo { - int ai_flags; - int ai_family; - int ai_socktype; - int ai_protocol; - int ai_addrlen; - pointer ai_canonname; - pointer ai_addr; - pointer ai_next; - - constructor() - { - self.clear() - } - - int Flags - { - get() - { - ^ ai_flags - } - - set(int val) - { - ai_flags := val - } - } - - int Family - { - get() - { - ^ ai_family - } - - set(int val) - { - ai_family := val - } - } - - int SocketType - { - get() - { - ^ ai_socktype - } - - set(int val) - { - ai_socktype := val - } - } - - int Protocol - { - get() - { - ^ ai_protocol - } - - set(int val) - { - ai_protocol := val - } - } - - int AddressLen - { - get() - { - ^ ai_addrlen - } - - set(int val) - { - ai_addrlen := val - } - } - - pointer Address - { - get() - { - ^ ai_addr - } - } - - clear() - { - ai_flags := 0; - ai_family := 0; - ai_socktype := 0; - ai_protocol := 0; - ai_addrlen := 0; - ai_canonname := default; - ai_addr := default; - ai_next := default; - } + int ai_flags : prop; + int ai_family : prop; + int ai_socktype : prop; + int ai_protocol : prop; + int ai_addrlen : prop; + pointer ai_canonname : prop; + pointer ai_addr : prop; + pointer ai_next : prop; } // --- AddrInfoReader --- @@ -173,15 +59,15 @@ public sealed struct AddrInfoReader { pointer paddrinfo; pointer prootinfo; - + constructor(string service, AddrInfo info) { pointer ptr := default; int retVal := extern WS2_32.getaddrinfo(0, service, info, ref ptr); - + ifnot(0 == retVal) { SocketException.new("getaddrinfo failed", retVal).raise() }; - + paddrinfo := ptr; prootinfo := ptr; } @@ -276,7 +162,7 @@ public sealed const struct Socket connect(string ip_address, int port) { - SOCKADDR_IN addr := new SOCKADDR_IN(); + SOCKADDR_IN addr := SOCKADDR_IN.Default; addr.port := port; addr.family := system'net'AF_INET; addr.ip_address := ip_address; @@ -291,23 +177,21 @@ public sealed const struct Socket int write(byte[] buffer) { int len := buffer.Length; - int sent := 0; - self.write(buffer, len, 0, ref sent); - - ^ sent + + ^ self.write(buffer, len, 0); } - write(byte[] buffer, int length, int flags, ref int sent) + int write(byte[] buffer, int length, int flags) { int retVal := extern WS2_32.send(_handle, buffer, length, flags); if (retVal == SOCKET_ERROR) { SocketException.new("Error at socket").raise() }; - sent := retVal + ^ retVal } - read(byte[] buffer, int maxLength, int flags, ref int recvd) + int read(byte[] buffer, int maxLength, int flags) { int retVal := extern WS2_32.recv(_handle,buffer,maxLength,flags); @@ -318,12 +202,12 @@ public sealed const struct Socket { SocketException.new("Error at socket").raise() } }; - recvd := retVal + ^ retVal } Socket accept() { - Socket socket := extern WS2_32.accept(_handle, 0, 0); + handle socket := extern WS2_32.accept(_handle, 0, 0); if (socket != INVALID_SOCKET) { @@ -343,17 +227,19 @@ public sealed const struct Socket { SocketException.new("Error at socket").raise() } } - iocommand(int command, ref int parameter) + int iocommand(int command) { - int retVal := extern WS2_32.ioctlsocket(_handle, command, ref parameter); + int retVal := extern WS2_32.ioctlsocket(_handle, command, ref int parameter); if (retVal == SOCKET_ERROR) - { SocketException.new("Error at socket").raise() } + { SocketException.new("Error at socket").raise() }; + + ^ parameter; } option(int level, int option, bool value) { - int n := value.iif(1,0); + int n := value ? 1 : 0; int retVal := extern WS2_32.setsockopt( _handle, level, option, ref n, 1); diff --git a/src60/system/operations/advanced/operations.l b/src60/system/operations/advanced/operations.l index 8ecd3d08ef..0623bdea11 100644 --- a/src60/system/operations/advanced/operations.l +++ b/src60/system/operations/advanced/operations.l @@ -29,3 +29,14 @@ public template if::is(truePart) : __included(statements) truePart; } } + +// --- expr :as T --- + +public template as(expr) : __included(statements) + = cast T(expr); + +// --- expr :of T --- + +public template is(expr) : __included(statements) + = expr.isInstanceOf(T); + diff --git a/src60/system/operations/operations.l b/src60/system/operations/operations.l index be042f5a7d..76bc452b7c 100644 --- a/src60/system/operations/operations.l +++ b/src60/system/operations/operations.l @@ -124,7 +124,7 @@ public template for::and public template try(try_block) : __included(statements) { - try_block \\ back(nil); + try_block \ back(nil); } // --- try:catch --- @@ -177,13 +177,13 @@ public template lock(block) : __included(statements) // --- operator templates --- -// .\ +// \. public template operator::alt(expr) : __included(statements) { expr \ back(identifier); } -// .! +// !. public template operator::else(expr) : __included(statements) { (nil == identifier) ? @@ -194,7 +194,7 @@ public template operator::else(expr) : __included(statements) expr } -// .? +// ?. public template operator::ifnil(expr) : __included(statements) { cast bool(nil != identifier) diff --git a/src60/system/pointers.l b/src60/system/pointers.l index 1182015045..b41b4fc746 100644 --- a/src60/system/pointers.l +++ b/src60/system/pointers.l @@ -31,3 +31,113 @@ public sealed const struct Handle ^ _value == 0; } } + +// --- UnsafePointer --- + +public sealed const struct UnsafePointer +{ + embeddable __ptr _pointer; + + private clear() : external(system'core_routines'__clearPtr); + + constructor() + { + self.clear(); + } + + constructor(pointer ptr) + { + _pointer := ptr + } + + constructor(object obj) + { + self.assignPtr(obj); + } + + get constructor Default() + = new UnsafePointer(); + + private readIntPtr(ref int retVal) : external(system'core_routines'__readIntPtr); + private readRealPtr(ref real retVal) : external(system'core_routines'__readRealPtr); + + private assignPtr(object obj) : external(system'core_routines'__assignPtr); + + bool isUnassigned() + { + ^ _pointer == 0; + } + + // unsafe code + string cast() + { + ^ PrimitivePointerOperations.readString(self); + } + + wide cast() + { + ^ PrimitivePointerOperations.readWideString(self); + } + + int cast() + { + self.readIntPtr(ref int retVal); + + ^ retVal + } + + real cast() + { + self.readRealPtr(ref real retVal); + + ^ retVal + } + + copyTo(byte[] target, int len) : external(system'core_routines'__ptrCopyTo); +} + +// --- CallStack --- + +public sealed class CallStack + : info("A call stack") +{ + pointer[] stack; + + private load(pointer[] stack, int length, ref int retVal) : external(system'core_routines'__loadCallStack); + + constructor() + { + pointer stack[64]; + self.load(stack, 64, ref int length); + + 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") + { + byte buffer[512]; + int bufferLength := 0; + pointer address; + string callStackText := emptyString; + int length := stack.Length; + for (int i := 1; i < length; i += 1) { + address := stack[i]; + + bufferLength := extern LoadAddressInfoLM(address, buffer, 512); + if (bufferLength > 0) { + callStackText := callStackText + String.fromByteArray(0, bufferLength, buffer).add(newLineConstant) + } + }; + + ^ callStackText + } +} diff --git a/src60/system/system.prj b/src60/system/system.prj index 94dbbd0f40..027e66fb98 100644 --- a/src60/system/system.prj +++ b/src60/system/system.prj @@ -16,7 +16,7 @@ ELENA Standard Library - 6.0.5 + 6.0.7 Aleksey Rakov @@ -47,7 +47,7 @@ closures.l convertors.l pointers.l - win_basic.l + win_primitives.l dynamic.l exceptions.l events.l diff --git a/src60/system/system.project b/src60/system/system.project index a6059ddbaf..01a4bd399b 100644 --- a/src60/system/system.project +++ b/src60/system/system.project @@ -50,7 +50,7 @@ ELENA Standard Library - 6.0.5 + 6.0.6 Aleksey Rakov @@ -81,7 +81,7 @@ closures.l convertors.l pointers.l - lnx_basic.l + lnx_primitives.l dynamic.l exceptions.l events.l diff --git a/src60/system/win_basic.l b/src60/system/win_basic.l deleted file mode 100644 index 67754da8a3..0000000000 --- a/src60/system/win_basic.l +++ /dev/null @@ -1,220 +0,0 @@ - -// --- UnsafePointer --- - -public sealed const struct UnsafePointer -{ - embeddable __ptr _pointer; - - private clear() : external(system'core_routines'__clearPtr); - - constructor() - { - self.clear(); - } - - constructor(pointer ptr) - { - _pointer := ptr - } - - constructor(object obj) - { - self.assignPtr(obj); - } - - get constructor Default() - = new UnsafePointer(); - - private readIntPtr(ref int retVal) : external(system'core_routines'__readIntPtr); - private readRealPtr(ref real retVal) : external(system'core_routines'__readRealPtr); - - private assignPtr(object obj) : external(system'core_routines'__assignPtr); - - bool isUnassigned() - { - ^ _pointer == 0; - } - - // unsafe code - string cast() - { - int len := extern KERNEL32.lstrlenA(self); - string s := String.allocate(len); - extern KERNEL32.lstrcpyA(s, self); - - ^ s - } - - wide cast() - { - int len := extern KERNEL32.lstrlenW(self); - wide s := WideString.allocate(len); - extern KERNEL32.lstrcpyW(s, self); - - ^ s - } - - int cast() - { - self.readIntPtr(ref int retVal); - - ^ retVal - } - - real cast() - { - self.readRealPtr(ref real retVal); - - ^ retVal - } - - copyTo(byte[] target, int len) : external(system'core_routines'__ptrCopyTo); -} - -// --- CallStack --- - -public sealed class CallStack - : info("A call stack") -{ - pointer[] stack; - - private load(pointer[] stack, int length, ref int retVal) : external(system'core_routines'__loadCallStack); - - constructor() - { - pointer stack[64]; - self.load(stack, 64, ref int length); - - 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") - { - byte buffer[512]; - int bufferLength := 0; - pointer address; - string callStackText := emptyString; - int length := stack.Length; - for (int i := 1; i < length; i += 1) { - address := stack[i]; - - bufferLength := extern LoadAddressInfoLM(address, buffer, 512); - if (bufferLength > 0) { - callStackText := callStackText + String.fromByteArray(0, bufferLength, buffer).add(newLineConstant) - } - }; - - ^ callStackText - } -} - -// --- COORD --- - -public sealed struct COORD -{ - short _x; - short _y; - - constructor() - { - _x := 0; - _y := 0; - } - - write(short x, short y) - { - _x := x; - _y := y - } - - write(COORD r) - { - short tmp := r.X; - _x := tmp; - - tmp := r.Y; - _y := tmp - } - - short X - { - get() - { - ^ _x - } - } - - short Y - { - get() - { - ^ _y - } - } -} - -// --- SMALL_RECT -- - -public sealed struct SMALL_RECT -{ - short _left; - short _top; - short _right; - short _bottom; - - short Left - { - get() - { - ^ _left - } - } - - short Top - { - get() - { - ^ _top - } - } - - short Right - { - get() - { - ^ _right - } - } - - short Bottom - { - get() - { - ^ _bottom - } - } - - write(SMALL_RECT r) - { - short tmp := r.Left; - _left := tmp; - - tmp := r.Top; - _top := tmp; - - tmp := r.Right; - _right := tmp; - - tmp := r.Bottom; - _bottom := tmp; - } -} diff --git a/src60/system/win_primitives.l b/src60/system/win_primitives.l new file mode 100644 index 0000000000..7eb6902f1f --- /dev/null +++ b/src60/system/win_primitives.l @@ -0,0 +1,123 @@ +// --- PrimitivePointerOperations --- +internal singleton PrimitivePointerOperations +{ + string readString(pointer ptr) + { + int len := extern KERNEL32.lstrlenA(ptr); + string s := String.allocate(len); + extern KERNEL32.lstrcpyA(s, ptr); + + ^ s + } + + wide readWideString(pointer ptr) + { + int len := extern KERNEL32.lstrlenW(ptr); + wide s := WideString.allocate(len); + extern KERNEL32.lstrcpyW(s, ptr); + + ^ s + } +} + +// --- COORD --- + +public sealed struct COORD +{ + short _x; + short _y; + + constructor() + { + _x := 0; + _y := 0; + } + + write(short x, short y) + { + _x := x; + _y := y + } + + write(COORD r) + { + short tmp := r.X; + _x := tmp; + + tmp := r.Y; + _y := tmp + } + + short X + { + get() + { + ^ _x + } + } + + short Y + { + get() + { + ^ _y + } + } +} + +// --- SMALL_RECT -- + +public sealed struct SMALL_RECT +{ + short _left; + short _top; + short _right; + short _bottom; + + short Left + { + get() + { + ^ _left + } + } + + short Top + { + get() + { + ^ _top + } + } + + short Right + { + get() + { + ^ _right + } + } + + short Bottom + { + get() + { + ^ _bottom + } + } + + write(SMALL_RECT r) + { + short tmp := r.Left; + _left := tmp; + + tmp := r.Top; + _top := tmp; + + tmp := r.Right; + _right := tmp; + + tmp := r.Bottom; + _bottom := tmp; + } +} diff --git a/tests60/sandbox/sandbox.l b/tests60/sandbox/sandbox.l index 62a807e3a0..44c46c51aa 100644 --- a/tests60/sandbox/sandbox.l +++ b/tests60/sandbox/sandbox.l @@ -1,6 +1,8 @@ +// --- test --- + import extensions; -public program() +public program() : info("sdfsdgds") { - console.printLine("Test"); -} + var s := "abcd"; +} \ No newline at end of file diff --git a/tests60/system_tests/basic.l b/tests60/system_tests/basic.l index 9c37686891..8b5df0fb40 100644 --- a/tests60/system_tests/basic.l +++ b/tests60/system_tests/basic.l @@ -1,6 +1,7 @@ import extensions; import system'routines; import system'dynamic'expressions; +import system'text; import ltests; // --- ControlTest --- @@ -1839,4 +1840,57 @@ public ByteArrayOpTests() : testCase() Assert.ifEqual(r[1], 2); console.write("."); -} \ No newline at end of file +} + +public ArrayAssignOperation() : testCase() +{ + int temp[4]; + + temp[0] := 1; + temp[1] := 2; + temp[2] := 3; + temp[3] := 4; + + temp[0] += 2; + temp[1] -= 1; + temp[2] *= 2; + temp[3] /= 2; + + Assert.ifEqual(temp[0], 3); + Assert.ifEqual(temp[1], 1); + Assert.ifEqual(temp[2], 6); + Assert.ifEqual(temp[3], 2); + + console.write("."); +} + +VT_B; + +VT_C +{ + VT_B cast() + = new VT_B(); +} + +singleton VT_E +{ + load(params VT_B[] o) + { + ^ new TextBuilder().print(o.asEnumerable()).Value; + } + + loadAndTypecast(params object[] args) + { + ^ self.load(cast VT_B(params args)); + } +} + +public variadicTypecastingTests() : testCase() +{ + var b := new VT_B(); + var c := new VT_C(); + + Assert.ifEqual(VT_E.loadAndTypecast(b,c), "system_tests'$private'VT_B,system_tests'$private'VT_B"); + + console.write("."); +}