From 003487c18c4b98e8d43d10d67f6171379e88bacf Mon Sep 17 00:00:00 2001 From: Aleksey Rakov Date: Tue, 9 Jul 2024 15:16:20 +0200 Subject: [PATCH] Iteration27 (#669) * [ADDED] new template extensions'dynamic'Serializer * [FIXED] String#class.copy[4] * fixing string.copy constructor * [FIXED]function attribute is allowed for the function declaration * [FIXED] template generation routines * [FIXED] include opcode must restore previous frame value * [FIXED] JIT code resolving * fixing elenavm code * [ADDED] key-value expression * #265 : working on enumeration template * [FIXED] private constructor must be called directly * adding a new unit test * [FIXED] accessing static fields inside a structure * [ADDED] #265 : Support enumeration list * [ADDED] new operator $size * fixing x86-64 routines * [FIXED]ppc64le : decoratorTest() * [ADDED] #658 : new project LDBG - ELENA Debugger Adapter --- .github/workflows/msbuild.yml | 2 +- CHANGELOG.md | 3 + VERSION | 2 +- asm/ppc64le/core60.asm | 2 +- build/aarch64/build_package_arm64.script | 2 +- build/aarch64/control | 2 +- build/amd64/build_package_amd64.script | 2 +- build/amd64/control | 2 +- build/i386/build_package_i386.script | 2 +- build/i386/control | 2 +- build/ppc64le/build_package_ppc64le.script | 2 +- build/ppc64le/control | 2 +- dat/sg/syntax60.txt | 23 +- doc/api/forms.html | 28 +- doc/api/index.html | 10 +- doc/api/net.html | 14 +- doc/api/system-runtime.html | 18 + doc/todo.txt | 32 +- elenasrc3/dpa/dpa_common.h | 17 + elenasrc3/dpa/dpa_session.cpp | 21 ++ elenasrc3/dpa/dpa_session.h | 23 ++ elenasrc3/elc/clicommon.h | 5 +- elenasrc3/elc/cliconst.h | 2 +- elenasrc3/elc/compiler.cpp | 354 +++++++++++++++++--- elenasrc3/elc/compiler.h | 29 ++ elenasrc3/elc/compilerlogic.cpp | 8 +- elenasrc3/elc/compiling.cpp | 14 + elenasrc3/elc/compiling.h | 3 + elenasrc3/elc/derivation.cpp | 94 +++++- elenasrc3/elc/derivation.h | 33 +- elenasrc3/elena-tests/bt_optimization.cpp | 118 +------ elenasrc3/elena-tests/bt_optimization.h | 44 +-- elenasrc3/elena-tests/compiler_tests.cpp | 5 - elenasrc3/elena-tests/constructor_tests.cpp | 75 +++++ elenasrc3/elena-tests/constructor_tests.h | 30 ++ elenasrc3/elena-tests/elena-tests.vcxproj | 2 + elenasrc3/elena-tests/scenario_consts.h | 4 + elenasrc3/elena-tests/tests_common.cpp | 95 ++++++ elenasrc3/elena-tests/tests_common.h | 33 ++ elenasrc3/elenart/linux/main.cpp | 4 + elenasrc3/elenart/vs/elenart.vcxproj | 2 +- elenasrc3/elenasrc3.sln | 10 + elenasrc3/engine/buildtree.h | 1 + elenasrc3/engine/elenaconst.h | 3 +- elenasrc3/engine/gcroutines.cpp | 3 - elenasrc3/engine/langcommon.h | 2 + elenasrc3/engine/syntaxtree.cpp | 1 + elenasrc3/engine/syntaxtree.h | 8 + elenasrc3/engine/windows/winroutines.cpp | 3 + elenasrc3/ldbg/ldbg_const.h | 1 + elenasrc3/ldbg/ldbg_session.cpp | 29 ++ elenasrc3/ldbg/ldbg_session.h | 28 ++ elenasrc3/ldbg/vs/Resource.rc | 60 ++++ elenasrc3/ldbg/vs/ldbg.vcxproj | 188 +++++++++++ elenasrc3/ldbg/vs/resource.h | 29 ++ elenasrc3/ldbg/windows/ldbg.cpp | 21 ++ src60/core/system.core_routines.esm | 10 + src60/forms/win32_controls.l | 18 +- src60/forms/win_forms.l | 4 +- src60/system/app.l | 2 +- src60/system/attributes/attributes.l | 1 + src60/system/calendar/lnx64_datetime.l | 4 +- src60/system/inline_templates.l | 80 +++++ src60/system/runtime/vectortable.l | 104 +++++- src60/system/system.prj | 2 +- src60/system/winforms/win_dialogs.l | 6 +- src60/system/winforms/win_windows.l | 3 +- tests60/sandbox/sandbox.l | 69 ++-- tests60/system_tests/basic.l | 21 +- 69 files changed, 1551 insertions(+), 325 deletions(-) create mode 100644 elenasrc3/dpa/dpa_common.h create mode 100644 elenasrc3/dpa/dpa_session.cpp create mode 100644 elenasrc3/dpa/dpa_session.h create mode 100644 elenasrc3/elena-tests/constructor_tests.cpp create mode 100644 elenasrc3/elena-tests/constructor_tests.h create mode 100644 elenasrc3/ldbg/ldbg_const.h create mode 100644 elenasrc3/ldbg/ldbg_session.cpp create mode 100644 elenasrc3/ldbg/ldbg_session.h create mode 100644 elenasrc3/ldbg/vs/Resource.rc create mode 100644 elenasrc3/ldbg/vs/ldbg.vcxproj create mode 100644 elenasrc3/ldbg/vs/resource.h create mode 100644 elenasrc3/ldbg/windows/ldbg.cpp diff --git a/.github/workflows/msbuild.yml b/.github/workflows/msbuild.yml index 25460c18d..52a1e7ddf 100644 --- a/.github/workflows/msbuild.yml +++ b/.github/workflows/msbuild.yml @@ -20,7 +20,7 @@ env: # https://docs.github.com/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix BUILD_CONFIGURATION: Release - BUILD_TAG: 6.2.0 + BUILD_TAG: 6.2.1 permissions: contents: read diff --git a/CHANGELOG.md b/CHANGELOG.md index 968a19cf8..c6fe045ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,7 @@ +## ELENA 6.3.0 + ## ELENA 6.2.0 +*25.06.2024* - ELC - [ADDED] optimized ternary expressions diff --git a/VERSION b/VERSION index 4ac4fded4..0df17dd0f 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -6.2.0 \ No newline at end of file +6.2.1 \ No newline at end of file diff --git a/asm/ppc64le/core60.asm b/asm/ppc64le/core60.asm index ae9eebdd0..4c587b001 100644 --- a/asm/ppc64le/core60.asm +++ b/asm/ppc64le/core60.asm @@ -1672,7 +1672,7 @@ end // ; savesi inline %0A2h - stw r14, __arg16_1(r1) + std r14, __arg16_1(r1) end diff --git a/build/aarch64/build_package_arm64.script b/build/aarch64/build_package_arm64.script index 87a7429ae..e442776d0 100755 --- a/build/aarch64/build_package_arm64.script +++ b/build/aarch64/build_package_arm64.script @@ -1,5 +1,5 @@ #!/bin/bash -RELEASE=elena-6.2.0.aarch64-linux +RELEASE=elena-6.2.1.aarch64-linux mkdir -p /usr/share/elena mkdir -p /etc/elena/ diff --git a/build/aarch64/control b/build/aarch64/control index f5735f3a5..e7141fa34 100644 --- a/build/aarch64/control +++ b/build/aarch64/control @@ -1,5 +1,5 @@ Package: elena-lang -Version: 6.2.0 +Version: 6.2.1 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 b7d50da82..0c110928c 100755 --- a/build/amd64/build_package_amd64.script +++ b/build/amd64/build_package_amd64.script @@ -1,5 +1,5 @@ #!/bin/bash -RELEASE=elena-6.2.0.amd64-linux +RELEASE=elena-6.2.1.amd64-linux mkdir -p /usr/share/elena mkdir -p /etc/elena/ diff --git a/build/amd64/control b/build/amd64/control index c218c6161..f7f7070a7 100644 --- a/build/amd64/control +++ b/build/amd64/control @@ -1,5 +1,5 @@ Package: elena-lang -Version: 6.2.0 +Version: 6.2.1 Architecture: amd64 Maintainer: Alex Rakov Depends: libc6 (>= 2.1) diff --git a/build/i386/build_package_i386.script b/build/i386/build_package_i386.script index 12ca1742f..ead38d66d 100755 --- a/build/i386/build_package_i386.script +++ b/build/i386/build_package_i386.script @@ -1,5 +1,5 @@ #!/bin/bash -RELEASE=elena-6.2.0.i386-linux +RELEASE=elena-6.2.1.i386-linux mkdir -p /usr/share/elena mkdir -p /etc/elena/ diff --git a/build/i386/control b/build/i386/control index 39d52c0d5..dc3b4fb3e 100644 --- a/build/i386/control +++ b/build/i386/control @@ -1,5 +1,5 @@ Package: elena-lang -Version: 6.2.0 +Version: 6.2.1 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 e2683637f..5a33e3521 100755 --- a/build/ppc64le/build_package_ppc64le.script +++ b/build/ppc64le/build_package_ppc64le.script @@ -1,5 +1,5 @@ #!/bin/bash -RELEASE=elena-6.2.0.ppc64le-linux +RELEASE=elena-6.2.1.ppc64le-linux mkdir -p /usr/share/elena mkdir -p /etc/elena/ diff --git a/build/ppc64le/control b/build/ppc64le/control index 2900df197..d5739f4d9 100644 --- a/build/ppc64le/control +++ b/build/ppc64le/control @@ -1,5 +1,5 @@ Package: elena-lang -Version: 6.2.0 +Version: 6.2.1 Architecture: ppc64le Maintainer: Alex Rakov Depends: libc6 (>= 2.1) diff --git a/dat/sg/syntax60.txt b/dat/sg/syntax60.txt index 8e120acf6..bf1d9a300 100644 --- a/dat/sg/syntax60.txt +++ b/dat/sg/syntax60.txt @@ -78,9 +78,11 @@ __define LAZY_OPERATION 6245; __define TUPLE_ASSIGNING 6246; __define CONTINUE_OPERATION 6247; __define YIELD_OPERATION 6248; +__define EXPRVAL_OPERATION 6249; __define REFER_OPERATION 6251; __define INC_OPERATION 6252; __define DEC_OPERATION 6253; +__define SIZE_OPERATION 6254; __define TEMPLATE_EXPR_BLOCK 6304; __define MESSAGE_OPERATION 6337; @@ -99,6 +101,7 @@ __define L3_SINGLE_EXPRESSION 6298; __define NESTED_ROOT_EXPRESSION 6299; __define OPERATION_TEMPLATE 6300; __define LT_EXPRESSION 6301; +__define KEY_VALUE_EXPRESSION 6305; __define SWITCH_OPTION 6353; __define SWITCH_LAST_OPTION 6354; __define SWITCH_CODE 6355; @@ -106,6 +109,8 @@ __define COLLECTION_EXPRESSION 6356; __define TUPLE_COLLECTION 6357; __define POSTFIX 4201; __define TEMPLATE_POSTFIX 4202; + +__define ENUM_POSTFIX 4207; __define TEMPLATE_ARG 4208; __define DIMENSION 5233; __define RESEND 7366; @@ -440,6 +445,7 @@ EXPRESSION ::= | "{" ^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 + | "=" ^OBJECT SINGLE_EXPRESSION ^KEY_VALUE_EXPRESSION | SBRACKET ^OBJECT INDEXER_R L0_F | ASSIGN ^OBJECT ASSIGN_R | L1a_OOP @@ -486,6 +492,7 @@ EXPRESSION ::= | identifier ^OBJECT { ASSIGN ASSIGN_R }? } | ":" ^OBJECT ^EXPRESSION identifier TEMPLATE_ARG ^ TEMPLATE_EXPR_BLOCK + | "=" ^OBJECT SINGLE_EXPRESSION ^KEY_VALUE_EXPRESSION | SBRACKET ^OBJECT INDEXER_R L0_F | L1a_OOP | ASSIGN ^OBJECT ASSIGN_R @@ -530,8 +537,10 @@ EXPRESSION ::= | "~" SINGLE_EXPRESSION ^BNOT_OPERATION L2_OP* L3_OP* L4_OP* L5_OP* L6_OP? L7_OP* L8_OP? L9_OP? | "-" SINGLE_EXPRESSION ^NEGATE_OPERATION L2_OP* L3_OP* L4_OP* L5_OP* L6_OP? L7_OP* L8_OP? L9_OP? | "$name" SINGLE_EXPRESSION ^NAME_OPERATION + | "$value" SINGLE_EXPRESSION ^EXPRVAL_OPERATION | "$reference" SINGLE_EXPRESSION ^REFER_OPERATION | "$len" SINGLE_EXPRESSION ^LEN_OPERATION + | "$size" SINGLE_EXPRESSION ^SIZE_OPERATION | "{" BLOCK ^CLOSURE L2_OP* L3_OP* L4_OP* L5_OP* L6_OP? L7_OP* L8_OP? L9_OP? | BRACKET SUB_EXPRESSION { L2_OP+ L3_OP* L4_OP* L5_OP* L6_OP? L7_OP* L8_OP? L9_OP? @@ -658,6 +667,7 @@ SUB_EXPRESSION ::= | "$name" SINGLE_EXPRESSION ^NAME_OPERATION ")" | "$reference" SINGLE_EXPRESSION ^REFER_OPERATION ")" | "$len" SINGLE_EXPRESSION ^LEN_OPERATION ")" + | "$size" SINGLE_EXPRESSION ^SIZE_OPERATION ")" | "{" BLOCK ^CLOSURE SUB_L_F ")" | BRACKET SUB_EXPRESSION SUB_L_F ")"; @@ -711,6 +721,7 @@ SUB_SINGLE_EXPRESSION ::= | "$name" SINGLE_EXPRESSION ^NAME_OPERATION ")" | "$reference" SINGLE_EXPRESSION ^REFER_OPERATION ")" | "$len" SINGLE_EXPRESSION ^LEN_OPERATION ")" + | "$size" SINGLE_EXPRESSION ^SIZE_OPERATION ")" | BRACKET SUB_EXPRESSION L2_OP* L3_OP* L4_OP* L5_OP* L6_OP? L7_OP* L8_OP? L9_OP? ")"; L4_EXPRESSION ::= @@ -722,6 +733,7 @@ L4_EXPRESSION ::= | "{" NESTED_EXPRESSION ^NESTED L2_OP* L3_OP* | eps ^OBJECT } + | "=" ^OBJECT SINGLE_EXPRESSION ^KEY_VALUE_EXPRESSION | SBRACKET ^OBJECT INDEXER_R L0_OP* L2_OP* L3_OP* | L2_OOP L2_OP* L3_OP* | L3_OOP L3_OP* @@ -736,6 +748,7 @@ L4_EXPRESSION ::= | "$name" SINGLE_EXPRESSION ^NAME_OPERATION | "$reference" SINGLE_EXPRESSION ^REFER_OPERATION | "$len" SINGLE_EXPRESSION ^LEN_OPERATION + | "$size" SINGLE_EXPRESSION ^SIZE_OPERATION | "*" SINGLE_EXPRESSION ^VALUE_OPERATION L2_OP* L3_OP* | "~" SINGLE_EXPRESSION ^BNOT_OPERATION L2_OP* L3_OP* | "-" SINGLE_EXPRESSION ^NEGATE_OPERATION L2_OP* L3_OP* @@ -752,6 +765,7 @@ L5_EXPRESSION ::= | "{" NESTED_EXPRESSION ^NESTED L2_OP* L3_OP* L4_OP* | eps ^OBJECT } + | "=" ^OBJECT SINGLE_EXPRESSION ^KEY_VALUE_EXPRESSION | SBRACKET ^OBJECT INDEXER_R L0_OP* L2_OP* L3_OP* L4_OP* | L2_OOP L2_OP* L3_OP* L4_OP* | L3_OOP L3_OP* L4_OP* @@ -767,6 +781,7 @@ L5_EXPRESSION ::= | "$name" SINGLE_EXPRESSION ^NAME_OPERATION | "$reference" SINGLE_EXPRESSION ^REFER_OPERATION | "$len" SINGLE_EXPRESSION ^LEN_OPERATION + | "$size" SINGLE_EXPRESSION ^SIZE_OPERATION | "*" SINGLE_EXPRESSION ^VALUE_OPERATION L2_OP* L3_OP* L4_OP* | "~" SINGLE_EXPRESSION ^BNOT_OPERATION L2_OP* L3_OP* L4_OP* | "-" SINGLE_EXPRESSION ^NEGATE_OPERATION L2_OP* L3_OP* L4_OP* @@ -784,6 +799,7 @@ L6_EXPRESSION ::= | "{" NESTED_EXPRESSION ^NESTED L2_OP* L3_OP* L4_OP* L5_OP* | eps ^OBJECT } + | "=" ^OBJECT SINGLE_EXPRESSION ^KEY_VALUE_EXPRESSION | SBRACKET ^OBJECT INDEXER_R L0_OP* L2_OP* L3_OP* L4_OP* L5_OP* | L2_OOP L2_OP* L3_OP* L4_OP* L5_OP* | L3_OOP L3_OP* L4_OP* L5_OP* @@ -800,6 +816,7 @@ L6_EXPRESSION ::= | "$name" SINGLE_EXPRESSION ^NAME_OPERATION | "$reference" SINGLE_EXPRESSION ^REFER_OPERATION | "$len" SINGLE_EXPRESSION ^LEN_OPERATION + | "$size" SINGLE_EXPRESSION ^SIZE_OPERATION | "*" SINGLE_EXPRESSION ^VALUE_OPERATION L2_OP* L3_OP* L4_OP* L5_OP* | "~" SINGLE_EXPRESSION ^BNOT_OPERATION L2_OP* L3_OP* L4_OP* L5_OP* | "-" SINGLE_EXPRESSION ^NEGATE_OPERATION L2_OP* L3_OP* L4_OP* L5_OP* @@ -818,6 +835,7 @@ L7_EXPRESSION ::= | "{" NESTED_EXPRESSION ^NESTED L2_OP* L3_OP* L4_OP* L5_OP* L6_OP? | eps ^OBJECT } + | "=" ^OBJECT SINGLE_EXPRESSION ^KEY_VALUE_EXPRESSION | SBRACKET ^OBJECT INDEXER_R L0_OP* L2_OP* L3_OP* L4_OP* L5_OP* L6_OP? | L2_OOP L2_OP* L3_OP* L4_OP* L5_OP* L6_OP? | L3_OOP L3_OP* L4_OP* L5_OP* L6_OP? @@ -836,6 +854,7 @@ L7_EXPRESSION ::= | "$name" SINGLE_EXPRESSION ^NAME_OPERATION | "$reference" SINGLE_EXPRESSION ^REFER_OPERATION | "$len" SINGLE_EXPRESSION ^LEN_OPERATION + | "$size" SINGLE_EXPRESSION ^SIZE_OPERATION | "*" SINGLE_EXPRESSION ^VALUE_OPERATION L2_OP* L3_OP* L4_OP* L5_OP* L6_OP? | "~" SINGLE_EXPRESSION ^BNOT_OPERATION L2_OP* L3_OP* L4_OP* L5_OP* L6_OP? | "-" SINGLE_EXPRESSION ^NEGATE_OPERATION L2_OP* L3_OP* L4_OP* L5_OP* L6_OP? @@ -1197,7 +1216,9 @@ POSTFIXES ::= POSTFIX ::= identifier { "(" { MESSAGE_PARAMETER { "," MESSAGE_PARAMETER }* }? ")" ^ INLINE - | TEMPLATE_BRACKETS ^ TEMPLATE_TYPE + | TEMPLATE_BRACKETS { + "(" { MESSAGE_PARAMETER { "," MESSAGE_PARAMETER }* }? ")" ^ENUM_POSTFIX + | eps ^ TEMPLATE_TYPE } | eps }; MESSAGE_PARAMETERS ::= diff --git a/doc/api/forms.html b/doc/api/forms.html index a28988e31..cbff62119 100644 --- a/doc/api/forms.html +++ b/doc/api/forms.html @@ -129,7 +129,7 @@

Field Summary

-EventHandler<system'Func1> +Func1 onClick @@ -596,7 +596,7 @@

Field Summary

-EventHandler<system'Func1> +Func1 onResize @@ -845,7 +845,7 @@

Field Summary

-EventHandler<system'Func1> +Func1 onResize @@ -1353,7 +1353,7 @@

Field Summary

-EventHandler<system'Func1> +Func1 onResize @@ -1526,7 +1526,7 @@

Field Summary

-EventHandler<system'Func1> +Func1 onClick @@ -1704,7 +1704,7 @@

Field Summary

-EventHandler<system'Func1> +Func1 onResize @@ -2305,7 +2305,7 @@

Field Summary

-EventHandler<system'Func<system'Object,system'drawing'Canvas,system'Object>> +Func<system'Object,system'drawing'Canvas,system'Object> onPaint @@ -3126,7 +3126,7 @@

Field Summary

-EventHandler<system'Func<system'Object,system'drawing'Canvas,system'Object>> +Func<system'Object,system'drawing'Canvas,system'Object> onPaint @@ -3322,7 +3322,7 @@

Field Summary

-EventHandler<system'Func1> +Func1 onResize @@ -3512,7 +3512,7 @@

Field Summary

-EventHandler<system'Func1> +Func1 onClick @@ -3736,7 +3736,7 @@

Field Summary

-EventHandler<system'Func1> +Func1 onResize @@ -3760,7 +3760,7 @@

Field Summary

-EventHandler<system'Func1> +Func1 onIndexChanged @@ -4138,7 +4138,7 @@

Field Summary

-EventHandler<system'Func1> +Func1 onResize @@ -4316,7 +4316,7 @@

Field Summary

-EventHandler<system'Func1> +Func1 onResize diff --git a/doc/api/index.html b/doc/api/index.html index 6cf6e86cc..326875fe0 100644 --- a/doc/api/index.html +++ b/doc/api/index.html @@ -2,7 +2,7 @@ -ELENA Standard Library 6.0 +ELENA Standard Library 6.2 @@ -19,17 +19,17 @@
-ELENA Standard Library
6.0 +ELENA Standard Library
6.2

-ELENA Object Library 6.0 +ELENA Object Library 6.2

-
This document is the API specification for the ELENA Object Library, version 6.0.
+
This document is the API specification for the ELENA Object Library, version 6.2.
    @@ -557,7 +557,7 @@

-ELENA Standard Library
6.0 +ELENA Standard Library
6.2
diff --git a/doc/api/net.html b/doc/api/net.html index 005080030..596e77957 100644 --- a/doc/api/net.html +++ b/doc/api/net.html @@ -93,7 +93,7 @@

Field Summary

-EventHandler<system'Func<net'TcpClient,system'Object>> +Func<net'TcpClient,system'Object> onConnect @@ -101,7 +101,7 @@

Field Summary

-EventHandler<system'Func<net'TcpClient,system'Array<system'ByteNumber>,ystem'IntNumber,system'Object>> +Func<net'TcpClient,system'Array<system'ByteNumber>,ystem'IntNumber,system'Object> onReceived @@ -109,7 +109,7 @@

Field Summary

-EventHandler<system'Func<net'TcpClient,system'net'SocketException,system'Object>> +Func<net'TcpClient,system'net'SocketException,system'Object> onError @@ -617,7 +617,7 @@

Field Summary

-EventHandler<system'Func<net'TcpRemoteClient,system'Object>> +Func<net'TcpRemoteClient,system'Object> OnConnect @@ -625,7 +625,7 @@

Field Summary

-EventHandler<system'Func<net'TcpRemoteClient,system'Object>> +Func<net'TcpRemoteClient,system'Object> OnLeave @@ -633,7 +633,7 @@

Field Summary

-EventHandler<system'Func<net'TcpRemoteClient,system'Array<system'ByteNumber>,ystem'IntNumber,system'Object>> +Func<net'TcpRemoteClient,system'Array<system'ByteNumber>,ystem'IntNumber,system'Object> OnReceived @@ -641,7 +641,7 @@

Field Summary

-EventHandler<system'Func<net'TcpRemoteClient,system'net'SocketException,system'Object>> +Func<net'TcpRemoteClient,system'net'SocketException,system'Object> OnError diff --git a/doc/api/system-runtime.html b/doc/api/system-runtime.html index bc5f935d3..a017fda75 100644 --- a/doc/api/system-runtime.html +++ b/doc/api/system-runtime.html @@ -366,12 +366,30 @@

Method Summary

+BoolValue + +rearrange() + + + + + + UnsafePointer allocate(Object obj) + + + + + +release(Object obj) + + + diff --git a/doc/todo.txt b/doc/todo.txt index 1f3a08f7e..f8ecaccb4 100644 --- a/doc/todo.txt +++ b/doc/todo.txt @@ -5,35 +5,25 @@ In development: [development] ### EPIC: elena 6.3 ### - === Iteration 27 === + === Iteration 28 === -------------------------------------- dev: - - #265 - - system'winforms : free PermVectorTable item after the window is closed, to save the resources - - + - upndown + - web server - weather forecast + - #668 gen: - elt : nested executing managed code : keep frames (the frames must be included / excluded correctly) - elt : fails after executing several times, exception handler works only once - nested call must not stop / start vm, maint: - - - - - - - port: - - x86-64 : agenda, scripts - - #658 : create debug adapter - - - prom: - -------------------------------------- - -------------------------------------- - - === Iteration 28 === - -------------------------------------- - dev: - gen: - maint: + - elena : nested classes should not be loadable at runtime + - constructor - single dispatcher; passing nil to single dispatcher (both normal / constructor) + - #667 port: - prom: + - x86-64 : vm terminal, ide vm console + - #658 : create simplest debug adapter; connect with it from VSCode + - linux sdi - menu / new file + prom: posting weekly -------------------------------------- -------------------------------------- diff --git a/elenasrc3/dpa/dpa_common.h b/elenasrc3/dpa/dpa_common.h new file mode 100644 index 000000000..4a43fa1f6 --- /dev/null +++ b/elenasrc3/dpa/dpa_common.h @@ -0,0 +1,17 @@ +//--------------------------------------------------------------------------- +// E L E N A P r o j e c t: ELENA Debugger Adapater +// +// This file contains the common DPA declarations +// +// (C)2024, by Aleksey Rakov +//--------------------------------------------------------------------------- + +#ifndef DPA_COMMON_H +#define DPA_COMMON_H + +namespace dpa +{ + +} + +#endif \ No newline at end of file diff --git a/elenasrc3/dpa/dpa_session.cpp b/elenasrc3/dpa/dpa_session.cpp new file mode 100644 index 000000000..fbab19d18 --- /dev/null +++ b/elenasrc3/dpa/dpa_session.cpp @@ -0,0 +1,21 @@ +//--------------------------------------------------------------------------- +// E L E N A P r o j e c t: ELENA Debugger Adapater +// +// This file contains the DPA Session implementations +// +// (C)2024, by Aleksey Rakov +//--------------------------------------------------------------------------- + +#include "dpa_session.h" + +using namespace dpa; + +Session :: Session() +{ + +} + +Session :: ~Session() +{ + +} \ No newline at end of file diff --git a/elenasrc3/dpa/dpa_session.h b/elenasrc3/dpa/dpa_session.h new file mode 100644 index 000000000..9e758287a --- /dev/null +++ b/elenasrc3/dpa/dpa_session.h @@ -0,0 +1,23 @@ +//--------------------------------------------------------------------------- +// E L E N A P r o j e c t: ELENA Debugger Adapater +// +// This file contains the DPA Session declarations +// +// (C)2024, by Aleksey Rakov +//--------------------------------------------------------------------------- + +#ifndef DPA_SESSION_H +#define DPA_SESSION_H + +namespace dpa +{ + // --- Session --- + class Session + { + public: + Session(); + virtual ~Session(); + }; +} + +#endif \ No newline at end of file diff --git a/elenasrc3/elc/clicommon.h b/elenasrc3/elc/clicommon.h index ecc245f93..6ebb26690 100644 --- a/elenasrc3/elc/clicommon.h +++ b/elenasrc3/elc/clicommon.h @@ -145,7 +145,8 @@ enum class TemplateType InlineProperty, Class, Statement, - Expression + Expression, + Enumeration }; enum class Visibility @@ -525,6 +526,8 @@ class TemplateProssesorBase List& arguments, List& parameters) = 0; virtual bool importExpressionTemplate(ModuleScopeBase& moduleScope, ref_t templateRef, SyntaxNode target, List& arguments, List& parameters) = 0; + virtual bool importEnumTemplate(ModuleScopeBase& moduleScope, ref_t templateRef, + SyntaxNode target, List& arguments, List& parameters) = 0; }; // --- SyntaxWriterBase --- diff --git a/elenasrc3/elc/cliconst.h b/elenasrc3/elc/cliconst.h index 8b498f327..47bfa0124 100644 --- a/elenasrc3/elc/cliconst.h +++ b/elenasrc3/elc/cliconst.h @@ -13,7 +13,7 @@ namespace elena_lang { - #define ELC_REVISION_NUMBER 0x001B + #define ELC_REVISION_NUMBER 0x0023 #if defined _M_IX86 || _M_X64 diff --git a/elenasrc3/elc/compiler.cpp b/elenasrc3/elc/compiler.cpp index 6cf370f70..8b1e5cfe1 100644 --- a/elenasrc3/elc/compiler.cpp +++ b/elenasrc3/elc/compiler.cpp @@ -160,6 +160,52 @@ void declareTemplateParameters(ModuleBase* module, TemplateTypeList& typeList, dummyWriter.closeNode(); } +void declareArguments(SyntaxNode node, SyntaxTree& dummyTree, List& arguments) +{ + SyntaxTreeWriter dummyWriter(dummyTree); + dummyWriter.newNode(SyntaxKey::Root); + + SyntaxNode current = node.firstChild(); + while (current != SyntaxKey::None) { + switch (current.key) { + case SyntaxKey::Expression: + dummyWriter.newNode(SyntaxKey::Expression); + + arguments.add(dummyWriter.CurrentNode()); + SyntaxTree::copyNode(dummyWriter, current); + + dummyWriter.closeNode(); + break; + default: + break; + } + + current = current.nextNode(); + } + + + //for (size_t i = 0; i < typeList.count(); i++) { + // ref_t elementRef = typeList[i]; + + // dummyWriter.newNode(SyntaxKey::TemplateArg, elementRef); + + // parameters.add(dummyWriter.CurrentNode()); + + // dummyWriter.newNode(SyntaxKey::Type); + + // ustr_t referenceName = module->resolveReference(elementRef); + // if (isWeakReference(referenceName)) { + // dummyWriter.appendNode(SyntaxKey::reference, referenceName); + // } + // else dummyWriter.appendNode(SyntaxKey::globalreference, referenceName); + + // dummyWriter.closeNode(); + // dummyWriter.closeNode(); + //} + + dummyWriter.closeNode(); +} + inline ref_t mapIntConstant(ModuleScopeBase* moduleScope, int integer) { String s; @@ -696,6 +742,9 @@ bool Interpreter :: evalDeclOp(ref_t operator_id, ArgumentsInfo& args, ObjectInf case ObjectKind::Field: retVal = { ObjectKind::FieldName, { V_STRING }, loperand.reference }; return true; + case ObjectKind::ConstGetter: + retVal = { ObjectKind::StringLiteral, { V_STRING }, loperand.extra }; + return true; default: break; } @@ -1997,6 +2046,35 @@ ref_t Compiler :: retrieveTemplate(NamespaceScope& scope, SyntaxNode node, List< return reference; } +bool Compiler :: importEnumTemplate(Scope& scope, SyntaxNode node, SyntaxNode target) +{ + TypeAttributes attributes = {}; + + TemplateTypeList typeList; + declareTemplateAttributes(scope, node, typeList, attributes, true, false); + if (attributes.isNonempty()) + scope.raiseError(errInvalidOperation, node); + + // HOTFIX : generate a temporal template to pass the type + SyntaxTree dummyTree; + List parameters({}); + declareTemplateParameters(scope.module, typeList, dummyTree, parameters); + + SyntaxTree dummyTree2; + List arguments({}); + declareArguments(node, dummyTree, arguments); + + NamespaceScope* ns = Scope::getScope(scope, Scope::ScopeLevel::Namespace); + ref_t templateRef = retrieveTemplate(*ns, node, parameters, nullptr, SyntaxKey::None, ENUM_POSTFIX); + if (!templateRef) + return false; + + if (!_templateProcessor->importEnumTemplate(*scope.moduleScope, templateRef, target, parameters, arguments)) + scope.raiseError(errInvalidOperation, node); + + return true; +} + bool Compiler :: importTemplate(Scope& scope, SyntaxNode node, SyntaxNode target, bool weakOne) { TypeAttributes attributes = {}; @@ -3199,6 +3277,15 @@ void Compiler :: generateClassField(ClassScope& scope, SyntaxNode node, } ustr_t name = node.findChild(SyntaxKey::Name).firstChild(SyntaxKey::TerminalMask).identifier(); + if (scope.info.fields.exist(name)) { + if (attrs.autogenerated) { + node.setKey(SyntaxKey::Idle); + } + else scope.raiseError(errDuplicatedField, node); + + return; + } + if (!generateClassField(scope, attrs, name, sizeHint, typeInfo, singleField)) { if (attrs.overrideMode && checkPreviousDeclaration(node, name)) { @@ -3895,6 +3982,53 @@ void Compiler :: copyParentNamespaceExtensions(NamespaceScope& source, Namespace } } +ObjectInfo Compiler :: evalExprValueOperation(Interpreter& interpreter, Scope& scope, SyntaxNode node, bool ignoreErrors) +{ + SyntaxNode lnode = node.firstChild(SyntaxKey::DeclarationMask); + while (lnode == SyntaxKey::Expression) + lnode = lnode.firstChild(); + + if (lnode == SyntaxKey::KeyValueExpression) { + return evalExpression(interpreter, scope, lnode.findChild(SyntaxKey::Expression), ignoreErrors); + } + + if (!ignoreErrors) { + scope.raiseError(errCannotEval, node); + } + return {}; +} + +ObjectInfo Compiler :: evalSizeOperation(Interpreter& interpreter, Scope& scope, SyntaxNode node, bool ignoreErrors) +{ + SyntaxNode lnode = node.firstChild(SyntaxKey::DeclarationMask); + + ObjectInfo loperand = evalExpression(interpreter, scope, lnode, ignoreErrors); + SizeInfo sizeInfo = {}; + switch (loperand.kind) { + case ObjectKind::LocalAddress: + case ObjectKind::ParamAddress: + { + ref_t sourceRef = resolveStrongType(scope, loperand.typeInfo); + sizeInfo = _logic->defineStructSize(*scope.moduleScope, sourceRef); + + break; + } + case ObjectKind::Class: + sizeInfo = _logic->defineStructSize(*scope.moduleScope, loperand.reference); + break; + default: + break; + } + + if (sizeInfo.size > 0) + return { ObjectKind::IntLiteral, { V_INT32 }, ::mapIntConstant(scope.moduleScope, sizeInfo.size), sizeInfo.size }; + + if (!ignoreErrors) { + scope.raiseError(errCannotEval, node); + } + return {}; +} + ObjectInfo Compiler :: evalOperation(Interpreter& interpreter, Scope& scope, SyntaxNode node, ref_t operator_id, bool ignoreErrors) { ObjectInfo loperand = {}; @@ -3966,6 +4100,17 @@ ObjectInfo Compiler :: evalObject(Interpreter& interpreter, Scope& scope, Syntax return mapObject(scope, node, mode); } +ObjectInfo Compiler :: evalGetter(Interpreter& interpreter, Scope& scope, SyntaxNode node, bool ignoreErrors) +{ + // HOTFIX : getter is partially evaluated to be used with $name operator + SyntaxNode nameNode = node.findChild(SyntaxKey::Object).findChild(SyntaxKey::identifier); + assert(nameNode.key == SyntaxKey::identifier); + + ref_t nameRef = scope.module->mapConstant(nameNode.identifier()); + + return { ObjectKind::ConstGetter, V_GETTER, 0, nameRef }; +} + ObjectInfo Compiler :: evalPropertyOperation(Interpreter& interpreter, Scope& scope, SyntaxNode node, bool ignoreErrors) { SyntaxNode lnode = node.firstChild(); @@ -4088,6 +4233,9 @@ ObjectInfo Compiler :: evalExpression(Interpreter& interpreter, Scope& scope, Sy case SyntaxKey::ReferOperation: retVal = evalOperation(interpreter, scope, node, (int)node.key - OPERATOR_MAKS, ignoreErrors); break; + case SyntaxKey::ExprValOperation: + retVal = evalExprValueOperation(interpreter, scope, node, ignoreErrors); + break; case SyntaxKey::Object: retVal = evalObject(interpreter, scope, node); if (!ignoreErrors && retVal.kind == ObjectKind::Unknown) { @@ -4109,6 +4257,11 @@ ObjectInfo Compiler :: evalExpression(Interpreter& interpreter, Scope& scope, Sy retVal = metaExpr.generateNestedConstant(node); break; } + case SyntaxKey::KeyValueExpression: + { + retVal = evalGetter(interpreter, scope, node, ignoreErrors); + break; + } default: if (ignoreErrors) { return {}; @@ -4535,6 +4688,11 @@ void Compiler :: declareMethodAttributes(MethodScope& scope, SyntaxNode node, bo } else scope.info.hints |= hint; } + else if (value == V_TYPEOF) { + // HOTFIX : if it is a type of the class + if (!scope.info.outputRef) + scope.info.outputRef = scope.getClassRef(); + } else { current.setArgumentReference(0); @@ -4762,6 +4920,7 @@ void Compiler :: saveNamespaceInfo(SyntaxNode node, NamespaceScope* nsScope, boo void Compiler :: declareTemplate(TemplateScope& scope, SyntaxNode& node) { switch (scope.type) { + case TemplateType::Enumeration: case TemplateType::Class: case TemplateType::InlineProperty: { @@ -4848,8 +5007,9 @@ void Compiler :: declareTemplateClass(TemplateScope& scope, SyntaxNode& node) declareTemplateAttributes(scope, node, postfix); int argCount = SyntaxTree::countChild(node, SyntaxKey::TemplateArg); + postfix.append('#'); - postfix.appendInt(argCount); + postfix.appendInt(scope.type == TemplateType::Enumeration ? argCount-1 : argCount); if (SyntaxTree::ifChildExists(node, SyntaxKey::Attribute, V_WEAK)) postfix.append(WEAK_POSTFIX); @@ -4859,6 +5019,9 @@ void Compiler :: declareTemplateClass(TemplateScope& scope, SyntaxNode& node) case TemplateType::InlineProperty: prefix.append(INLINE_PROPERTY_PREFIX); break; + case TemplateType::Enumeration: + postfix.append(ENUM_POSTFIX); + break; default: break; } @@ -8527,14 +8690,20 @@ void Compiler :: compileConstructor(BuildTreeWriter& writer, MethodScope& scope, writer.appendNode(BuildKey::OpenFrame); newFrame = true; - if (!retExpr) { - // NOTE : the named constructor should be polymorphic, depending on the message target - writer.appendNode(BuildKey::Local, -1); - //writer.appendNode(BuildKey::ClassReference, scope.getClassRef()); - - writer.newNode(BuildKey::CallOp, defConstrMssg); - writer.appendNode(BuildKey::Index, 1); // built-in constructor entry should be the second entry in VMT - writer.closeNode(); + if (!retExpr) { + if (test(defConstrMssg, STATIC_MESSAGE)) { + // NOTE : if the the constructor is private - it must be called directly (the class cannot be inherited in this case, so it is not polymorphic anymore) + writer.newNode(BuildKey::DirectCallOp, defConstrMssg); + writer.appendNode(BuildKey::Type, classClassScope.reference); + writer.closeNode(); + } + else { + // NOTE : the named constructor should be polymorphic, depending on the message target + writer.appendNode(BuildKey::Local, -1); + writer.newNode(BuildKey::CallOp, defConstrMssg); + writer.appendNode(BuildKey::Index, 1); // built-in constructor entry should be the second entry in VMT + writer.closeNode(); + } } } // if it is a dynamic object implicit constructor call is not possible @@ -9028,24 +9197,14 @@ void Compiler :: compileClassVMT(BuildTreeWriter& writer, ClassScope& classClass // first pass - compile constructors while (current != SyntaxKey::None) { switch (current.key) { - case SyntaxKey::Constructor: - { - MethodScope methodScope(&scope); - initializeMethod(classClassScope, methodScope, current); - methodScope.constructorMode = true; - -#ifdef FULL_OUTOUT_INFO - IdentifierString messageName; - ByteCodeUtil::resolveMessageName(messageName, scope.module, methodScope.message); - - _errorProcessor->info(infoCurrentMethod, *messageName); -#endif // FULL_OUTOUT_INFO - - compileConstructor(writer, methodScope, classClassScope, current, scope.isAbstract()); - break; - } - default: - break; + case SyntaxKey::Constructor: + { + Method method(this, scope); + method.compileConstructor(writer, current, classClassScope); + break; + } + default: + break; } current = current.nextNode(); } @@ -9054,24 +9213,24 @@ void Compiler :: compileClassVMT(BuildTreeWriter& writer, ClassScope& classClass current = node.firstChild(); while (current != SyntaxKey::None) { switch (current.key) { - case SyntaxKey::StaticMethod: - { - MethodScope methodScope(&classClassScope); - initializeMethod(classClassScope, methodScope, current); + case SyntaxKey::StaticMethod: + { + MethodScope methodScope(&classClassScope); + initializeMethod(classClassScope, methodScope, current); -#ifdef FULL_OUTOUT_INFO - IdentifierString messageName; - ByteCodeUtil::resolveMessageName(messageName, scope.module, methodScope.message); + #ifdef FULL_OUTOUT_INFO + IdentifierString messageName; + ByteCodeUtil::resolveMessageName(messageName, scope.module, methodScope.message); - _errorProcessor->info(infoCurrentMethod, *messageName); -#endif // FULL_OUTOUT_INFO + _errorProcessor->info(infoCurrentMethod, *messageName); + #endif // FULL_OUTOUT_INFO - compileMethod(writer, methodScope, current); + compileMethod(writer, methodScope, current); - break; - } - default: - break; + break; + } + default: + break; } current = current.nextNode(); } @@ -9292,6 +9451,7 @@ void Compiler :: compileClass(BuildTreeWriter& writer, ClassScope& scope, Syntax writer.appendNode(BuildKey::Path, *ns->sourcePath); compileVMT(writer, scope, node); + writer.closeNode(); scope.save(); @@ -9315,6 +9475,7 @@ void Compiler :: compileClassClass(BuildTreeWriter& writer, ClassScope& classCla writer.appendNode(BuildKey::Path, *ns->sourcePath); compileClassVMT(writer, classClassScope, scope, node); + writer.closeNode(); } @@ -10494,7 +10655,7 @@ bool Compiler::Class :: isParentDeclared(SyntaxNode node) return true; SyntaxNode child = parentNode.firstChild(); - if (child != SyntaxKey::TemplateType && child != SyntaxKey::None) { + if (child != SyntaxKey::TemplateType && child != SyntaxKey::EnumPostfix && child != SyntaxKey::None) { ref_t parentRef = compiler->resolveStrongTypeAttribute(scope, child, true, false).typeRef; return scope.moduleScope->isDeclared(parentRef); @@ -10600,7 +10761,11 @@ void Compiler::Class :: resolveClassPostfixes(SyntaxNode node, bool extensionMod parentRef = compiler->resolveStrongTypeAttribute(scope, child, extensionMode, false).typeRef; } - else if (!compiler->importTemplate(scope, child, node, false)) + else if (!compiler->importTemplate(scope, child, node, false)) + scope.raiseError(errUnknownTemplate, current); + } + else if (child == SyntaxKey::EnumPostfix) { + if (!compiler->importEnumTemplate(scope, child, node)) scope.raiseError(errUnknownTemplate, current); } else if (!parentRef) { @@ -10681,6 +10846,20 @@ void Compiler::Class :: load() scope.extensionClassRef = scope.getAttribute(ClassAttribute::ExtensionRef); } +// --- Compiler::ClassClass --- + +Compiler::ClassClass :: ClassClass(Class& classHelper) + : compiler(classHelper.compiler), + scope(classHelper.scope.parent, classHelper.scope.info.header.classRef, classHelper.scope.visibility, + &classHelper.scope.info, classHelper.scope.reference) +{ +} + +void Compiler::ClassClass :: load() +{ + scope.moduleScope->loadClassInfo(scope.info, scope.reference, false); +} + // --- Compiler::Method --- Compiler::Method :: Method(Class& cls) @@ -10725,6 +10904,28 @@ void Compiler::Method :: compile(BuildTreeWriter& writer, SyntaxNode current) else compiler->compileMethod(writer, scope, current); } +void Compiler::Method :: compileConstructor(BuildTreeWriter& writer, SyntaxNode current, ClassScope& classClassScope) +{ + ClassScope* classScope = Scope::getScope(scope, Scope::ScopeLevel::Class); + + compiler->initializeMethod(classClassScope, scope, current); + scope.constructorMode = true; + +#ifdef FULL_OUTOUT_INFO + IdentifierString messageName; + ByteCodeUtil::resolveMessageName(messageName, scope.module, methodScope.message); + + _errorProcessor->info(infoCurrentMethod, *messageName); +#endif // FULL_OUTOUT_INFO + + compiler->compileConstructor(writer, scope, classClassScope, current, classScope->isAbstract()); +} + +void Compiler::Method :: compileConstructor(BuildTreeWriter& writer, SyntaxNode current, ClassClass& classClassHelper) +{ + compileConstructor(writer, current, classClassHelper.scope); +} + // --- Compiler::Code --- Compiler::Code :: Code(Method& method) @@ -10929,6 +11130,10 @@ ObjectInfo Compiler::Expression :: compile(SyntaxNode node, ref_t targetRef, EAt case SyntaxKey::NegateOperation: retVal = compileOperation(current, (int)current.key - OPERATOR_MAKS, targetRef, mode); break; + case SyntaxKey::ExprValOperation: + case SyntaxKey::SizeOperation: + retVal = compileEvalOnlySpecialOperation(current); + break; case SyntaxKey::BreakOperation: case SyntaxKey::ContinueOperation: retVal = compileSpecialOperation(current, (int)current.key - OPERATOR_MAKS, targetRef); @@ -11011,6 +11216,9 @@ ObjectInfo Compiler::Expression :: compile(SyntaxNode node, ref_t targetRef, EAt case SyntaxKey::CollectionExpression: retVal = compileCollection(current, mode); break; + case SyntaxKey::KeyValueExpression: + retVal = compileKeyValue(current, mode); + break; case SyntaxKey::Type: case SyntaxKey::ReferOperation: scope.raiseError(errInvalidOperation, node); @@ -12105,6 +12313,28 @@ ObjectInfo Compiler::Expression :: compileTupleCollection(SyntaxNode node, ref_t return { ObjectKind::Object, { tupleRef }, 0 }; } +ObjectInfo Compiler::Expression :: compileKeyValue(SyntaxNode node, ExpressionAttribute mode) +{ + SyntaxTree tempTree; + SyntaxTreeWriter treeWriter(tempTree); + treeWriter.newNode(SyntaxKey::NestedBlock); + treeWriter.newNode(SyntaxKey::Method); + + treeWriter.appendNode(SyntaxKey::Attribute, V_GETACCESSOR); + treeWriter.newNode(SyntaxKey::Name); + SyntaxTree::copyNode(treeWriter, node.findChild(SyntaxKey::Object), false); + treeWriter.closeNode(); + + treeWriter.newNode(SyntaxKey::ReturnExpression); + SyntaxTree::copyNode(treeWriter, node.findChild(SyntaxKey::Expression), true); + treeWriter.closeNode(); + + treeWriter.closeNode(); + treeWriter.closeNode(); + + return compileNested(tempTree.readRoot(), EAttr::None, nullptr); +} + ObjectInfo Compiler::Expression :: compileTupleAssigning(SyntaxNode node) { ArgumentsInfo targets; @@ -12872,6 +13102,33 @@ ObjectInfo Compiler::Expression :: compileMessageOperation(SyntaxNode node, Obje return retVal; } +ObjectInfo Compiler::Expression :: compileEvalOnlySpecialOperation(SyntaxNode node) +{ + Interpreter interpreter(scope.moduleScope, compiler->_logic); + ObjectInfo evalRetVal = {}; + + switch (node.key) { + case SyntaxKey::ExprValOperation: + evalRetVal = compiler->evalExprValueOperation(interpreter, scope, node, false); + break; + case SyntaxKey::SizeOperation: + evalRetVal = compiler->evalSizeOperation(interpreter, scope, node, false); + break; + default: + assert(false); + break; + } + + if (evalRetVal.kind != ObjectKind::Unknown) { + return evalRetVal; + } + + // NOTE : it must be only compile-time operation + scope.raiseError(errInvalidOperation, node); + + return {}; +} + ObjectInfo Compiler::Expression :: compileOperation(SyntaxNode node, SyntaxNode rnode, int operatorId, ref_t expectedRef) { if (compiler->_evaluateOp) { @@ -13070,8 +13327,13 @@ bool Compiler::Expression :: writeObjectInfo(ObjectInfo info, bool allowMeta) writer->appendNode(BuildKey::Field, info.extra); break; case ObjectKind::StaticConstField: - writeObjectInfo(scope.mapSelf()); - writer->appendNode(BuildKey::ClassOp, CLASS_OPERATOR_ID); + if (scope.isSealed(false)) { + writer->appendNode(BuildKey::ClassReference, scope.getClassRef(false)); + } + else { + writeObjectInfo(scope.mapSelf()); + writer->appendNode(BuildKey::ClassOp, CLASS_OPERATOR_ID); + } writer->appendNode(BuildKey::Field, info.reference); break; case ObjectKind::ClassStaticConstField: @@ -13396,7 +13658,7 @@ bool Compiler::Expression :: compileAssigningOp(ObjectInfo target, ObjectInfo ex if (size != 0) { writer->appendNode(BuildKey::Size, size); - // HOTFIX : nil cannit be assigned to a struct + // HOTFIX : nil cannot be assigned to a struct if (exprVal.kind == ObjectKind::Nil) return false; diff --git a/elenasrc3/elc/compiler.h b/elenasrc3/elc/compiler.h index 36259c006..7b650170d 100644 --- a/elenasrc3/elc/compiler.h +++ b/elenasrc3/elc/compiler.h @@ -96,6 +96,7 @@ namespace elena_lang ClosureInfo, MemberInfo, LocalField, + ConstGetter, // key = value constant }; enum TargetMode @@ -956,6 +957,12 @@ namespace elena_lang return scope ? scope->reference : 0; } + ref_t isSealed(bool ownerClass = true) + { + ClassScope* scope = Scope::getScope(*this, ownerClass ? ScopeLevel::OwnerClass : ScopeLevel::Class); + + return scope ? test(scope->info.header.flags, elSealed) : false; + } ObjectInfo mapSelf(bool ownerClass = false) { @@ -1153,6 +1160,19 @@ namespace elena_lang Class(Namespace& ns, ref_t reference, Visibility visibility); }; + class ClassClass + { + friend class Compiler; + + Compiler* compiler; + ClassClassScope scope; + + public: + void load(); + + ClassClass(Class& classHelper); + }; + class Method { friend class Compiler; @@ -1160,8 +1180,11 @@ namespace elena_lang Compiler* compiler; MethodScope scope; + void compileConstructor(BuildTreeWriter& writer, SyntaxNode current, ClassScope& classClassScope); + public: void compile(BuildTreeWriter& writer, SyntaxNode current); + void compileConstructor(BuildTreeWriter& writer, SyntaxNode current, ClassClass& classClassHelper); Method(Class& cls); Method(Compiler* compiler, ClassScope& classScope); @@ -1202,6 +1225,7 @@ namespace elena_lang ObjectInfo compilePropertyOperation(SyntaxNode node, ref_t targetRef, ExpressionAttribute attrs); ObjectInfo compileOperation(SyntaxNode node, int operatorId, ref_t expectedRef, ExpressionAttribute mode); + ObjectInfo compileEvalOnlySpecialOperation(SyntaxNode node); 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); @@ -1323,6 +1347,7 @@ namespace elena_lang ObjectInfo compileObject(SyntaxNode node, ExpressionAttribute mode, ArgumentsInfo* updatedOuterArgs); ObjectInfo compileCollection(SyntaxNode node, ExpressionAttribute mode); ObjectInfo compileTupleCollection(SyntaxNode node, ref_t targetRef); + ObjectInfo compileKeyValue(SyntaxNode node, ExpressionAttribute mode); ObjectInfo compileSubCode(SyntaxNode node, ExpressionAttribute mode, bool withoutNewScope = false); @@ -1426,6 +1451,7 @@ namespace elena_lang bool isDefaultOrConversionConstructor(Scope& scope, mssg_t message, bool internalOne, bool& isProtectedDefConst); + bool importEnumTemplate(Scope& scope, SyntaxNode node, SyntaxNode target); bool importTemplate(Scope& scope, SyntaxNode node, SyntaxNode target, bool weakOne); bool importInlineTemplate(Scope& scope, SyntaxNode node, ustr_t postfix, SyntaxNode target); bool importPropertyTemplate(Scope& scope, SyntaxNode node, ustr_t postfix, SyntaxNode target); @@ -1548,6 +1574,9 @@ namespace elena_lang ObjectInfo evalObject(Interpreter& interpreter, Scope& scope, SyntaxNode node); ObjectInfo evalCollection(Interpreter& interpreter, Scope& scope, SyntaxNode node, bool anonymousOne, bool ignoreErrors); ObjectInfo evalPropertyOperation(Interpreter& interpreter, Scope& scope, SyntaxNode node, bool ignoreErrors); + ObjectInfo evalExprValueOperation(Interpreter& interpreter, Scope& scope, SyntaxNode node, bool ignoreErrors); + ObjectInfo evalSizeOperation(Interpreter& interpreter, Scope& scope, SyntaxNode node, bool ignoreErrors); + ObjectInfo evalGetter(Interpreter& interpreter, Scope& scope, SyntaxNode node, bool ignoreErrors); void evalStatement(MetaScope& scope, SyntaxNode node); diff --git a/elenasrc3/elc/compilerlogic.cpp b/elenasrc3/elc/compilerlogic.cpp index 8d3379426..f9ee72e22 100644 --- a/elenasrc3/elc/compilerlogic.cpp +++ b/elenasrc3/elc/compilerlogic.cpp @@ -41,7 +41,7 @@ bool testMethodHint(ref_t hint, MethodHint mask) typedef CompilerLogic::Op Op; -constexpr auto OperationLength = 206; +constexpr auto OperationLength = 207; constexpr Op Operations[OperationLength] = { { @@ -71,6 +71,9 @@ constexpr Op Operations[OperationLength] = { NAME_OPERATOR_ID, BuildKey::DeclOp, V_DECLARATION, 0, 0, V_STRING }, + { + NAME_OPERATOR_ID, BuildKey::DeclOp, V_GETTER, 0, 0, V_STRING + }, { REFERENCE_OPERATOR_ID, BuildKey::DeclOp, V_DECLARATION, 0, 0, V_STRING }, @@ -761,6 +764,9 @@ bool CompilerLogic :: validateTemplateAttribute(ref_t attribute, Visibility& vis case V_FIELD: type = TemplateType::InlineProperty; break; + case V_ENUMERATION: + type = TemplateType::Enumeration; + break; case V_TEMPLATE: case V_WEAK: break; diff --git a/elenasrc3/elc/compiling.cpp b/elenasrc3/elc/compiling.cpp index 4ed81609c..3a552bdf1 100644 --- a/elenasrc3/elc/compiling.cpp +++ b/elenasrc3/elc/compiling.cpp @@ -158,6 +158,20 @@ bool CompilingProcess::TemplateGenerator :: importExpressionTemplate(ModuleScope return true; } +bool CompilingProcess::TemplateGenerator :: importEnumTemplate(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.importEnumTemplate(sectionInfo.section, target, arguments, parameters); + + return true; +} + size_t getLengthSkipPostfix(ustr_t name) { size_t len = name.length(); diff --git a/elenasrc3/elc/compiling.h b/elenasrc3/elc/compiling.h index e60bbccbe..e6f00e4aa 100644 --- a/elenasrc3/elc/compiling.h +++ b/elenasrc3/elc/compiling.h @@ -60,6 +60,9 @@ namespace elena_lang bool importExpressionTemplate(ModuleScopeBase& moduleScope, ref_t templateRef, SyntaxNode target, List& arguments, List& parameters) override; + bool importEnumTemplate(ModuleScopeBase& moduleScope, ref_t templateRef, + SyntaxNode target, List& arguments, List& parameters) override; + TemplateGenerator(CompilingProcess* process); }; diff --git a/elenasrc3/elc/derivation.cpp b/elenasrc3/elc/derivation.cpp index 107eda811..7c091a0f3 100644 --- a/elenasrc3/elc/derivation.cpp +++ b/elenasrc3/elc/derivation.cpp @@ -784,6 +784,13 @@ void SyntaxTreeBuilder :: flushDescriptor(SyntaxTreeWriter& writer, Scope& scope } else flushNode(writer, scope, current); } + else if (scope.withEnumParameter()) { + int index = scope.parameters.get(current.identifier()); + if (index) { + key = SyntaxKey::EnumNameArgParameter; + attrRef = index + scope.nestedLevel; + } + } writer.newNode(key, attrRef); flushNode(writer, scope, current); @@ -971,6 +978,26 @@ void SyntaxTreeBuilder :: flushParentTemplate(SyntaxTreeWriter& writer, Scope& s writer.closeNode(); } +void SyntaxTreeBuilder :: flushEnumTemplate(SyntaxTreeWriter& writer, Scope& scope, SyntaxNode node) +{ + writer.newNode(node.key); + + SyntaxNode current = node.firstChild(); + while (current != SyntaxKey::None) { + if (current == SyntaxKey::TemplateArg) { + flushTemplateArg(writer, scope, current, true); + } + else if (current == SyntaxKey::Expression) { + flushExpression(writer, scope, current); + } + else flushNode(writer, scope, current); + + current = current.nextNode(); + } + + writer.closeNode(); +} + void SyntaxTreeBuilder :: flushParent(SyntaxTreeWriter& writer, Scope& scope, SyntaxNode node) { ref_t attributeCategory = V_CATEGORY_MAX; @@ -980,6 +1007,9 @@ void SyntaxTreeBuilder :: flushParent(SyntaxTreeWriter& writer, Scope& scope, Sy if (current == SyntaxKey::TemplatePostfix) { flushParentTemplate(writer, scope, current); } + else if (current == SyntaxKey::EnumPostfix) { + flushEnumTemplate(writer, scope, current); + } else if (testNodeMask(current.key, SyntaxKey::TerminalMask)) { flushAttribute(writer, scope, current, attributeCategory, current.nextNode() == SyntaxKey::None); } @@ -1490,6 +1520,13 @@ void SyntaxTreeBuilder :: flushTemplate(SyntaxTreeWriter& writer, Scope& scope, { // load arguments SyntaxNode current = node.findChild(SyntaxKey::TemplateArg); + if (scope.type == ScopeType::Enumeration) { + // NOTE : the first argument is the enumeration member + flushParameterArgDescr(writer, scope, current); + + current = current.nextNode(); + } + while (current == SyntaxKey::TemplateArg) { flushTemplateArgDescr(writer, scope, current); @@ -1614,6 +1651,9 @@ SyntaxTreeBuilder::ScopeType SyntaxTreeBuilder :: defineTemplateType(SyntaxNode case V_EXTENSION: type = ScopeType::ExtensionTemplate; break; + case V_ENUMERATION: + type = ScopeType::Enumeration; + break; default: break; } @@ -1825,6 +1865,13 @@ void SyntaxTreeBuilder :: clearMetaSection(SyntaxNode node) // --- TemplateProssesor --- +void TemplateProssesor :: copyKVKey(SyntaxTreeWriter& writer, TemplateScope& scope, SyntaxNode node) +{ + SyntaxNode key = node.firstChild(); + + copyChildren(writer, scope, key); +} + void TemplateProssesor :: copyNode(SyntaxTreeWriter& writer, TemplateScope& scope, SyntaxNode node) { switch (node.key) { @@ -1868,6 +1915,32 @@ void TemplateProssesor :: copyNode(SyntaxTreeWriter& writer, TemplateScope& scop writer.closeNode(); } break; + case SyntaxKey::EnumNameArgParameter: + if (node.arg.reference < 0x100) { + SyntaxNode nodeToInject = scope.parameterValues.get(scope.enumIndex); + + writer.newNode(SyntaxKey::Name); + copyKVKey(writer, scope, nodeToInject.firstChild()); + writer.closeNode(); + } + else { + writer.newNode(node.key, node.arg.reference - 0x100); + copyChildren(writer, scope, node); + writer.closeNode(); + } + break; + case SyntaxKey::EnumArgParameter: + if (node.arg.reference < 0x100) { + SyntaxNode nodeToInject = scope.parameterValues.get(scope.enumIndex); + writer.CurrentNode().setKey(nodeToInject.key); + copyChildren(writer, scope, nodeToInject); + } + else { + writer.newNode(node.key, node.arg.reference - 0x100); + copyChildren(writer, scope, node); + writer.closeNode(); + } + break; case SyntaxKey::TemplateParameter: if (node.arg.reference < 0x100) { SyntaxNode nodeToInject = scope.parameterValues.get(node.arg.reference); @@ -1925,6 +1998,16 @@ void TemplateProssesor :: copyClassMembers(SyntaxTreeWriter& writer, TemplateSco } } +void TemplateProssesor :: generateEnumTemplate(SyntaxTreeWriter& writer, TemplateScope& scope, SyntaxNode node) +{ + scope.enumIndex = 0; + for (auto it = scope.parameterValues.start(); !it.eof(); ++it) { + scope.enumIndex++; + + copyClassMembers(writer, scope, node); + } +} + void TemplateProssesor :: generate(SyntaxTreeWriter& writer, TemplateScope& scope, MemoryBase* templateSection) { SyntaxTree templateTree; @@ -1941,6 +2024,9 @@ void TemplateProssesor :: generate(SyntaxTreeWriter& writer, TemplateScope& scop case Type::Class: copyClassMembers(writer, scope, root); break; + case Type::Enumeration: + generateEnumTemplate(writer, scope, root); + break; case Type::ExpressionTemplate: copyChildren(writer, scope, root.findChild(SyntaxKey::ReturnExpression)); break; @@ -1982,7 +2068,7 @@ void TemplateProssesor :: importTemplate(Type type, MemoryBase* templateSection, bufferWriter.closeNode(); SyntaxTreeWriter targetWriter(target); - if (type == Type::Class || type == Type::InlineProperty) { + if (type == Type::Class || type == Type::InlineProperty || type == Type::Enumeration) { SyntaxNode current = bufferTree.readRoot().firstChild(); while (current != SyntaxKey::None) { if(current == SyntaxKey::Method) { @@ -2035,6 +2121,12 @@ void TemplateProssesor :: importExpressionTemplate(MemoryBase* templateSection, importTemplate(Type::ExpressionTemplate, templateSection, target, &arguments, ¶meters); } +void TemplateProssesor :: importEnumTemplate(MemoryBase* templateSection, + SyntaxNode target, List& arguments, List& parameters) +{ + importTemplate(Type::Enumeration, 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 c07811c7d..c2c45de98 100644 --- a/elenasrc3/elc/derivation.h +++ b/elenasrc3/elc/derivation.h @@ -27,6 +27,7 @@ namespace elena_lang PropertyTemplate, ExtensionTemplate, ExpressionTemplate, + Enumeration }; struct Scope @@ -39,12 +40,16 @@ namespace elena_lang bool withTypeParameters() const { - return type == ScopeType::ClassTemplate || type == ScopeType::PropertyTemplate || type == ScopeType::ExtensionTemplate; + return type == ScopeType::ClassTemplate || type == ScopeType::PropertyTemplate || type == ScopeType::ExtensionTemplate || type == ScopeType::Enumeration; } bool withNameParameters() const { return type == ScopeType::PropertyTemplate; } + bool withEnumParameter() const + { + return type == ScopeType::Enumeration; + } bool isParameter(SyntaxNode node, SyntaxKey& parameterKey, ref_t& parameterIndex, bool allowType) { @@ -93,6 +98,17 @@ namespace elena_lang } } return false; + case ScopeType::Enumeration: + { + ref_t index = parameters.get(node.identifier()); + if (index > 0) { + parameterKey = SyntaxKey::EnumArgParameter; + parameterIndex = index + nestedLevel; + + return true; + } + return false; + } default: return false; } @@ -161,6 +177,7 @@ namespace elena_lang void flushStatement(SyntaxTreeWriter& writer, Scope& scope, SyntaxNode node); void flushMethodCode(SyntaxTreeWriter& writer, Scope& scope, SyntaxNode node); void flushTupleType(SyntaxTreeWriter& writer, Scope& scope, SyntaxNode node, ref_t& previusCategory); + void flushEnumTemplate(SyntaxTreeWriter& writer, Scope& scope, SyntaxNode node); void copyHeader(SyntaxTreeWriter& writer, Scope& scope, SyntaxNode node, bool includeType); void copyType(SyntaxTreeWriter& writer, Scope& scope, SyntaxNode node); @@ -251,7 +268,8 @@ namespace elena_lang CodeTemplate, Class, InlineProperty, - ExpressionTemplate + ExpressionTemplate, + Enumeration }; typedef Map NodeMap; @@ -263,12 +281,13 @@ namespace elena_lang NodeMap parameterValues; ModuleScopeBase* moduleScope; ref_t targetRef; + int enumIndex; TemplateScope() : type(Type::None), argValues({}), parameterValues({}), - moduleScope(nullptr), targetRef(0) + moduleScope(nullptr), targetRef(0), enumIndex(0) { } TemplateScope(Type type, ModuleScopeBase* scope, ref_t targetRef) : @@ -276,7 +295,8 @@ namespace elena_lang argValues({}), parameterValues({}), moduleScope(scope), - targetRef(targetRef) + targetRef(targetRef), + enumIndex(0) { } }; @@ -291,9 +311,12 @@ namespace elena_lang void copyParent(SyntaxTreeWriter& writer, TemplateScope& scope, SyntaxNode node); void copyClassMembers(SyntaxTreeWriter& writer, TemplateScope& scope, SyntaxNode node); void copyTemplatePostfix(SyntaxTreeWriter& writer, TemplateScope& scope, SyntaxNode node); + void copyKVKey(SyntaxTreeWriter& writer, TemplateScope& scope, SyntaxNode node); void copyModuleInfo(SyntaxTreeWriter& writer, SyntaxNode rootNode, TemplateScope& scope); + void generateEnumTemplate(SyntaxTreeWriter& writer, TemplateScope& scope, SyntaxNode node); + void generate(SyntaxTreeWriter& writer, TemplateScope& scope, MemoryBase* templateSection); void generateTemplate(SyntaxTreeWriter& writer, TemplateScope& scope, @@ -310,6 +333,8 @@ namespace elena_lang SyntaxNode target, List& arguments, List& parameters); void importExpressionTemplate(MemoryBase* templateSection, SyntaxNode target, List& arguments, List& parameters); + void importEnumTemplate(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/elena-tests/bt_optimization.cpp b/elenasrc3/elena-tests/bt_optimization.cpp index f575b4e5b..42bd8c6c0 100644 --- a/elenasrc3/elena-tests/bt_optimization.cpp +++ b/elenasrc3/elena-tests/bt_optimization.cpp @@ -33,8 +33,6 @@ 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_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\" ())))))"; @@ -46,8 +44,6 @@ constexpr auto S1_DirectCall_2 = "class (attribute -2147479546 ()nameattr (ident 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_Func = "class (attribute -2147467263 ()attribute -2147479545 ()nameattr (identifier \"Func\" ())method (attribute -2147471358 ()nameattr (identifier \"function\" ())no_body ()))"; @@ -66,8 +62,6 @@ 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 ()"; @@ -93,8 +87,6 @@ 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 ()"; @@ -302,31 +294,6 @@ void BTOptimization2 :: SetUp() BuildTreeSerializer::load(OptimizedBuildTree2, afterOptimization); } -// --- ScenarioTest --- - -SyntaxNode ScenarioTest :: findTargetNode() -{ - return findClassNode().findChild(SyntaxKey::Method); -} - -SyntaxNode ScenarioTest :: findClassNode() -{ - return SyntaxTree::gotoChild(declarationNode.firstChild(), SyntaxKey::Class, targetRef); -} - -void ScenarioTest :: 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); -} - // --- StructAlignment --- void StructAlignment :: SetUp() @@ -398,68 +365,6 @@ void PrimitiveStructAlignment:: SetUp() expectedSize = 2; } -// --- DispatchTest --- - -void DispatchTest :: SetUp() -{ - ScenarioTest::SetUp(); -} - -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); - 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() @@ -469,7 +374,7 @@ SyntaxNode VariadicRuntimeSingleDispatch :: findTargetNode() void VariadicRuntimeSingleDispatch :: SetUp() { - DispatchTest::SetUp(); + MethodScenarioTest::SetUp(); LoadDeclarationScenario(S_DefaultNamespace_1, S1_VariadicTemplates, S1_VariadicSingleDispatch_1, S_IntNumber); @@ -486,7 +391,7 @@ void VariadicRuntimeSingleDispatch :: SetUp() void VariadicCompiletimeSingleDispatch :: SetUp() { - DispatchTest::SetUp(); + MethodScenarioTest::SetUp(); LoadDeclarationScenario(S_DefaultNamespace_1, S1_VariadicTemplates, S1_VariadicSingleDispatch_1, S_IntNumber, S1_VariadicSingleDispatch_2); @@ -503,7 +408,7 @@ void VariadicCompiletimeSingleDispatch :: SetUp() void VariadicCompiletimeSingleDispatch_WithDifferentArgs :: SetUp() { - DispatchTest::SetUp(); + MethodScenarioTest::SetUp(); LoadDeclarationScenario(S_DefaultNamespace_1, S1_VariadicTemplates, S1_VariadicSingleDispatch_3b, S_IntNumber, S1_VariadicSingleDispatch_1, S1_VariadicSingleDispatch_3a); @@ -593,23 +498,6 @@ void CallVariadocMethodWithoutTarget :: SetUp() BuildTreeSerializer::load(BuildTree_CallVariadicMethodWithoutTarget, controlOutputNode); } -// --- VariadicCompiletimeConstructorSingleDispatch --- - -void VariadicCompiletimeConstructorSingleDispatch :: SetUp() -{ - DispatchTest::SetUp(); - - LoadDeclarationScenario(S_DefaultNamespace_1, S1_VariadicTemplates, S1_VariadicConstructorSingleDispatch_1, S_IntNumber); - - BuildTreeSerializer::load(BuildTree_VariadicSingleDispatch_3, controlOutputNode); - - argArrayRef = 0x80; - genericVargRef = 3; - targetVargRef = 4; - targetRef = 5; - intNumberRef = 7; -} - // --- LambdaTest --- BuildNode LambdaTest :: findOutput(BuildNode root) diff --git a/elenasrc3/elena-tests/bt_optimization.h b/elenasrc3/elena-tests/bt_optimization.h index d0808304c..c25302645 100644 --- a/elenasrc3/elena-tests/bt_optimization.h +++ b/elenasrc3/elena-tests/bt_optimization.h @@ -62,38 +62,6 @@ namespace elena_lang } }; - class ScenarioTest : public BaseFixture - { - protected: - BuildTree buildTree; - - BuildNode controlOutputNode; - - ref_t targetRef; - - virtual SyntaxNode findClassNode(); - virtual SyntaxNode findTargetNode(); - - void SetUp() override; - }; - - class DispatchTest : public ScenarioTest - { - protected: - ref_t genericVargRef; - ref_t targetVargRef; - - ref_t argArrayRef; - ref_t intNumberRef; - - SyntaxNode findAutoGenerated(SyntaxNode classNode); - - void SetUp() override; - - public: - void runTest(bool withProtectedConstructor = false); - }; - // Optimization #2 (byRefOp) : "a := b.get()" => "b.get(ref a)" class BTOptimization1_1 : public BTOptimization { @@ -150,7 +118,7 @@ namespace elena_lang void SetUp() override; }; - class VariadicRuntimeSingleDispatch : public DispatchTest + class VariadicRuntimeSingleDispatch : public MethodScenarioTest { protected: SyntaxNode findTargetNode() override; @@ -158,19 +126,13 @@ namespace elena_lang void SetUp() override; }; - class VariadicCompiletimeSingleDispatch : public DispatchTest - { - protected: - void SetUp() override; - }; - - class VariadicCompiletimeSingleDispatch_WithDifferentArgs : public DispatchTest + class VariadicCompiletimeSingleDispatch : public MethodScenarioTest { protected: void SetUp() override; }; - class VariadicCompiletimeConstructorSingleDispatch : public DispatchTest + class VariadicCompiletimeSingleDispatch_WithDifferentArgs : public MethodScenarioTest { protected: void SetUp() override; diff --git a/elenasrc3/elena-tests/compiler_tests.cpp b/elenasrc3/elena-tests/compiler_tests.cpp index 92f3cc6b9..5e80a9866 100644 --- a/elenasrc3/elena-tests/compiler_tests.cpp +++ b/elenasrc3/elena-tests/compiler_tests.cpp @@ -56,11 +56,6 @@ 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) { diff --git a/elenasrc3/elena-tests/constructor_tests.cpp b/elenasrc3/elena-tests/constructor_tests.cpp new file mode 100644 index 000000000..9e3e33f71 --- /dev/null +++ b/elenasrc3/elena-tests/constructor_tests.cpp @@ -0,0 +1,75 @@ +#include "pch.h" +// ------------------------------------------------ +#include "serializer.h" +#include "bcwriter.h" + +#include "constructor_tests.h" +#include "scenario_consts.h" + +using namespace elena_lang; + +// ==== Tests Scenarios === + +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 ()))"; + +constexpr auto S_PrivateConstructorTest = "class (nameattr (identifier \"X\" ())field (type (identifier \"IntNumber\" ())nameattr (identifier \"_value\" ()))method (attribute -2147467262 ()nameattr (identifier \"constructor\" ())code ())method (attribute -2147479548 ()nameattr (identifier \"load\" ())parameter (type (identifier \"IntNumber\" ())nameattr (identifier \"v\" ()))code (expression (assign_operation (object (identifier \"_value\" ())expression (object (identifier \"v\" ())))))))"; + +#ifdef _M_IX86 + +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_PrivateConstructorTest = "tape(open_frame() direct_call_op 800(type 6()) assigning 1 ()local -2 ()saving_stack()create_struct 4 (type 2()) copying_to_acc 2 (size 4 ()) assigning 2() local 2() saving_stack () local 1() field_assign () local 1() close_frame()exit())reserved 3 ())"; + +#elif _M_X64 + +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_PrivateConstructorTest = "tape(open_frame() direct_call_op 800(type 6()) assigning 1 ()local -2 ()saving_stack()create_struct 4 (type 2()) copying_to_acc 2 (size 4 ()) assigning 2() local 2() saving_stack () local 1() field_assign () local 1() close_frame()exit())reserved 4 ())"; + +#endif + +// --- VariadicCompiletimeConstructorSingleDispatch --- + +void VariadicCompiletimeConstructorSingleDispatch :: SetUp() +{ + MethodScenarioTest::SetUp(); + + LoadDeclarationScenario(S_DefaultNamespace_1, S1_VariadicTemplates, S1_VariadicConstructorSingleDispatch_1, S_IntNumber); + + BuildTreeSerializer::load(BuildTree_VariadicSingleDispatch_3, controlOutputNode); + + argArrayRef = 0x80; + genericVargRef = 3; + targetVargRef = 4; + targetRef = 5; + intNumberRef = 7; +} + +// --- CallPrivateConstructorDirectly --- + +void CallPrivateConstructorDirectly :: SetUp() +{ + MethodScenarioTest::SetUp(); + + LoadDeclarationScenario(S_DefaultNamespace_3, S_IntNumber, S_PrivateConstructorTest); + + BuildTreeSerializer::load(BuildTree_PrivateConstructorTest, controlOutputNode); + + intNumberRef = 2; + targetRef = 3; +} + +SyntaxNode CallPrivateConstructorDirectly :: findTargetNode() +{ + return findClassNode().findChild(SyntaxKey::Constructor).nextNode(); +} + +// ==== Tests === + +TEST_F(VariadicCompiletimeConstructorSingleDispatch, ConstructorTest) +{ + runTest(true); +} + +TEST_F(CallPrivateConstructorDirectly, ConstructorTest) +{ + runTest(false, true); +} diff --git a/elenasrc3/elena-tests/constructor_tests.h b/elenasrc3/elena-tests/constructor_tests.h new file mode 100644 index 000000000..37265a8eb --- /dev/null +++ b/elenasrc3/elena-tests/constructor_tests.h @@ -0,0 +1,30 @@ +//--------------------------------------------------------------------------- +// E L E N A P r o j e c t: ELENA Compiler +// +// This header contains ELENA Test Optimization Fixture declarations +// (C)2024, by Aleksey Rakov +//--------------------------------------------------------------------------- + +#ifndef CONSTRUCTOR_TESTS_H +#define CONSTRUCTOR_TESTS_H + +#include "tests_common.h" + +namespace elena_lang +{ + class VariadicCompiletimeConstructorSingleDispatch : public MethodScenarioTest + { + protected: + void SetUp() override; + }; + + class CallPrivateConstructorDirectly : public MethodScenarioTest + { + protected: + SyntaxNode findTargetNode() override; + + void SetUp() override; + }; +} + +#endif diff --git a/elenasrc3/elena-tests/elena-tests.vcxproj b/elenasrc3/elena-tests/elena-tests.vcxproj index e63128ac3..3ce4af8c8 100644 --- a/elenasrc3/elena-tests/elena-tests.vcxproj +++ b/elenasrc3/elena-tests/elena-tests.vcxproj @@ -134,6 +134,7 @@ + @@ -158,6 +159,7 @@ + diff --git a/elenasrc3/elena-tests/scenario_consts.h b/elenasrc3/elena-tests/scenario_consts.h index 509733c5f..60fe19a06 100644 --- a/elenasrc3/elena-tests/scenario_consts.h +++ b/elenasrc3/elena-tests/scenario_consts.h @@ -10,3 +10,7 @@ constexpr auto S_IntNumber = "class (attribute -2147467263 () attribute -2147475 // main program body constexpr auto S_NillableIntAssigning = "class (attribute -2147467263 ()nameattr (identifier \"program\" ())attribute -2147479546 ()method (attribute -2147479540 ()code (expression (assign_operation (object (nullable (type (identifier \"IntNumber\" ()))identifier \"n\" ())expression (object (identifier \"nil\" ()))))expression (assign_operation (object (nullable (type (identifier \"IntNumber\" ()))identifier \"m\" ())expression (object (integer \"2\" ())))))))"; constexpr auto S_IntAssigningNil = "class (attribute -2147467263 ()nameattr (identifier \"program\" ())attribute -2147479546 ()method (attribute -2147479540 ()code (expression (assign_operation (object (type (identifier \"IntNumber\" ())identifier \"m\" ())expression (object (identifier \"nil\" ())))))))"; + +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\" ())))"; + + diff --git a/elenasrc3/elena-tests/tests_common.cpp b/elenasrc3/elena-tests/tests_common.cpp index 1024f706d..e935c976f 100644 --- a/elenasrc3/elena-tests/tests_common.cpp +++ b/elenasrc3/elena-tests/tests_common.cpp @@ -219,6 +219,12 @@ bool TestTemplateProssesor :: importExpressionTemplate(ModuleScopeBase& moduleSc return false; } +bool TestTemplateProssesor :: importEnumTemplate(ModuleScopeBase& moduleScope, ref_t templateRef, + SyntaxNode target, List& arguments, List& parameters) +{ + return false; +} + // --- CompilerEnvironment --- CompilerEnvironment :: CompilerEnvironment() @@ -236,6 +242,7 @@ ModuleScopeBase* CompilerEnvironment :: createModuleScope(bool tapeOptMode, bool scope->attributes.add("public", V_PUBLIC); scope->attributes.add("var", V_VARIABLE); scope->attributes.add("new", V_NEWOP); + scope->attributes.add("constructor", V_CONSTRUCTOR); } return scope; @@ -366,3 +373,91 @@ void elena_lang::getAppPath(PathString& appPath) appPath.lower(); } +// --- ScenarioTest --- + +SyntaxNode ScenarioTest::findTargetNode() +{ + return findClassNode().findChild(SyntaxKey::Method); +} + +SyntaxNode ScenarioTest::findClassNode() +{ + return SyntaxTree::gotoChild(declarationNode.firstChild(), SyntaxKey::Class, targetRef); +} + +void ScenarioTest::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); +} + +// --- MethodScenarioTest --- + +void MethodScenarioTest :: runTest(bool withProtectedConstructor, bool withAttributes) +{ + // Arrange + ModuleScopeBase* moduleScope = env.createModuleScope(true, withAttributes); + 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::Method) { + methodHelper.compile(writer, methodNode); + } + else if (methodNode == SyntaxKey::Constructor) { + Compiler::ClassClass classClassHelper(classHelper); + classClassHelper.load(); + + methodHelper.compileConstructor(writer, methodNode, classClassHelper); + } + + // Assess + bool matched = BuildTree::compare(output.readRoot(), controlOutputNode, true); + EXPECT_TRUE(matched); + + freeobj(compiler); + freeobj(moduleScope); +} + +SyntaxNode MethodScenarioTest :: 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 {}; +} diff --git a/elenasrc3/elena-tests/tests_common.h b/elenasrc3/elena-tests/tests_common.h index 28bd67c8e..7d72bac74 100644 --- a/elenasrc3/elena-tests/tests_common.h +++ b/elenasrc3/elena-tests/tests_common.h @@ -166,6 +166,8 @@ namespace elena_lang List& arguments, List& parameters) override; bool importExpressionTemplate(ModuleScopeBase& moduleScope, ref_t templateRef, SyntaxNode target, List& arguments, List& parameters) override; + bool importEnumTemplate(ModuleScopeBase& moduleScope, ref_t templateRef, + SyntaxNode target, List& arguments, List& parameters) override; static TemplateProssesorBase* getInstance(Map, ref_t>* mapping = nullptr) { @@ -215,6 +217,37 @@ namespace elena_lang CompilerEnvironment env; }; + // --- ScenarioTest --- + class ScenarioTest : public BaseFixture + { + protected: + BuildTree buildTree; + + BuildNode controlOutputNode; + + ref_t targetRef; + + virtual SyntaxNode findClassNode(); + virtual SyntaxNode findTargetNode(); + + void SetUp() override; + }; + + // --- MethodScenarioTest --- + class MethodScenarioTest : public ScenarioTest + { + protected: + ref_t genericVargRef; + ref_t targetVargRef; + ref_t argArrayRef; + ref_t intNumberRef; + + SyntaxNode findAutoGenerated(SyntaxNode classNode); + + public: + void runTest(bool withProtectedConstructor = false, bool withAttributes = false); + }; + void getAppPath(PathString& appPath); } diff --git a/elenasrc3/elenart/linux/main.cpp b/elenasrc3/elenart/linux/main.cpp index 63a069365..28af2e6ab 100644 --- a/elenasrc3/elenart/linux/main.cpp +++ b/elenasrc3/elenart/linux/main.cpp @@ -131,6 +131,10 @@ mssg_t LoadMessageLA(const char* messageName) /// a reference to dynamically created VMT void* InjectProxyTypeLA(void* target, void* type, int staticLength, int nameIndex) { +#ifdef DEBUG_OUTPUT + printf("InjectProxyTypeLA %llx %llx %x %x\n", (long long)target, (long long)type, staticLength, nameIndex); +#endif + return (void*)machine->injectType(systemEnv, target, type, staticLength, nameIndex); } diff --git a/elenasrc3/elenart/vs/elenart.vcxproj b/elenasrc3/elenart/vs/elenart.vcxproj index 16837c118..6d79150aa 100644 --- a/elenasrc3/elenart/vs/elenart.vcxproj +++ b/elenasrc3/elenart/vs/elenart.vcxproj @@ -134,7 +134,7 @@ - Level3 + Level4 true _DEBUG;RT_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) true diff --git a/elenasrc3/elenasrc3.sln b/elenasrc3/elenasrc3.sln index 3832e939c..8914e77f0 100644 --- a/elenasrc3/elenasrc3.sln +++ b/elenasrc3/elenasrc3.sln @@ -34,6 +34,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "elt", "tools\elt\vs\elt.vcx EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "elena-tests", "elena-tests\elena-tests.vcxproj", "{89A68A7E-1CB6-45CB-9B02-8183FF59284A}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ldbg", "ldbg\vs\ldbg.vcxproj", "{60FE12CF-0DA9-4266-9C0F-F544DB115020}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 @@ -138,6 +140,14 @@ Global {89A68A7E-1CB6-45CB-9B02-8183FF59284A}.Release|x64.Build.0 = Release|x64 {89A68A7E-1CB6-45CB-9B02-8183FF59284A}.Release|x86.ActiveCfg = Release|Win32 {89A68A7E-1CB6-45CB-9B02-8183FF59284A}.Release|x86.Build.0 = Release|Win32 + {60FE12CF-0DA9-4266-9C0F-F544DB115020}.Debug|x64.ActiveCfg = Debug|x64 + {60FE12CF-0DA9-4266-9C0F-F544DB115020}.Debug|x64.Build.0 = Debug|x64 + {60FE12CF-0DA9-4266-9C0F-F544DB115020}.Debug|x86.ActiveCfg = Debug|Win32 + {60FE12CF-0DA9-4266-9C0F-F544DB115020}.Debug|x86.Build.0 = Debug|Win32 + {60FE12CF-0DA9-4266-9C0F-F544DB115020}.Release|x64.ActiveCfg = Release|x64 + {60FE12CF-0DA9-4266-9C0F-F544DB115020}.Release|x64.Build.0 = Release|x64 + {60FE12CF-0DA9-4266-9C0F-F544DB115020}.Release|x86.ActiveCfg = Release|Win32 + {60FE12CF-0DA9-4266-9C0F-F544DB115020}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/elenasrc3/engine/buildtree.h b/elenasrc3/engine/buildtree.h index a70092f30..25d68d34f 100644 --- a/elenasrc3/engine/buildtree.h +++ b/elenasrc3/engine/buildtree.h @@ -367,6 +367,7 @@ namespace elena_lang map.add("going_to_eop", BuildKey::goingToEOP); map.add("field", BuildKey::Field); map.add("nil", BuildKey::NilReference); + map.add("field_assign", BuildKey::FieldAssigning); map.add("value", BuildKey::Value); map.add("tape", BuildKey::Tape); diff --git a/elenasrc3/engine/elenaconst.h b/elenasrc3/engine/elenaconst.h index bf216b05c..5540975c2 100644 --- a/elenasrc3/engine/elenaconst.h +++ b/elenasrc3/engine/elenaconst.h @@ -13,7 +13,7 @@ namespace elena_lang { // --- Common ELENA Engine constants --- #define ENGINE_MAJOR_VERSION 6 // ELENA Engine version - #define ENGINE_MINOR_VERSION 1 + #define ENGINE_MINOR_VERSION 2 constexpr auto LINE_LEN = 0x1000; // the maximal source line length constexpr auto IDENTIFIER_LEN = 0x0300; // the maximal identifier length @@ -56,6 +56,7 @@ namespace elena_lang constexpr auto PACKAGE_SECTION = "#package"; constexpr auto WEAK_POSTFIX = "#weak"; + constexpr auto ENUM_POSTFIX = "#enum"; constexpr auto NAMESPACE_REF = "$namespace"; diff --git a/elenasrc3/engine/gcroutines.cpp b/elenasrc3/engine/gcroutines.cpp index 7d3655fa6..396e07418 100644 --- a/elenasrc3/engine/gcroutines.cpp +++ b/elenasrc3/engine/gcroutines.cpp @@ -302,8 +302,6 @@ inline void FixObject(GCTable* table, GCRoot* roots, size_t start, size_t end) // ; check if it valid reference if (*ptr >= start && *ptr < end) { - uintptr_t t = *ptr; - ObjectPage* pagePtr = getObjectPage(*ptr); uintptr_t mappings = table->gc_header + (((uintptr_t)pagePtr - table->gc_start) >> page_size_order_minus2); @@ -468,7 +466,6 @@ void* SystemRoutineProvider :: GCRoutine(GCTable* table, GCRoot* roots, size_t s if (size == INVALID_SIZE) return nullptr; - uintptr_t allocated = table->gc_yg_current; if (table->gc_yg_end - table->gc_yg_current < size) { // ; try to allocate in the mg while (table->gc_end - table->gc_mg_current < size) { diff --git a/elenasrc3/engine/langcommon.h b/elenasrc3/engine/langcommon.h index 9846035ef..fa72f95cc 100644 --- a/elenasrc3/engine/langcommon.h +++ b/elenasrc3/engine/langcommon.h @@ -233,6 +233,7 @@ namespace elena_lang constexpr auto V_VARIABLE = 0x8000100Du; constexpr auto V_MEMBER = 0x8000100Eu; constexpr auto V_STATIC = 0x8000100Fu; + constexpr auto V_ENUMERATION = 0x80001010u; constexpr auto V_CONVERSION = 0x80001011u; constexpr auto V_NEWOP = 0x80001012u; constexpr auto V_DISPATCHER = 0x80001013u; @@ -305,6 +306,7 @@ namespace elena_lang constexpr auto V_UINT16 = 0x80000022u; constexpr auto V_NILLABLE = 0x80000023u; constexpr auto V_FLOAT64ARRAY = 0x80000024u; + constexpr auto V_GETTER = 0x80000025u; /// built-in variables constexpr auto V_SELF_VAR = 0x80000081u; diff --git a/elenasrc3/engine/syntaxtree.cpp b/elenasrc3/engine/syntaxtree.cpp index ab7fb39d8..78472f124 100644 --- a/elenasrc3/engine/syntaxtree.cpp +++ b/elenasrc3/engine/syntaxtree.cpp @@ -43,6 +43,7 @@ void SyntaxTree :: loadTokens(TokenMap& map) map.add("message_operation", SyntaxKey::MessageOperation); map.add("property_operation", SyntaxKey::PropertyOperation); map.add("value_operation", SyntaxKey::ValueOperation); + map.add("keyvalue_expression", SyntaxKey::KeyValueExpression); map.add("equal_operation", SyntaxKey::EqualOperation); map.add("notequal_operation", SyntaxKey::NotEqualOperation); diff --git a/elenasrc3/engine/syntaxtree.h b/elenasrc3/engine/syntaxtree.h index a01f9af24..2754b7993 100644 --- a/elenasrc3/engine/syntaxtree.h +++ b/elenasrc3/engine/syntaxtree.h @@ -118,11 +118,16 @@ namespace elena_lang TupleAssignOperation = 0x001866, ContinueOperation = 0x001867, YieldOperation = 0x001868, + ExprValOperation = 0x001869, + Postfix = 0x001069, + TemplatePostfix = 0x00106A, ReferOperation = 0x00186B, IncOperation = 0x00186C, DecOperation = 0x00186D, + SizeOperation = 0x00186E, + EnumPostfix = 0x00106F, TemplateArg = 0x001070, Dimension = 0x001471, NestedBlock = 0x001080, @@ -142,6 +147,7 @@ namespace elena_lang TemplateOperation = 0x00189C, LTExpression = 0x00189D, TemplateExpression = 0x0018A0, + KeyValueExpression = 0x0018A1, FieldInitializer = 0x0018B0, Message = 0x0010C0, MessageOperation = 0x0018C1, @@ -196,6 +202,8 @@ namespace elena_lang NameArgParameter = 0x000110, FillingAttr = 0x000111, ProxyDispatcher = 0x000112, + EnumNameArgParameter = 0x000113, + EnumArgParameter = 0x000114, Column = 0x000201, Row = 0x000202, diff --git a/elenasrc3/engine/windows/winroutines.cpp b/elenasrc3/engine/windows/winroutines.cpp index 552f7ac3f..ff2de46cc 100644 --- a/elenasrc3/engine/windows/winroutines.cpp +++ b/elenasrc3/engine/windows/winroutines.cpp @@ -172,6 +172,9 @@ LONG WINAPI ELENAVectoredHandler(struct _EXCEPTION_POINTERS* ExceptionInfo) ExceptionInfo->ContextRecord->Rip = CriticalHandler; return EXCEPTION_CONTINUE_EXECUTION; + case 0x000006ba: + // !! HOTFIX : temporally ignore + return EXCEPTION_CONTINUE_SEARCH; default: ExceptionInfo->ContextRecord->Rdx = ExceptionInfo->ContextRecord->Rip; ExceptionInfo->ContextRecord->Rax = ELENA_ERR_CRITICAL; diff --git a/elenasrc3/ldbg/ldbg_const.h b/elenasrc3/ldbg/ldbg_const.h new file mode 100644 index 000000000..eb7fd79e5 --- /dev/null +++ b/elenasrc3/ldbg/ldbg_const.h @@ -0,0 +1 @@ +#define LDBG_REVISION_NUMBER 0x0001 diff --git a/elenasrc3/ldbg/ldbg_session.cpp b/elenasrc3/ldbg/ldbg_session.cpp new file mode 100644 index 000000000..615e0adc1 --- /dev/null +++ b/elenasrc3/ldbg/ldbg_session.cpp @@ -0,0 +1,29 @@ +//--------------------------------------------------------------------------- +// E L E N A P r o j e c t: ELENA command-Line Debugger Adapter +// +// This file contains DPA Session wrapper implementation +// +// (C)2024, by Aleksey Rakov +//--------------------------------------------------------------------------- + +#include "ldbg_session.h" +#include "common.h" + +using namespace elena_lang; + +// --- DPASessionWrapper --- + +DPASessionWrapper :: DPASessionWrapper() +{ + +} + +DPASessionWrapper :: ~DPASessionWrapper() +{ + freeobj(_session); +} + +void DPASessionWrapper :: prepare() +{ + _session = new dpa::Session(); +} \ No newline at end of file diff --git a/elenasrc3/ldbg/ldbg_session.h b/elenasrc3/ldbg/ldbg_session.h new file mode 100644 index 000000000..2ee7e0fe2 --- /dev/null +++ b/elenasrc3/ldbg/ldbg_session.h @@ -0,0 +1,28 @@ +//--------------------------------------------------------------------------- +// E L E N A P r o j e c t: ELENA command-Line Debugger Adapter +// +// This file contains DPA Session wrapper declaration +// +// (C)2024, by Aleksey Rakov +//--------------------------------------------------------------------------- + +#ifndef LDBG_SESSION_H +#define LDBG_SESSION_H + +#include "dpa_session.h" + +namespace elena_lang +{ + class DPASessionWrapper + { + dpa::Session* _session; + + public: + void prepare(); + + DPASessionWrapper(); + virtual ~DPASessionWrapper(); + }; +} + +#endif \ No newline at end of file diff --git a/elenasrc3/ldbg/vs/Resource.rc b/elenasrc3/ldbg/vs/Resource.rc new file mode 100644 index 000000000..fcf4fce29 --- /dev/null +++ b/elenasrc3/ldbg/vs/Resource.rc @@ -0,0 +1,60 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) +LANGUAGE 7, 1 + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION ENGINE_MAJOR_VERSION,ENGINE_MINOR_VERSION,LDBG_REVISION_NUMBER,0 + PRODUCTVERSION ENGINE_MAJOR_VERSION,ENGINE_MINOR_VERSION,0,0 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x0L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040004b0" + BEGIN + VALUE "CompanyName", "ELENA Programming Language by Alex Rakov" + VALUE "FileDescription", "ELENA debugger adapter" + VALUE "FileVersion", VER_FILE_VERSION_STR "\0" + VALUE "InternalName", "TODO: " + VALUE "LegalCopyright", "Copyright (C) 2024" + VALUE "OriginalFilename", "elc" + VALUE "ProductName", "ELENA Programming Language" + VALUE "ProductVersion", VER_PRODUCT_VERSION_STR "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x400, 1200 + END +END + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// diff --git a/elenasrc3/ldbg/vs/ldbg.vcxproj b/elenasrc3/ldbg/vs/ldbg.vcxproj new file mode 100644 index 000000000..59c821d92 --- /dev/null +++ b/elenasrc3/ldbg/vs/ldbg.vcxproj @@ -0,0 +1,188 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + Win32Proj + {60FE12CF-0DA9-4266-9C0F-F544DB115020} + ConsoleApplication1 + 10.0 + + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + ..\..\..\bin\ + ..\..\temp\ldbg\ + elena-dpa + + + false + ..\..\..\bin\ + ..\..\temp\ldbg\ + elena-dpa + + + true + ..\..\..\bin\ + ..\..\temp\ldbg64\ + elena64-dpa + + + false + ..\..\..\bin\ + ..\..\temp\ldbg64\ + elena64-dpa + + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + true + ..\..\common;..\..\engine;..\..\dpa;..\windows;..;%(AdditionalIncludeDirectories) + + + Console + true + + + ..;..\..\engine + + + + + Level3 + true + true + true + WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + true + ..\..\common;..\..\engine;..\..\dpa;..\windows;..;%(AdditionalIncludeDirectories) + + + Console + true + true + true + + + ..;..\..\engine + + + + + Level3 + true + _DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + true + ..\..\common;..\..\engine;..\..\dpa;..\windows;..;%(AdditionalIncludeDirectories) + + + Console + true + + + ..;..\..\engine + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + true + ..\..\common;..\..\engine;..\..\dpa;..\windows;..;%(AdditionalIncludeDirectories) + + + Console + true + true + true + + + ..;..\..\engine + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/elenasrc3/ldbg/vs/resource.h b/elenasrc3/ldbg/vs/resource.h new file mode 100644 index 000000000..8dc044e92 --- /dev/null +++ b/elenasrc3/ldbg/vs/resource.h @@ -0,0 +1,29 @@ +#include "elenaconst.h" +#include "ldbg_const.h" + +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by Resource.rc + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif + +#define STRINGIZE2(s) #s +#define STRINGIZE(s) STRINGIZE2(s) + +#define VER_FILE_VERSION_STR STRINGIZE(ENGINE_MAJOR_VERSION) \ + "." STRINGIZE(ENGINE_MINOR_VERSION) \ + "." STRINGIZE(LDBG_REVISION_NUMBER) \ + ".0" + +#define VER_PRODUCT_VERSION_STR STRINGIZE(ENGINE_MAJOR_VERSION) \ + "." STRINGIZE(ENGINE_MINOR_VERSION) \ + ".0.0" diff --git a/elenasrc3/ldbg/windows/ldbg.cpp b/elenasrc3/ldbg/windows/ldbg.cpp new file mode 100644 index 000000000..1f1338861 --- /dev/null +++ b/elenasrc3/ldbg/windows/ldbg.cpp @@ -0,0 +1,21 @@ +//--------------------------------------------------------------------------- +// E L E N A P r o j e c t: ELENA command-Line Debugger Adapter +// +// This file contains the main body of the win32 / win64 +// ELENA Debugger Adapter +// +// (C)2024, by Aleksey Rakov +//--------------------------------------------------------------------------- + +#include "ldbg_session.h" + +using namespace elena_lang; + +int main() +{ + DPASessionWrapper session; + + session.prepare(); + + return 0; +} \ No newline at end of file diff --git a/src60/core/system.core_routines.esm b/src60/core/system.core_routines.esm index 8a895b0e1..2e822b48a 100644 --- a/src60/core/system.core_routines.esm +++ b/src60/core/system.core_routines.esm @@ -1644,6 +1644,16 @@ procedure __perm_array_set end +procedure __perm_array_clear + + peek sp:1 + load + set nil + swap sp:0 + xassign + +end + procedure __perm_array_refer (self,index,retVal) xflush sp:0 diff --git a/src60/forms/win32_controls.l b/src60/forms/win32_controls.l index 0ef5915f9..62ba37781 100644 --- a/src60/forms/win32_controls.l +++ b/src60/forms/win32_controls.l @@ -501,7 +501,9 @@ class PaintboxListener : WindowCallback { _owner.destroy(); - super.onWMDestoy(hwnd) + super.onWMDestoy(hwnd); + + PermVectorTable.release(self); } } @@ -765,6 +767,13 @@ class PanelListener : WindowCallback { _owner.resize(control, width, height); } + + onWMDestoy(Handle hwnd) + { + super.onWMDestoy(hwnd); + + PermVectorTable.release(self); + } } public sealed class Panel : BasePanel, interface @@ -819,6 +828,13 @@ class RadioButtonGroupListener : WindowCallback _owner := owner } + onWMDestoy(Handle hwnd) + { + super.onWMDestoy(hwnd); + + PermVectorTable.release(self); + } + onClick(Handle control) { _owner.onClick(control); diff --git a/src60/forms/win_forms.l b/src60/forms/win_forms.l index b02b62e12..32c39766a 100644 --- a/src60/forms/win_forms.l +++ b/src60/forms/win_forms.l @@ -43,7 +43,7 @@ class SDIWindowListener : SDIWindowCallback { super.onWMDestoy(hwnd); - //TODO : free PermVectorTable entry to reuse it + PermVectorTable.release(self); } onSize(Handle control, int width, int height) @@ -142,7 +142,7 @@ class ChildWindowListener : ChildWindowCallback { super.onWMDestoy(hwnd); - //TODO : free PermVectorTable entry to reuse it + PermVectorTable.release(self); } onSize(Handle control, int width, int height) diff --git a/src60/system/app.l b/src60/system/app.l index f33306b35..c9f4157c7 100644 --- a/src60/system/app.l +++ b/src60/system/app.l @@ -32,7 +32,7 @@ entry() function(AbortException e) { } - + function(Exception err) { startUpEvents.handlingError(err); diff --git a/src60/system/attributes/attributes.l b/src60/system/attributes/attributes.l index 100178acf..eed31c2f0 100644 --- a/src60/system/attributes/attributes.l +++ b/src60/system/attributes/attributes.l @@ -46,6 +46,7 @@ #let attributes["var"] := 8000100Dh; #let attributes["this"] := 8000100Eh; #let attributes["static"] := 8000100Fh; +#let attributes["enumeration"] := 80001010h; #let attributes["cast"] := 80001011h; #let attributes["new"] := 80001012h; #let attributes["dispatch"] := 80001013h; diff --git a/src60/system/calendar/lnx64_datetime.l b/src60/system/calendar/lnx64_datetime.l index 1fec58575..d4e7a58d1 100644 --- a/src60/system/calendar/lnx64_datetime.l +++ b/src60/system/calendar/lnx64_datetime.l @@ -144,12 +144,12 @@ namespace calendar long tm_usec; - embeddable constructor(SystemTime time) + constructor(SystemTime time) { self.write(time) } - embeddable constructor() + constructor() { tm_isdst := -1 } diff --git a/src60/system/inline_templates.l b/src60/system/inline_templates.l index 2fff772f2..98d005b04 100644 --- a/src60/system/inline_templates.l +++ b/src60/system/inline_templates.l @@ -106,3 +106,83 @@ public weak interface embeddable dispatch() => self; }; } + +// --- enum --- + +public enumeration enum +{ + T _value; + + const T[] __enumValues; + const string[] __enumNames; + + this __enumValues += $value member; + this __enumNames += $name member; + + private constructor() {} + + private constructor load(T v) { _value := v } + + get static __typeof member() + = self.load($value member); + + T cast() + = _value; + + private static __typeof getEnumValue(int index) + { + T value := __enumValues[index]; + + ^ __typeof self.load(value) + } + + private static int getEnumCount() + { + int len := __enumValues.Length; + + ^ len + } + + static Enumerator enumerator() = new BaseEnumerator + { + this index := -1; + + this length := getEnumCount(); + + get Value() = getEnumValue(this index.Value); + + enumerable() = self; + + reset() + { + this index.Value := -1 + } + }; + + string toPrintable() + { + string[] names := __enumNames; + T[] values := __enumValues; + + int len := values.Length; + for (int i := 0; i < len; i++) { + if (values[i] == _value) { + ^ names[i] + } + }; + + InvalidOperationException.raise(); + + ^ string.MinValue + } + + bool equal(o) + { + if (o; is T n) + { + ^ _value == n + }; + + ^ false + } +} \ No newline at end of file diff --git a/src60/system/runtime/vectortable.l b/src60/system/runtime/vectortable.l index b76a92426..1f2631e43 100644 --- a/src60/system/runtime/vectortable.l +++ b/src60/system/runtime/vectortable.l @@ -16,6 +16,9 @@ class PermVectorArray setAt(int index, object obj) : external(system'core_routines'__perm_array_set); + removeAt(int index) + : external(system'core_routines'__perm_array_clear); + int Length { get() @@ -32,7 +35,8 @@ class PermVectorArray class PermVectorChain { - Reference Used : rprop; + Reference Free : rprop; + Reference Current : rprop; PermVectorArray Array : rprop; @@ -42,30 +46,66 @@ class PermVectorChain get bool isAvailable() { - int length := Array.Length; - int used := *Used; + int free := *Free; - ^ length > used; + ^ free > 0; } pointer allocate(object) { - int index := *Used; + int index := *Current; + while (Array[index] != nil) + index++; Array[index] := object; - Used.append(1); + Current.Value := index + 1; + + Free.reduce(1); Array.refer(index, out pointer ptr); ^ ptr; } + int indexOf(object) + { + int len := Array.Length; + for (int i := 0; i < len; i++) { + if (Array[i] != nil && object == Array[i]) { + ^ i + } + }; + + ^ -1 + } + + remove(int index) + { + Array.removeAt(index); + } + + bool rearrange() + { + int len := Array.Length; + int free := 0; + for (int i := 0; i < len; i++) { + if (Array[i] == nil) + free++; + }; + + Current.Value := 0; + Free.Value := free; + + ^ self.isAvailable; + } + constructor(PermVectorChain next) { - Array := self.createArray(); - Used := 0; - Next := next; + Array := self.createArray(); + Current := 0; + Free := Array.Length; + Next := next; } } @@ -73,6 +113,7 @@ class PermVectorChain public singleton PermVectorTable { + static PermVectorChain _firstChainItem; static PermVectorChain _chainItem; get private bool isAvailable() @@ -87,14 +128,57 @@ public singleton PermVectorTable ^ false; } + bool rearrange() + { + PermVectorChain previous := nil; + PermVectorChain current := _firstChainItem; + while (current != nil) { + if (current.rearrange()) { + _chainItem := current; + + ^ true + }; + + previous := current; + current := current.Next; + }; + + if (previous == nil) { + _firstChainItem := new PermVectorChain(previous); + _chainItem := _firstChainItem; + + ^ true + }; + _chainItem := previous; + + ^ false; + } + pointer allocate(object obj) { if (!self.isAvailable) { - _chainItem := new PermVectorChain(_chainItem); + ifnot (rearrange()) { + _chainItem := new PermVectorChain(_chainItem); + } }; pointer ptr := _chainItem.allocate(obj); ^ ptr; } + + release(object obj) + { + PermVectorChain current := _firstChainItem; + while (current != nil) { + int index := current.indexOf(obj); + if (index >= 0) { + current.remove(index); + + $break; + }; + + current := current.Next; + }; + } } \ No newline at end of file diff --git a/src60/system/system.prj b/src60/system/system.prj index f67eb866e..bc09433ee 100644 --- a/src60/system/system.prj +++ b/src60/system/system.prj @@ -16,7 +16,7 @@ ELENA Standard Library - 6.1.2 + 6.2.0 Aleksey Rakov diff --git a/src60/system/winforms/win_dialogs.l b/src60/system/winforms/win_dialogs.l index 189af5ffc..8cc369054 100644 --- a/src60/system/winforms/win_dialogs.l +++ b/src60/system/winforms/win_dialogs.l @@ -18,7 +18,7 @@ public singleton messageBox } } -packed tagOFNA +struct tagOFNA { int lStructSize : prop; Handle hwndOwner : prop; @@ -37,7 +37,7 @@ packed tagOFNA short nFileOffset : prop; short nFileExtension : prop; pointer lpstrDefExt : prop; - int lCustData : prop; + pointer lCustData : prop; pointer lpfnHook : prop; pointer lpTemplateName : prop; pointer pvReserved : prop; @@ -105,7 +105,7 @@ class BaseFileDialog internal prepare(tagOFNA struct, short[] filters, short[] fileName, int maxFile) { - struct.lStructSize := 88; + struct.lStructSize := $size struct; struct.hwndOwner := _parent.Handle; struct.hInstance := CurrentInstance.Handle; struct.lpstrFilter := filters; diff --git a/src60/system/winforms/win_windows.l b/src60/system/winforms/win_windows.l index 7ffa86021..0c4884ae1 100644 --- a/src60/system/winforms/win_windows.l +++ b/src60/system/winforms/win_windows.l @@ -71,8 +71,9 @@ public closed class WindowCallback onWMDestoy(Handle hwnd) { extern { + extern USER32.SetWindowLongW(hwnd, GWL_USERDATA, 0); extern USER32.DefWindowProcW(hwnd, WM_DESTROY, 0, 0); - } + }; } onWMPaint(Handle hwnd) diff --git a/tests60/sandbox/sandbox.l b/tests60/sandbox/sandbox.l index 4bc275b0c..5638b3fb5 100644 --- a/tests60/sandbox/sandbox.l +++ b/tests60/sandbox/sandbox.l @@ -1,32 +1,55 @@ -import extensions'scripting; -import system'dynamic'expressions; +import extensions; +import system'dynamic; -symbol used : preloaded = new object[]{Expression, DynamicSingleton,DynamicExpressionSymbol,SymbolCollection,LazySymbolExpression}; +interface IDecoratorA +{ + abstract giveMe(); +} + +class DecoratorBaseA : IDecoratorA +{ + field value; + + constructor(value) + { + this value := value + } + + giveMe() + = value; +} -test() +class DecoratorA { - var s := new system'dynamic'expressions'SymbolCollection ( - new system'dynamic'expressions'SymbolInfo ( - "program", - new system'dynamic'expressions'DynamicSingleton ( - new system'dynamic'expressions'ActionMethodExpression ( - new system'dynamic'expressions'CodeblockExpression ( - new system'dynamic'expressions'ExtensionOrMessageCallExpression ( - new system'dynamic'expressions'LazySymbolExpression ( - "system'console" - ), - "writeLine", - new system'dynamic'expressions'IntConstantExpression ( "2" ) ) ) ) ) ) ) ; - - s.safeEval() + object target; + object extra; + + constructor(target, extra) + { + this target := target; + this extra := extra; + } + + giveMe() + = target.giveMe() + extra; + + generic cast() + { + var type := __received.__getFirstSignatureMember(); + + var proxy := ::{ dispatch() => self; }; + proxy.__injectInferface(type); + + ^ __received(proxy); + } } public program() { -// var tape := lscript.eval("public program() { system'console.writeLine(2); }"); -// var program := tape.program; + var a := new DecoratorBaseA(2); + var decA := new DecoratorA(a, 3); - test(); + Assert.ifEqual((decA :as IDecoratorA).giveMe(), 5); -// program(); -} \ No newline at end of file + console.write("."); +} diff --git a/tests60/system_tests/basic.l b/tests60/system_tests/basic.l index 3886a3ac6..884b83223 100644 --- a/tests60/system_tests/basic.l +++ b/tests60/system_tests/basic.l @@ -946,9 +946,9 @@ public multySelectTest() : testCase() console.write(".") } -// --- enumTest --- +// --- stringEnumerationTest --- -public enumTest() : testCase() +public stringEnumerationTest() : testCase() { var s := String.MinValue; "123".forEach::(x) @@ -1999,3 +1999,20 @@ public ifNilOperatorTest() : testCase() Assert.ifNil(b?.Value); console.write("."); } + +// --- enumTest --- + +public const struct Color : enum(Red = 1,Green = 2,Blue = 3); + +public enumTest() : testCase() +{ + Color red := Color.Red; + Color green := Color.Green; + + Assert.ifTrue(red == Color.Red); + Assert.ifFalse(red == Color.Green); + Assert.ifEqual(red.toPrintable(), "Red"); + Assert.ifEqual(green.toPrintable(), "Green"); + + console.write("."); +}