From 77fda7dedfd5016897775604197ac9b345dc4f05 Mon Sep 17 00:00:00 2001 From: arakov Date: Tue, 4 Nov 2025 09:36:30 +0100 Subject: [PATCH 1/9] housekeeping - re-targeting actions --- .github/workflows/bsd.nightly.yml | 2 +- .github/workflows/lnx.nightly.yml | 2 +- .github/workflows/mac.nightly.yml | 2 +- .github/workflows/nightly.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/bsd.nightly.yml b/.github/workflows/bsd.nightly.yml index 8321f137a..a27724e8c 100644 --- a/.github/workflows/bsd.nightly.yml +++ b/.github/workflows/bsd.nightly.yml @@ -19,7 +19,7 @@ jobs: steps: - uses: actions/checkout@v4 with: - ref: iteration42 + ref: iteration43 - name: Run in FreeBSD id: nightly uses: vmactions/freebsd-vm@v1 diff --git a/.github/workflows/lnx.nightly.yml b/.github/workflows/lnx.nightly.yml index c6bf90d3a..fe7b8e3ea 100644 --- a/.github/workflows/lnx.nightly.yml +++ b/.github/workflows/lnx.nightly.yml @@ -24,7 +24,7 @@ jobs: steps: - uses: actions/checkout@v4 with: - ref: iteration42 + ref: iteration43 - name: Set version run: | diff --git a/.github/workflows/mac.nightly.yml b/.github/workflows/mac.nightly.yml index 9ca485e7b..8305983bf 100644 --- a/.github/workflows/mac.nightly.yml +++ b/.github/workflows/mac.nightly.yml @@ -22,7 +22,7 @@ jobs: steps: - uses: actions/checkout@v4 with: - ref: iteration42 + ref: iteration43 - name: Set version run: | diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index ef2433770..70f79b6f7 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -33,7 +33,7 @@ jobs: steps: - uses: actions/checkout@v4 with: - ref: iteration42 + ref: iteration43 - name: Add MSBuild to PATH uses: microsoft/setup-msbuild@v2 From de6da77d5f6614956780f83007c40a6c7a3f62f3 Mon Sep 17 00:00:00 2001 From: Aleksey Rakov Date: Fri, 23 Jan 2026 17:56:25 +0100 Subject: [PATCH 2/9] Iteration 43 (#837) * #820 : Launch elena64-ide.exe from the command line * working on const array support * support const T[] array declaration * #592 : allow to assign a constant array element inside the constructor * #351 : add readonly fields support description * storing constant array in rdata section when it is possible * [ADDED] both program and Program (preferred way) are supported as a program main entry * [CRITICAL][ADDED] program main entry is renamed from program to Program * supporting both program and Program * [ADDED] short-cut syntax for constant array * fixing xor operation * API : fixing __getProperties extension method * #592 : supporting constant symbols * adding AnsiEncoder * some refactoring rename toByteArray to saveToByteArray * [FIXED] retoverload method * [FIXED] calling indexed method for sealed stack-allocated method * fixing Truncate File sample * fixing an issue with ByIndex optimization * #34 : migrating to mbedtls 4.0.0 * working on async support; fixing an error with swallowing an exception * fixing an issue with reused generated templates * [FIXED] extension literal constant * [FIXED] #820 - Launch elena64-ide.exe from the command line * [ADDED] warning when passing an unsupported nullable argument * [ADDED] ecv: new flag - ignore internal classes * [ADDED] new compiler option : -n used to compile a sub collection * fixing UTF32 conversion * [FIXED] assigning a struct field in sub code * [FIXED] calling retoverload method in a returning expression * [ADDED] new unit test : calling retoverload method in a returning expression --- .gitignore | 4 + CHANGELOG.md | 26 +- VERSION | 2 +- bin/scripts/jscript60.es | 2 +- bin/scripts/multiline.elt | 2 +- bin/scripts/repl.elt | 2 +- bin/scripts/textgen_ln.elt | 2 +- bin/templates/lib60.cfg | 1 + bin/templates/lib60.config | 1 + bin/templates/lnx_console60.config | 2 +- bin/templates/local.lib60.config | 1 + bin/templates/local.mt_lnx_console60.config | 2 +- bin/templates/local.vm_lnx_console60.config | 2 +- bin/templates/mt_lnx_console60.config | 2 +- bin/templates/mt_win_console60.cfg | 2 +- bin/templates/vm_lnx_console60.config | 2 +- bin/templates/vm_win_console60.cfg | 2 +- bin/templates/win_console60.cfg | 2 +- bin/templates/win_gui60.cfg | 2 +- bin/templates/win_webapi60.cfg | 2 +- dat/og/bc_rules60.txt | 4 +- dat/sg/syntax67.txt | 8 +- doc/api/system-summary.html | 198 +++--- doc/api/system.html | 198 ++++++ doc/features | 65 ++ doc/todo.txt | 80 +-- elenasrc3/common/lists.h | 4 +- elenasrc3/common/paths.h | 4 + elenasrc3/elc/cli.cpp | 18 +- elenasrc3/elc/clicommon.h | 25 +- elenasrc3/elc/cliconst.h | 8 +- elenasrc3/elc/compiler.cpp | 653 ++++++++++++------ elenasrc3/elc/compiler.h | 26 +- elenasrc3/elc/compilerlogic.cpp | 260 ++++--- elenasrc3/elc/compilerlogic.h | 37 +- elenasrc3/elc/compiling.cpp | 2 +- elenasrc3/elc/errors.h | 2 + elenasrc3/elc/messages.h | 6 +- elenasrc3/elc/modulescope.cpp | 18 +- elenasrc3/elc/modulescope.h | 3 +- elenasrc3/elc/project.cpp | 11 +- elenasrc3/elc/project.h | 4 +- elenasrc3/elena-tests/bt_optimization.h | 13 + elenasrc3/elena-tests/compile_tests.h | 24 + elenasrc3/elena-tests/scenario_consts.h | 20 +- elenasrc3/elena-tests/tape_consts.h | 6 + elenasrc3/elena-tests/tests_bt.cpp | 8 + .../elena-tests/tests_bt_optimization.cpp | 57 +- elenasrc3/elena-tests/tests_build.cpp | 8 + elenasrc3/elena-tests/tests_common.cpp | 9 +- elenasrc3/elena-tests/tests_common.h | 6 +- elenasrc3/elena-tests/tests_compile.cpp | 137 +++- elenasrc3/elena-tests/tests_declaration.cpp | 4 +- elenasrc3/elenavm/elenavmmachine.cpp | 20 +- elenasrc3/elenavm/elenavmmachine.h | 11 +- elenasrc3/elenavm/vmcommon.h | 4 +- elenasrc3/elenavm/windows/dllmain.cpp | 4 +- elenasrc3/engine/buildtree.h | 4 + elenasrc3/engine/bytecode.cpp | 5 +- elenasrc3/engine/elena.h | 16 +- elenasrc3/engine/elenaconst.h | 20 +- elenasrc3/engine/jitcompiler.cpp | 18 +- elenasrc3/engine/langcommon.h | 27 +- elenasrc3/engine/libman.cpp | 40 ++ elenasrc3/engine/syntaxtree.cpp | 1 + elenasrc3/gui/text.cpp | 6 +- elenasrc3/ide/eng/messages.h | 4 +- elenasrc3/ide/idecontroller.cpp | 9 +- elenasrc3/ide/idecontroller.h | 2 + elenasrc3/ide/ideversion.h | 2 +- elenasrc3/ide/windows/main.cpp | 86 ++- elenasrc3/ide/windows/winide.cpp | 5 +- elenasrc3/tools/asmc/asmconst.h | 2 +- elenasrc3/tools/ecv/ecvconst.h | 6 +- elenasrc3/tools/ecv/ecviewer.cpp | 13 +- elenasrc3/tools/ecv/ecviewer.h | 4 +- elenasrc3/tools/ecv/windows/ecv.cpp | 2 +- examples60/console/binary/binary.l | 2 +- examples60/console/bsort/bsort.l | 2 +- examples60/console/collatz/collatz.l | 2 +- examples60/console/datetime/control.l | 2 +- .../console/datetime/datetime.linux.prj | 4 +- examples60/console/datetime/datetime.prj | 4 +- examples60/console/goods/goods.l | 2 +- examples60/console/helloworld/helloworld.l | 2 +- examples60/console/matrix/matrix.l | 2 +- examples60/console/matrix/matrix.prj | 4 +- examples60/console/pi/pi.l | 2 +- examples60/console/pi2/pi2.l | 2 +- examples60/console/random/random.l | 12 +- examples60/console/regex/regex.l | 2 +- examples60/console/regex/regex.prj | 4 +- examples60/console/replace/replace.l | 2 +- examples60/console/sum/sum.l | 2 +- examples60/console/trans/control.l | 4 +- examples60/console/trans/translit.linux.prj | 32 + examples60/console/words/words.l | 2 +- examples60/db/sqlite/main.l | 4 +- examples60/files/textdb/textdb.l | 2 +- examples60/files/textfile/textfile.l | 2 +- examples60/gui/agenda/form.l | 2 +- examples60/gui/c_a_g/calc_area_gui.l | 2 +- examples60/gui/helloworld/helloworld.l | 2 +- examples60/gui/helloworld/helloworld.xs | 6 +- examples60/net/chat/client_cui/main.l | 2 +- examples60/net/chat/server_cui/main.l | 2 +- examples60/net/httpget/httpget.l | 2 +- examples60/net/httpget/httpsget.l | 2 +- .../net/webapi/sampleapi1/Server/bootstrap.l | 2 +- .../webapi/sampleapi1/Server/sampleapi1.prj | 44 +- examples60/rosetta/accumulator/accumulator.l | 8 +- examples60/rosetta/ackermann/ackermann.l | 10 +- examples60/rosetta/addfield/addfield.l | 2 +- examples60/rosetta/amb/amb.l | 4 +- examples60/rosetta/anagram/anagram.l | 2 +- examples60/rosetta/anonymrec/anonymrec.l | 2 +- examples60/rosetta/aplusb/aplusb.l | 4 +- .../rosetta/applycallback/applycallback.l | 2 +- .../rosetta/arithmeticint/arithmeticint.l | 2 +- examples60/rosetta/arithmeval/arithmeval.l | 2 +- examples60/rosetta/arithmmean/arithmmean.l | 2 +- examples60/rosetta/arrayconcat/arrayconcat.l | 6 +- examples60/rosetta/arraymode/arraymode.l | 2 +- examples60/rosetta/arrays/arrays.l | 4 +- .../associativearrays/associativearrays.l | 2 +- examples60/rosetta/bestshuffle/bestshuffle.l | 2 +- examples60/rosetta/binary/binary.l | 2 +- examples60/rosetta/bitwise/bitwise.l | 2 +- examples60/rosetta/brackets/brackets.l | 2 +- examples60/rosetta/bullscows/bullscows.l | 2 +- examples60/rosetta/caesar/caesar.l | 2 +- examples60/rosetta/calendar/calendar.l | 6 +- examples60/rosetta/charmatch/charmatch.l | 2 +- .../rosetta/combinations/combinations.l | 2 +- examples60/rosetta/complist/complist.l | 2 +- examples60/rosetta/doors/doors.l | 2 +- examples60/rosetta/dynamic_var/dynamic_var.l | 2 +- .../rosetta/evolutionary/evolutionary.l | 4 +- examples60/rosetta/firstclass/firstclass.l | 2 +- examples60/rosetta/gameoflife/gameoflife.l | 2 +- examples60/rosetta/knutalg/knutalg.l | 6 +- .../rosetta/loop_multiple_arrays/loopma.l | 10 +- examples60/rosetta/manboy/manboy.l | 2 +- examples60/rosetta/median/median.l | 2 +- examples60/rosetta/ninetynine/ninetynine.l | 2 +- .../reverse_words_in_string/reverse_words.l | 2 +- examples60/rosetta/smavg/smavg.l | 2 +- .../rosetta/string_append/string_append.l | 2 +- examples60/rosetta/string_case/string_case.l | 2 +- .../string_comparison/string_comparision.l | 2 +- .../string_concatenation.l | 2 +- .../string_interpolation.l | 2 +- .../rosetta/string_matching/string_matching.l | 2 +- .../rosetta/string_prepend/string_prepend.l | 2 +- examples60/rosetta/tokenizer/tokenizer.l | 2 +- examples60/rosetta/toppergroup/toppergroup.l | 2 +- examples60/rosetta/treeview/treeview.l | 2 +- .../rosetta/trigonometric/trigonometric.l | 2 +- examples60/rosetta/truncprime/truncprime.l | 2 +- examples60/rosetta/twelvestats/twelvestats.l | 2 +- examples60/rosetta/twentyfour/twentyfour.l | 12 +- examples60/rosetta/wireworld/wireworld.l | 2 +- examples60/rosetta/ycombinator/ycombinator.l | 2 +- .../zeckendorf_arithm/zeckendorf_arithm.l | 96 ++- examples60/rosetta/zhangsuen/zhangsuen.l | 4 +- examples60/scripts/calc/calc.prj | 4 +- examples60/scripts/calc/control.l | 4 +- examples60/scripts/calc/parser.l | 2 +- examples60/scripts/interpreter/interpreter.l | 4 +- examples60/scripts/js/jsinterpreter.prj | 4 +- examples60/scripts/js/main.l | 2 +- examples60/scripts/ls/main.l | 2 +- examples60/scripts/ls/sample.ls | 2 +- examples60/scripts/ls/sample1.ls | 2 +- examples60/scripts/ls/sample2.ls | 10 +- examples60/scripts/ls/sample3.ls | 2 +- examples60/scripts/ls/sample4.ls | 2 +- examples60/threads/async/main.l | 2 +- examples60/threads/tasks/main.l | 2 +- examples60/threads/threadpool/threadpool.l | 2 +- scripts/aarch64/build_package_arm64.script | 2 +- scripts/aarch64/control | 2 +- scripts/amd64/control | 2 +- scripts/amd64/local_create_package.script | 2 +- scripts/bsd.amd64/local_create_package.script | 2 +- scripts/i386/control | 2 +- scripts/i386/local_create_package.script | 2 +- scripts/ppc64le/build_package_ppc64le.script | 2 +- scripts/ppc64le/control | 2 +- src60/cellular/rulesets.l | 2 +- src60/extensions/app.l | 2 +- src60/extensions/convertors.l | 2 +- src60/extensions/extensions.linux.prj | 2 +- src60/extensions/extensions.prj | 3 +- src60/extensions/random.l | 7 +- src60/extensions/scripting/lscript.l | 8 +- src60/extensions/text/encoding.l | 31 + src60/forms/win_forms.l | 2 +- src60/mbedtls/common.l | 30 +- src60/mbedtls/mbedtls.prj | 6 +- src60/mbedtls/mbedtlslistener.l | 4 +- src60/mbedtls/mbedtlssocket.l | 22 +- .../server/registration/registration.l | 6 +- src60/net/http/httpresponse.l | 4 +- src60/net/http/server/httpserver.l | 11 + src60/net/http/server/httpserverresponse.l | 7 +- src60/system/app.l | 6 +- src60/system/attributes/attributes.l | 6 +- src60/system/collections/list.l | 32 +- .../system/dynamic/expressions/expressions.l | 8 +- src60/system/dynamic/groups.l | 4 +- src60/system/dynamic/reflection.l | 2 +- src60/system/inline_templates.l | 4 +- src60/system/io/console.l | 2 +- src60/system/io/files.l | 11 +- src60/system/io/streamwriter.l | 2 +- src60/system/net/networkstream.l | 4 +- src60/system/operations/operations.l | 2 +- src60/system/primitives.l | 1 + src60/system/strings.l | 118 +++- src60/system/system.linux.prj | 2 +- src60/system/system.prj | 2 +- src60/system/template_tests.l | 1 + src60/system/text/base64.l | 6 +- src60/system/text/encoding.l | 3 +- src60/system/text/parsing/regex.l | 2 +- src60/system/text/textbuffer.l | 6 +- src60/system/winforms/win_app.l | 2 +- src60/system/winforms/win_dialogs.l | 2 +- src60/system/winforms/win_windows.l | 2 +- src60/textgen/extensions.l | 2 +- src60/textgen/parser.l | 2 +- src60/xforms/common.l | 41 ++ src60/xforms/xforms.prj | 3 +- src60/xml/xml.linux.prj | 2 +- src60/xml/xml.prj | 2 +- src60/xml/xmldoc.l | 2 +- tests60/api_tests/main.l | 2 +- tests60/async_tests/async_tests.prj | 23 + tests60/async_tests/basic.l | 41 ++ tests60/async_tests/main.l | 10 + tests60/sandbox/sandbox.l | 9 +- tests60/sandbox2/sandbox2.l | 2 +- tests60/script_tests/basic.l | 6 +- tests60/script_tests/main.l | 2 +- tests60/system_tests/basic.l | 25 + tests60/system_tests/main.l | 2 +- 247 files changed, 2262 insertions(+), 1079 deletions(-) create mode 100644 examples60/console/trans/translit.linux.prj create mode 100644 src60/extensions/text/encoding.l create mode 100644 src60/xforms/common.l create mode 100644 tests60/async_tests/async_tests.prj create mode 100644 tests60/async_tests/basic.l create mode 100644 tests60/async_tests/main.l diff --git a/.gitignore b/.gitignore index a4fea9493..dd6a7fae9 100644 --- a/.gitignore +++ b/.gitignore @@ -27,4 +27,8 @@ *.layout *.depend /elenasrc3/temp +/elenasrc3/engine/vs +/elenasrc3/lruntime/vs +/elenasrc3/ldebugger/vs +examples60/db/sqlite/bin .vs/ diff --git a/CHANGELOG.md b/CHANGELOG.md index 91b5c15e3..87bab3117 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,23 @@ +## ELENA 7.0.0 + +- ELENA + +- ELC + +- API + +- SM + +- Scripts + +- SAMPLES + +- IDE + +- Tools + +- Misc + ## ELENA 6.8.0 - ELENA @@ -50,12 +70,6 @@ - [ADDED] #35 : adding webapi module - [ADDED] UnsafeArray, UnsafeArray -- SM - -- Scripts - -- SAMPLES - - IDE - [FIXED] an issue with a vertical splitter - [FIXED] breakpoint must be inside the loop diff --git a/VERSION b/VERSION index 8a1c5c7e9..23863d3de 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -6.8.0 \ No newline at end of file +6.8.1 \ No newline at end of file diff --git a/bin/scripts/jscript60.es b/bin/scripts/jscript60.es index 33c63ece3..7d0c5feab 100644 --- a/bin/scripts/jscript60.es +++ b/bin/scripts/jscript60.es @@ -9,7 +9,7 @@ root ( public_namespace ( public_symbol ( - nameattr ( identifier = program ) + nameattr ( identifier = Program ) get_expression ( nested ( diff --git a/bin/scripts/multiline.elt b/bin/scripts/multiline.elt index 594a66e9b..b87cd8801 100644 --- a/bin/scripts/multiline.elt +++ b/bin/scripts/multiline.elt @@ -1 +1 @@ -public program() { $1 } +public Program() { $1 } diff --git a/bin/scripts/repl.elt b/bin/scripts/repl.elt index d263336c8..c9cde7c13 100644 --- a/bin/scripts/repl.elt +++ b/bin/scripts/repl.elt @@ -1,3 +1,3 @@ -public program() { +public Program() { system'Console.writeLine($1) } diff --git a/bin/scripts/textgen_ln.elt b/bin/scripts/textgen_ln.elt index 625bf6403..152aecadb 100644 --- a/bin/scripts/textgen_ln.elt +++ b/bin/scripts/textgen_ln.elt @@ -1,7 +1,7 @@ ///$output:=the output path ///$script:=the textgen script ///$target:= the multi-line text to be parsed -public program() { +public Program() { $1 var output := textgen'TextGen.parseAsLineSeparated($target, $script); diff --git a/bin/templates/lib60.cfg b/bin/templates/lib60.cfg index ae01c5668..344948821 100644 --- a/bin/templates/lib60.cfg +++ b/bin/templates/lib60.cfg @@ -42,6 +42,7 @@ system'BoolValue#false system'Reference#1 system'Array#1 + system'ConstArray#1 system'VariadicArray#1 system'Message system'MessageName diff --git a/bin/templates/lib60.config b/bin/templates/lib60.config index 6f2245a61..05237b35b 100644 --- a/bin/templates/lib60.config +++ b/bin/templates/lib60.config @@ -61,6 +61,7 @@ system'BoolValue#false system'Reference#1 system'Array#1 + system'ConstArray#1 system'VariadicArray#1 system'Message system'MessageName diff --git a/bin/templates/lnx_console60.config b/bin/templates/lnx_console60.config index 0cd186d8e..68f9d1421 100644 --- a/bin/templates/lnx_console60.config +++ b/bin/templates/lnx_console60.config @@ -49,6 +49,6 @@ system'core_routines'sta_start system'$private'entrySymbol - $rootnamespace'program + $rootnamespace'Program|program \ No newline at end of file diff --git a/bin/templates/local.lib60.config b/bin/templates/local.lib60.config index 177c9f440..0d4ba0fcb 100644 --- a/bin/templates/local.lib60.config +++ b/bin/templates/local.lib60.config @@ -61,6 +61,7 @@ system'BoolValue#false system'Reference#1 system'Array#1 + system'ConstArray#1 system'VariadicArray#1 system'Message system'MessageName diff --git a/bin/templates/local.mt_lnx_console60.config b/bin/templates/local.mt_lnx_console60.config index df8cfa25f..c80555170 100644 --- a/bin/templates/local.mt_lnx_console60.config +++ b/bin/templates/local.mt_lnx_console60.config @@ -17,6 +17,6 @@ system'core_routines'mta_start system'$private'entrySymbol - $rootnamespace'program + $rootnamespace'Program|program \ No newline at end of file diff --git a/bin/templates/local.vm_lnx_console60.config b/bin/templates/local.vm_lnx_console60.config index 5eb59dc50..b425db20d 100644 --- a/bin/templates/local.vm_lnx_console60.config +++ b/bin/templates/local.vm_lnx_console60.config @@ -33,6 +33,6 @@ system'core_routines'vm_sta_start system'$private'entrySymbol - $rootnamespace'program + $rootnamespace'Program|program \ No newline at end of file diff --git a/bin/templates/mt_lnx_console60.config b/bin/templates/mt_lnx_console60.config index 1b502caf8..d5b5d7f92 100644 --- a/bin/templates/mt_lnx_console60.config +++ b/bin/templates/mt_lnx_console60.config @@ -19,6 +19,6 @@ system'core_routines'mta_start system'$private'entrySymbol - $rootnamespace'program + $rootnamespace'Program|program \ No newline at end of file diff --git a/bin/templates/mt_win_console60.cfg b/bin/templates/mt_win_console60.cfg index 754ac9fed..8ba380309 100644 --- a/bin/templates/mt_win_console60.cfg +++ b/bin/templates/mt_win_console60.cfg @@ -27,6 +27,6 @@ system'core_routines'mta_start system'$private'entrySymbol - $rootnamespace'program + $rootnamespace'Program|program \ No newline at end of file diff --git a/bin/templates/vm_lnx_console60.config b/bin/templates/vm_lnx_console60.config index 5eb59dc50..b425db20d 100644 --- a/bin/templates/vm_lnx_console60.config +++ b/bin/templates/vm_lnx_console60.config @@ -33,6 +33,6 @@ system'core_routines'vm_sta_start system'$private'entrySymbol - $rootnamespace'program + $rootnamespace'Program|program \ No newline at end of file diff --git a/bin/templates/vm_win_console60.cfg b/bin/templates/vm_win_console60.cfg index 11f1fd761..fc005ef20 100644 --- a/bin/templates/vm_win_console60.cfg +++ b/bin/templates/vm_win_console60.cfg @@ -18,6 +18,6 @@ system'core_routines'vm_sta_start system'$private'entrySymbol - $rootnamespace'program + $rootnamespace'Program|program \ No newline at end of file diff --git a/bin/templates/win_console60.cfg b/bin/templates/win_console60.cfg index 674f8057c..c8440511d 100644 --- a/bin/templates/win_console60.cfg +++ b/bin/templates/win_console60.cfg @@ -23,6 +23,6 @@ system'core_routines'sta_start system'$private'entrySymbol - $rootnamespace'program + $rootnamespace'Program|program \ No newline at end of file diff --git a/bin/templates/win_gui60.cfg b/bin/templates/win_gui60.cfg index 79f0c6226..958087213 100644 --- a/bin/templates/win_gui60.cfg +++ b/bin/templates/win_gui60.cfg @@ -18,7 +18,7 @@ system'core_routines'sta_start system'$private'guiEntrySymbol - system'winforms'program + system'winforms'Program $rootnamespace'MainWindow \ No newline at end of file diff --git a/bin/templates/win_webapi60.cfg b/bin/templates/win_webapi60.cfg index f041a5d2d..c271599aa 100644 --- a/bin/templates/win_webapi60.cfg +++ b/bin/templates/win_webapi60.cfg @@ -3,6 +3,6 @@ - webapi'Program + webapi'Program \ No newline at end of file diff --git a/dat/og/bc_rules60.txt b/dat/og/bc_rules60.txt index f33e5d8a6..dd9e7dec8 100644 --- a/dat/og/bc_rules60.txt +++ b/dat/og/bc_rules60.txt @@ -5,8 +5,8 @@ open, store fp, close => idle, idle, idle; open, store fp, get i, close => idle, idle, get i, idle; peek fp:$1, copy, peek fp:#1 => peek fp, copy, idle; peek fp:$1, save, peek fp:#1 => peek fp, save, idle; -set :$2, store sp:$1 => xstore sp:$3, idle; -set :$2, store fp:$1 => xstore fp:$3, idle; +set :$2, store sp:$1 $ => xstore sp:$3, idle; +set :$2, store fp:$1 $ => xstore fp:$3, idle; load dp:$1, save dp:#1 => load dp, idle; store sp:$1, peek sp:#1 => store sp, idle; store fp:$1, peek fp:#1 => store fp, idle; diff --git a/dat/sg/syntax67.txt b/dat/sg/syntax67.txt index 53f51822c..188c4ae1f 100644 --- a/dat/sg/syntax67.txt +++ b/dat/sg/syntax67.txt @@ -637,7 +637,7 @@ VI_OP ::= // ; extening I_OP EI_OP ::= - BRACKET ^OBJECT FUNCTION_R L2_F; + BRACKET ^OBJECT FUNCTION_R { L2_F | INLINE_F}; RI5_OP ::= LESS ^OBJECT TEMPLATE_ARG { "," TEMPLATE_ARG }* ">" ^TEMPLATE_TYPE TEMPLATE_R; @@ -667,7 +667,7 @@ I8_OP ::= IF ^OBJECT SINGLE_EXPRESSION ":" SINGLE_EXPRESSION ^IF_ELSE_OPERATION; I_OP ::= - SBRACKET ^OBJECT INDEXER_R { INLINE_F | L0_F } + SBRACKET ^OBJECT INDEXER_R { INLINE_F | L0_F | BRACKET FUNCTION_R } | "::" ^OBJECT EXT_R L3_F | INC ^OBJECT ^INC_OPERATION | DEC ^OBJECT ^DEC_OPERATION @@ -702,7 +702,7 @@ TEMPLATE_R ::= | { DYNAMIC_DIMENSION ^ARRAY_TYPE }+ ^OBJECT BRACKET FUNCTION_R L3_F | identifier ^OBJECT { ASSIGN ASSIGN_R }? | "?" ^NULLABLE_TYPE identifier ^OBJECT { ASSIGN ASSIGN_R }? - | BRACKET ^OBJECT FUNCTION_R + | BRACKET ^OBJECT FUNCTION_R L3_F | SBRACKET ^OBJECT INDEXER_R | DOT ^OBJECT MESSAGE L3_R | eps ^OBJECT; @@ -747,7 +747,7 @@ RI_OP ::= T_EXPRESSION T_EXPRESSION_F ^ TEMPLATE_BLOCK | LT_EXPRESSION ^ TEMPLATE_BLOCK } - | { "," MESSAGE_PARAMETER }+ ")" { eps ^MESSAGE_OPERATION } + | { "," MESSAGE_PARAMETER }+ ")" { RF_OP | eps ^MESSAGE_OPERATION } } | ")" { RF_OP diff --git a/doc/api/system-summary.html b/doc/api/system-summary.html index 85eed2184..bf88ed813 100644 --- a/doc/api/system-summary.html +++ b/doc/api/system-summary.html @@ -435,6 +435,16 @@

+ConstArray<T1> + + +
+public template ConstArray<T1>
+A strong-typed constant array template
+ + + + COORD @@ -442,7 +452,7 @@

public class COORD - + CriticalException @@ -451,7 +461,7 @@

public class CriticalException - + DivisionByZeroException @@ -460,7 +470,7 @@

public class DivisionByZeroException - + Enumerable @@ -470,7 +480,7 @@

An abstract generic enumerable class
Must be overridden
- + Enumerable<T1> @@ -480,7 +490,7 @@

An abstract strong-typed enumerable class
Must be overridden
- + Enumerator @@ -490,7 +500,7 @@

A generic enumerator interface - + Enumerator<T1> @@ -500,7 +510,7 @@

A strong-typed enumerator template - + Exception @@ -510,7 +520,7 @@

A basic exception - + Extension @@ -519,7 +529,7 @@

public class Extension - + ExtensionMessage @@ -529,7 +539,7 @@

An extended message constant - + ExtensionVariable @@ -538,7 +548,7 @@

public class ExtensionVariable - + FormatException @@ -547,7 +557,7 @@

public class FormatException - + Func @@ -557,7 +567,7 @@

A base weak action without arguments - + Func<T1> @@ -567,7 +577,7 @@

A base strong-typed function without arguments - + Func<T1,T1,system'IntNumber> @@ -577,7 +587,7 @@

A base strong-typed function with two arguments - + Func<T1,T2> @@ -587,7 +597,7 @@

A base strong-typed function with a single argument - + Func<T1,T2,T3> @@ -597,7 +607,7 @@

A base strong-typed function with two arguments - + Func<T1,T2,T3,T4> @@ -607,7 +617,7 @@

A base strong-typed function with three arguments - + Func<T1,T2,T3,T4,T5> @@ -617,7 +627,7 @@

A base strong-typed function with four arguments - + Func<T1,T2,T3,T4,T5,T6> @@ -627,7 +637,7 @@

A base strong-typed function with five arguments - + Func<T1,T2,T3,T4,T5,T6,T7> @@ -637,7 +647,7 @@

A base strong-typed function with six arguments - + Func<T1,T2,T3,T4,T5,T6,T7,T8> @@ -647,7 +657,7 @@

A base strong-typed function with seven arguments - + Func<T1,T2,T3,T4,T5,T6,T7,T8,T9> @@ -657,7 +667,7 @@

A base strong-typed function with eight arguments - + Func<T1,T2,T3,T4,T5,T6,T7,T8,T9,T10> @@ -666,7 +676,7 @@

abstract public template Func<T1,T2,T3,T4,T5,T6,T7,T8,T9,T10> - + Func<T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11> @@ -676,7 +686,7 @@

A base strong-typed function with ten arguments - + Func<T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12> @@ -686,7 +696,7 @@

A base strong-typed function with eleven arguments - + Func1 @@ -696,7 +706,7 @@

A base weak action with a single argument - + Func10 @@ -706,7 +716,7 @@

A base weak action with ten arguments - + Func11 @@ -716,7 +726,7 @@

A base weak action with eleven arguments - + Func2 @@ -726,7 +736,7 @@

A base weak action with two arguments - + Func3 @@ -736,7 +746,7 @@

A base weak action with three arguments - + Func4 @@ -746,7 +756,7 @@

A base weak action with four arguments - + Func5 @@ -756,7 +766,7 @@

A base weak action with five arguments - + Func6 @@ -766,7 +776,7 @@

A base weak action with six arguments - + Func7 @@ -776,7 +786,7 @@

A base weak action with seven arguments - + Func8 @@ -786,7 +796,7 @@

A base weak action with eight arguments - + Func9 @@ -796,7 +806,7 @@

A base weak action with nine arguments - + Handle @@ -805,7 +815,7 @@

public class Handle - + IConsoleReader @@ -814,7 +824,7 @@

abstract public class IConsoleReader - + IConsoleWriter @@ -823,7 +833,7 @@

abstract public class IConsoleWriter - + Indexable @@ -833,7 +843,7 @@

An abstract generic indexable class
Must be overridden
- + Indexable<T1> @@ -843,7 +853,7 @@

An abstract strong-typed indexable class
Must be overridden
- + Indexer @@ -853,7 +863,7 @@

A generic indexer interface
The indexer is a tape interface over a collection, allowing to move along it, setting and getting its elements by an index
- + Indexer<T1> @@ -863,7 +873,7 @@

A strong-typed indexer interface
The indexer is a tape interface over a collection, allowing to move along it, setting and getting its elements by an index
- + IntBaseNumber @@ -873,7 +883,7 @@

a base integer value - + IntConvertor @@ -882,7 +892,7 @@

public singleton IntConvertor - + IntMatrix @@ -892,7 +902,7 @@

A two-dimensional array of integers - + IntNumber @@ -902,7 +912,7 @@

A signed 32 bit integer - + InvalidArgumentException @@ -911,7 +921,7 @@

public class InvalidArgumentException - + InvalidOperationException @@ -920,7 +930,7 @@

public class InvalidOperationException - + KeyValue @@ -930,7 +940,7 @@

A key - value pair
Extends the object with a key property
- + LongConvertor @@ -939,7 +949,7 @@

public singleton LongConvertor - + LongNumber @@ -949,7 +959,7 @@

A signed 64 bit integer value - + Matrix<T1> @@ -959,7 +969,7 @@

A two-dimensional strong-type array - + Message @@ -969,7 +979,7 @@

A message constant - + MessageLoaderException @@ -978,7 +988,7 @@

public class MessageLoaderException - + MessageName @@ -988,7 +998,7 @@

A message name constant - + MethodNotFoundException @@ -997,7 +1007,7 @@

public class MethodNotFoundException - + MssgConvertor @@ -1006,7 +1016,7 @@

public singleton MssgConvertor - + NilReferenceException @@ -1015,7 +1025,7 @@

public class NilReferenceException - + NilValue @@ -1025,7 +1035,7 @@

A nil value - + NotSupportedException @@ -1034,7 +1044,7 @@

public class NotSupportedException - + Object @@ -1044,7 +1054,7 @@

a common ancestor - + OutOfMemoryException @@ -1053,7 +1063,7 @@

public class OutOfMemoryException - + OutOfRangeException @@ -1062,7 +1072,7 @@

public class OutOfRangeException - + PropertyMessageName @@ -1072,7 +1082,7 @@

A property name constant - + Range @@ -1082,7 +1092,7 @@

represents a range that has start and end indexes.
The class support Enumerable interface
- + RealConvertor @@ -1091,7 +1101,7 @@

public singleton RealConvertor - + RealMatrix @@ -1101,7 +1111,7 @@

A two-dimensional array of real numbers - + RealNumber @@ -1111,7 +1121,7 @@

A 64bit float numeric value - + Reference<T1> @@ -1121,7 +1131,7 @@

a variable template - + SByteConvertor @@ -1130,7 +1140,7 @@

public singleton SByteConvertor - + SByteNumber @@ -1140,7 +1150,7 @@

a signed 8 bit integer - + ShortArrayConvertor @@ -1149,7 +1159,7 @@

public singleton ShortArrayConvertor - + ShortConvertor @@ -1158,7 +1168,7 @@

public singleton ShortConvertor - + ShortNumber @@ -1168,7 +1178,7 @@

a signed 16 bit integer - + SMALL_RECT @@ -1177,7 +1187,7 @@

public class SMALL_RECT - + StackOverflowException @@ -1186,7 +1196,7 @@

public class StackOverflowException - + StartUpEvents @@ -1195,7 +1205,7 @@

public class StartUpEvents - + String @@ -1205,7 +1215,7 @@

A UTF-8 literal value - + StringConvertor @@ -1214,7 +1224,7 @@

public singleton StringConvertor - + Symbol @@ -1223,7 +1233,7 @@

public class Symbol - + SymbolLoaderException @@ -1232,7 +1242,7 @@

public class SymbolLoaderException - + TypeLoaderException @@ -1241,7 +1251,7 @@

public class TypeLoaderException - + UIntConvertor @@ -1250,7 +1260,7 @@

public singleton UIntConvertor - + UIntNumber @@ -1260,7 +1270,7 @@

A unsigned 32 bit integer - + UnsafeArray @@ -1269,7 +1279,7 @@

public class UnsafeArray - + UnsafePointer @@ -1278,7 +1288,7 @@

public class UnsafePointer - + UnsafePointer<T1> @@ -1287,7 +1297,7 @@

public template UnsafePointer<T1> - + UShortConvertor @@ -1296,7 +1306,7 @@

public singleton UShortConvertor - + UShortNumber @@ -1306,7 +1316,7 @@

an unsigned 16 bit integer - + Variable @@ -1316,7 +1326,7 @@

A generic variable.
Extends an assigned value with compound operators : append (+=), reduce (-=), multiplyBy (*=) and divideBy (/=)
- + Variant @@ -1326,7 +1336,7 @@

A basic type variant class - + WideConvertor @@ -1335,7 +1345,7 @@

public singleton WideConvertor - + WideString diff --git a/doc/api/system.html b/doc/api/system.html index 59ce2d8d4..3b0843241 100644 --- a/doc/api/system.html +++ b/doc/api/system.html @@ -6054,6 +6054,204 @@

Method Summary


+ + + +
+
+system'
+

ConstArray<T1>

+
+
+
+
+
+
+public template ConstArray<T1>
+A strong-typed constant array template
+
+
+ + +
    +
  • +

    Field Summary

    + + + + + + + + + +
    Modifier and TypeField
    + + +array +
    +
  • +
+ +
    +
  • +

    Constructor Summary

    + + + + + + + + + + + + + +
    Modifier and TypeConstructor / Static Method
    + +ConstArray<T1> +allocate(IntNumber length) + +
    +Creates an array with the specified length
    +
    + +ConstArray<T1> +copy(T1[] array, IntNumber index, IntNumber length) + +
    +Creates a copy of sub array of array starting from index with the specified length
    +
    +
  • +
+ +
    +
  • +

    Property Summary

    + + + + + + + + + +
    Modifier and TypeProperty
    + +get  IntNumber +Length() +
    +Returns the array length
    +
    +
  • +
+ +
    +
  • +

    Conversion Summary

    + + + + + + + + + + + + + + + + + +
    Modifier and TypeConversion Method
    + +T1[] +cast() +
    +Creates a copy of the strong-typed array
    +
    + +Array +cast() +
    +Creates a weak copy of the array
    +
    + +Enumerable +cast() +
    +Returns enumerable wrapper around the array
    +
    +
  • +
+ +
    +
  • +

    Method Summary

    + + + + + + + + + + + + + + + + + +
    Modifier and TypeMethod
    + +Enumerator<T1> +enumerator() + +
    +Creates an array enumerator
    +
    + +T1[] +clone() + +
    +Returns the shallow copy of the array
    +
    + +T1 +at(IntNumber n) + +
    +Returns an element at the position n
    If an index is out of range, it raises InvalidArgumentException exception.
    +
    +
  • +
+
+
diff --git a/doc/features b/doc/features index b04ce324e..95209166d 100644 --- a/doc/features +++ b/doc/features @@ -477,3 +477,68 @@ public program() f1(); f2(); } + +---------------------------------------------------------------------------- + short-cut syntax for array +---------------------------------------------------------------------------- + +public program() +{ + string[] dirNames := new []{ ".", ".." }; +} + +---------------------------------------------------------------------------- + syntax for a constant array +---------------------------------------------------------------------------- + +public program() +{ + const string[] dirNames := new const string []{ ".", ".." }; +} + +---------------------------------------------------------------------------- + readonly fields +---------------------------------------------------------------------------- + +class B; + +class A +{ + readonly B b; + + constructor new(B b) + { + this b := b + } + + testReadOnly(B arg) + { + b := arg // !! raises an error 116 : Read-only field cannot be changed + } +} + +public program() +{ + A a := A.new(new B()); + a.testReadOnly(new B()); +} + +---------------------------------------------------------------------------- + without template reusing +---------------------------------------------------------------------------- + +It is possible to force the compiler to generate the templates without +reusing ones declared in the previous modules. The special module hint +must be provided + + + common.l + mbedtlssocket.l + mbedtlslistener.l + + + client\registration\registration.l + + + server\registration\registration.l + diff --git a/doc/todo.txt b/doc/todo.txt index 7630821c8..486f5033f 100644 --- a/doc/todo.txt +++ b/doc/todo.txt @@ -3,78 +3,38 @@ In development: ------ [development] - ### EPIC: elena 6.8 ### - - === Iteration 42 === - -------------------------------------- - * release 6.8 - -------------------------------------- - - merge PR - - prepare release notes - - upload linux x86, linux amd64, bsd amd64 - - upload release files - - release a new version of mbedtls wrapper - -------------------------------------- - ### EPIC: elena 6.9 ### - === Iteration 44 === - ====================================== - * new version 6.8.1 - * fix entropy sample - * api : provide descriptions for all classes in system & extensions, starting from IntMatrix - * #820 : Launch elena64-ide.exe from the command line - * warn if nil is passed to the non-nil argument - * ldoc : support search by method name - * ldoc : support search by class name - * Babylonian spiral - ====================================== - * #184 : IDE linux - migrate to gtkmm4 + === Iteration 44 (linux mt console; ide; powerpc) === -------------------------------------- - - #184 : IDE : project view - - #184 : project menu commands - - #184 : IDE : enable / disable menu commands - - #184 : IDE - select text with a mouse - - #184 : dialogs must be mandantory - - - #184 : IDE linux - implement all menu commands (except debug / compile) - - get rid of FileDialogBase - - #184 : IDE linux - mark modified file - - #184 : IDE linux - include / exclude - - #184 : uncomment checkMenuItemById - - #184 : exit - - #184 : recent file / project list + * new version 6.8.2 -------------------------------------- - * IDE : close all - do not save file if it was not changed - * IDE : call stack - * IDE Profile : introduce menu sub menu - profiles where the current profile can be selected - * IDE : right click on tab - context menu : close, close all, close all but current - * IDE : close icon on the tab - ====================================== - #35 : webapi weather backend (using existing frontend) + * dev + ====================================== + * lang + ====================================== + * doc + ====================================== + * current -------------------------------------- - * working on dummy https server : investigate error - mbedtls_socket_handshake returns -28160 - * example - https://github.com/Mbed-TLS/mbedtls/blob/development/programs/ssl/ssl_pthread_server.c - * comment output => use logger to display this information - - * simple web api client - GET - * simple web api - POST - * simple web api client - POST - - * combining into a generic httpserver - * DI resolver : https://learn.microsoft.com/en-us/aspnet/web-api/overview/advanced/dependency-injection -------------------------------------- - === Iteration 45 === + === Iteration 45 (ldoc method index; full api docs; template generator; httpget / httpsget reliability) === -------------------------------------- + * new version 6.8.3 -------------------------------------- - - === Iteration 46 === + * dev + ====================================== + * lang + ====================================== + * doc + ====================================== + * current -------------------------------------- -------------------------------------- - ### EPIC: elena 6.10 ### + ### EPIC: elena 7.0 ### - === Iteration 47 === + === Iteration 46 === -------------------------------------- -------------------------------------- diff --git a/elenasrc3/common/lists.h b/elenasrc3/common/lists.h index 6a4eaf510..b3ab0f0dc 100644 --- a/elenasrc3/common/lists.h +++ b/elenasrc3/common/lists.h @@ -3286,13 +3286,13 @@ namespace elena_lang void* ptr = realloc(_allocated, _allocatedSize * sizeof(T)); - assert(ptr != nullptr); - if (ptr) { _allocated = (T*)ptr; } } + assert(_allocated != nullptr); + if (index < cacheSize) { for (size_t i = _length; i > cacheSize; i--) _allocated[i - cacheSize] = _allocated[i - cacheSize - 1]; diff --git a/elenasrc3/common/paths.h b/elenasrc3/common/paths.h index 0a3fc3533..1b99272c3 100644 --- a/elenasrc3/common/paths.h +++ b/elenasrc3/common/paths.h @@ -133,6 +133,10 @@ namespace elena_lang copy(root); combine(subPath); } + PathString(path_t path, size_t len) + { + copy(path, len); + } #if (defined(_WIN32) || defined(__WIN32__)) bool append(const path_c* s, size_t length) { diff --git a/elenasrc3/elc/cli.cpp b/elenasrc3/elc/cli.cpp index a0bd39af0..9a3c0ccf3 100644 --- a/elenasrc3/elc/cli.cpp +++ b/elenasrc3/elc/cli.cpp @@ -262,6 +262,8 @@ void CLIHelper :: handleOption(path_c* arg, IdentifierString& profile, Project& case 'm': project.addBoolSetting(ProjectOption::MappingOutputMode, true); break; + case 'n': + break; case 'o': if (arg[2] == '0') { project.addIntSetting(ProjectOption::OptimizationMode, optNone); @@ -438,8 +440,17 @@ int CLIHelper :: compileProjectCollection(int argc, path_c** argv, path_t path, int retVal = 0; ProjectCollection collection; - if (!collection.load(platform, path)) { + // load name attribute + ustr_t nameAttr = nullptr; + if (argv[1][0] == '-' && argv[1][1] == 'n') { + IdentifierString argStr(argv[1] + 2); + + nameAttr = (*argStr).clone(); + } + + if (!collection.load(platform, path, nameAttr)) { presenter.printPath(presenter.getMessage(wrnInvalidConfig), path); + freeUStr(nameAttr); return EXIT_FAILURE; } @@ -457,12 +468,15 @@ int CLIHelper :: compileProjectCollection(int argc, path_c** argv, path_t path, int result = compileSingleProject(argc, argv, appPath, errorProcessor, spec->basePath, spec->profile); if (result == EXIT_FAILURE) { - return EXIT_FAILURE; + retVal = EXIT_FAILURE; + break; } else if (result == WARNING_RET_CODE) { retVal = WARNING_RET_CODE; } } + freeUStr(nameAttr); + return retVal; } diff --git a/elenasrc3/elc/clicommon.h b/elenasrc3/elc/clicommon.h index 5b99d2b5d..dc4952db9 100644 --- a/elenasrc3/elc/clicommon.h +++ b/elenasrc3/elc/clicommon.h @@ -3,7 +3,7 @@ // // This file contains the compiler common interfaces & types // -// (C)2021-2025, by Aleksey Rakov +// (C)2021-2026, by Aleksey Rakov // (C)2024, by ELENA-LANG Org //--------------------------------------------------------------------------- @@ -191,7 +191,7 @@ struct BuiltinReferences ref_t messageReference, extMessageReference; ref_t messageNameReference; ref_t wrapperTemplateReference; - ref_t arrayTemplateReference; + ref_t arrayTemplateReference, constArrayTemplateReference; ref_t nullableTemplateReference; ref_t argArrayTemplateReference; ref_t closureTemplateReference, tupleTemplateReference; @@ -230,7 +230,7 @@ struct BuiltinReferences messageReference = extMessageReference = 0; messageNameReference = 0; wrapperTemplateReference = 0; - arrayTemplateReference = argArrayTemplateReference = 0; + arrayTemplateReference = argArrayTemplateReference = constArrayTemplateReference = 0; nullableTemplateReference = 0; closureTemplateReference = lazyExpressionReference = tupleTemplateReference = 0; asyncStatemachineReference = yielditTemplateReference = 0; @@ -309,18 +309,13 @@ class ModuleScopeBase : public SectionScopeBase bool tapeOptMode; Map cachedSizes; + Map cachedFlags; Map cachedClassReferences; - Map cachedEmbeddableReadonlys; - Map cachedEmbeddables; - Map cachedEmbeddableStructs; - Map cachedEmbeddableArrays; - Map cachedStacksafeArgs; - Map cachedWrappers; - Map cachedClosed; virtual bool isStandardOne() = 0; virtual bool withValidation() = 0; virtual bool withPrologEpilog() = 0; + virtual bool isNoTemplateReuse() = 0; virtual bool isDeclared(ref_t reference) = 0; virtual bool isSymbolDeclared(ref_t reference) = 0; @@ -380,13 +375,7 @@ class ModuleScopeBase : public SectionScopeBase operations(0), cachedSizes({}), cachedClassReferences(0), - cachedEmbeddableReadonlys(false), - cachedEmbeddables(false), - cachedEmbeddableStructs(false), - cachedEmbeddableArrays(false), - cachedStacksafeArgs(false), - cachedWrappers(false), - cachedClosed(false) + cachedFlags(0) { this->module = module; this->debugModule = debugModule; @@ -454,6 +443,7 @@ enum class ExpressionAttribute : pos64_t NotNil = 0x0800000000000, HeapAllocated = 0x1000000000000, StackUnsafe = 0x2000000000000, + ReadOnly = 0x4000000000000, }; struct ExpressionAttributes @@ -518,6 +508,7 @@ struct FieldAttributes bool autogenerated; bool privateOne; bool isAuto; + bool ignoreDuplicates; }; // --- CompilerBase --- diff --git a/elenasrc3/elc/cliconst.h b/elenasrc3/elc/cliconst.h index c8f88e1a8..1dfb41512 100644 --- a/elenasrc3/elc/cliconst.h +++ b/elenasrc3/elc/cliconst.h @@ -3,7 +3,7 @@ // // This file contains the compiler common interfaces & types // -// (C)2021-2025, by Aleksey Rakov +// (C)2021-2026, by Aleksey Rakov //--------------------------------------------------------------------------- #ifndef CLICONST @@ -13,12 +13,12 @@ namespace elena_lang { - #define ELC_REVISION_NUMBER 0x0124 + #define ELC_REVISION_NUMBER 0x0142 constexpr auto WARNING_RET_CODE = 2; // --- Information messages --- - constexpr auto ELC_GREETING = "ELENA Command-line compiler %d.%d.%d (C)2005-2025 by Aleksey Rakov, ELENA-LANG Org\n"; + constexpr auto ELC_GREETING = "ELENA Command-line compiler %d.%d.%d (C)2005-2026 by Aleksey Rakov, ELENA-LANG Org\n"; constexpr auto ELC_CROSS_COMPILE_GREETING = "Cross-comile version\n"; constexpr auto ELC_STARTING = "\nProject: %s, Platform: %s, Target type: %s"; constexpr auto ELC_STRICT_MODE = "Strict type enforcing is on"; @@ -43,7 +43,7 @@ namespace elena_lang constexpr auto ELC_PROFILE_WARNING = "\nWARNING - Please select one of available profiles:%s\n"; constexpr auto ELC_PRJ_COLLECTION_WARNING = "\nWARNING - The project collection must be the last argument:%s\n"; - constexpr auto ELC_HELP_INFO = "elena-cli {-key} {source-file+ | project-file}\nkeys:\n -el{5 | 6} - specifying grammar compatibility\n -f{fwd=reference} - add a forward\n -l{profile name} - select a profile\n -m - turning on address mapping output\n -o{0 | 1 | 2} - set the optimization level\n -p - set the base path\n -r - clean the compilation output\n -s{ stackReserv:n } - set the linker option - stack reserved\n -t{ template name } - load the project template\n -v - turn on a verbose output mode\n - w{ 0 | 1 | 2 | 3 } - set the minimal warnings level to X = { 0 | 1 | 2 | 3 }\n -xb[-] - turn on / off a conditional boxing\n -xe[-] - turn on / off a compile-time expression evaluation\n -xj[-] - turn on / off jump alignment\n -xn[-] - turn on / off warning of nullable types\n -xm[-] - turn on / off auto loading module extension list\n -xp[-] - turn on / off generation of the parameter meta info\n -xs[-] - turn on / off strict type enforcing"; + constexpr auto ELC_HELP_INFO = "elena-cli {-key} {source-file+ | project-file}\nkeys:\n -el{5 | 6} - specifying grammar compatibility\n -f{fwd=reference} - add a forward\n -l{profile name} - select a profile\n -m - turning on address mapping output\n -f{fwd=reference} - add a forward\n -n{collection name} - select a collection to compile\n -o{0 | 1 | 2} - set the optimization level\n -p - set the base path\n -r - clean the compilation output\n -s{ stackReserv:n } - set the linker option - stack reserved\n -t{ template name } - load the project template\n -v - turn on a verbose output mode\n - w{ 0 | 1 | 2 | 3 } - set the minimal warnings level to X = { 0 | 1 | 2 | 3 }\n -xb[-] - turn on / off a conditional boxing\n -xe[-] - turn on / off a compile-time expression evaluation\n -xj[-] - turn on / off jump alignment\n -xn[-] - turn on / off warning of nullable types\n -xm[-] - turn on / off auto loading module extension list\n -xp[-] - turn on / off generation of the parameter meta info\n -xs[-] - turn on / off strict type enforcing"; constexpr auto SYNTAX50_FILE = "syntax50.dat"; constexpr auto SYNTAX60_FILE = "syntax60.dat"; diff --git a/elenasrc3/elc/compiler.cpp b/elenasrc3/elc/compiler.cpp index fb0ab4138..a2cc2f9f3 100644 --- a/elenasrc3/elc/compiler.cpp +++ b/elenasrc3/elc/compiler.cpp @@ -3,7 +3,7 @@ // // This file contains ELENA compiler class implementation. // -// (C)2021-2025, by Aleksey Rakov +// (C)2021-2026, by Aleksey Rakov //--------------------------------------------------------------------------- //#define FULL_OUTOUT_INFO 1 @@ -296,6 +296,18 @@ static inline bool isSingleObject(ObjectKind kind) } } +static inline bool isReadOnlyOperand(ObjectKind kind) +{ + switch (kind) { + case ObjectKind::ReadOnlySelfLocal: + case ObjectKind::ReadOnlyField: + case ObjectKind::ReadOnlyFieldAddress: + return true; + default: + return false; + } +} + static inline bool areConstants(ArgumentsInfo& args) { for (size_t i = 0; i < args.count(); i++) { @@ -1080,6 +1092,24 @@ ObjectInfo Compiler::NamespaceScope::defineObjectInfo(ref_t reference, Expressio return info; } + else { + SymbolInfo symbolInfo; + if (moduleScope->loadSymbolInfo(symbolInfo, reference)) { + switch (symbolInfo.symbolType) { + case SymbolType::Singleton: + if (symbolInfo.valueRef) + return { ObjectKind::Singleton, { symbolInfo.typeRef }, symbolInfo.valueRef }; + break; + case SymbolType::Constant: + case SymbolType::ConstantArray: + if (symbolInfo.valueRef) { + // HOTFIX : ingore declared but not defined constant + return defineConstant(symbolInfo); + } + break; + } + } + } } if (internOne) { // check if it is an internal procedure @@ -1433,7 +1463,10 @@ static inline ObjectInfo mapClassInfoField(ClassInfo& info, ustr_t identifier, E bool readOnly = (test(info.header.flags, elReadOnlyRole) || FieldInfo::checkHint(fieldInfo, FieldHint::ReadOnly)) && !EAttrs::test(attr, EAttr::InitializerScope); - return { readOnly ? ObjectKind::ReadOnlySelfLocal : ObjectKind::SelfLocal, fieldInfo.typeInfo, 1u, TargetMode::ArrayContent }; + TypeInfo typeInfo = fieldInfo.typeInfo; + typeInfo.constant = false; // !! HOTFIX : treat a constant embedded array like a normal one + + return { readOnly ? ObjectKind::ReadOnlySelfLocal : ObjectKind::SelfLocal, typeInfo, 1u, TargetMode::ArrayContent }; } else { auto staticFieldInfo = info.statics.get(identifier); @@ -3043,7 +3076,7 @@ void Compiler :: generateMethodAttributes(ClassScope& scope, SyntaxNode node, else methodInfo.hints &= ~((ref_t)MethodHint::Autogenerated); // add a stacksafe attribute for the embeddable structure automatically, except multi-methods - if (_logic->isEmbeddableStruct(scope.info) && !MethodScope::checkHint(methodInfo, MethodHint::Multimethod)) + if (_logic->isEmbeddableStruct(scope.info.header.flags) && !MethodScope::checkHint(methodInfo, MethodHint::Multimethod)) methodInfo.hints |= (ref_t)MethodHint::Stacksafe; TypeInfo outputInfo = retrieveTypeInfo(node.findChild(SyntaxKey::OutputInfo)); @@ -3058,7 +3091,7 @@ void Compiler :: generateMethodAttributes(ClassScope& scope, SyntaxNode node, int nodeNillableArgs = node.findChild(SyntaxKey::NillableInfo).arg.value; // validate if the nullable signatures matche each other - if (methodInfo.nillableArgs != 0 && methodInfo.nillableArgs != nodeNillableArgs) { + if ((methodInfo.nillableArgs & ~EnforcedNillableArgs) != 0 && methodInfo.nillableArgs != nodeNillableArgs) { scope.raiseWarning(WARNING_LEVEL_1, wrnNillableRedefined, node); } @@ -3427,7 +3460,7 @@ void Compiler :: declareInvoker(ClassInfo& info, mssg_t targetMssg, MethodInfo& else handlerInfo.hints &= ~(ref_t)MethodHint::Abstract; // HOTFIX : mark it as stacksafe if required - if (_logic->isEmbeddableStruct(info)) + if (_logic->isEmbeddableStruct(info.header.flags)) handlerInfo.hints |= (ref_t)MethodHint::Stacksafe; if (found) { @@ -3727,7 +3760,7 @@ void Compiler::generateClassStaticField(ClassScope& scope, SyntaxNode node, Fiel { ustr_t name = node.findChild(SyntaxKey::Name).firstChild(SyntaxKey::TerminalMask).identifier(); if (scope.info.statics.exist(name)) { - if (attrs.autogenerated) { + if (attrs.ignoreDuplicates) { node.setKey(SyntaxKey::Idle); } else scope.raiseError(errDuplicatedField, node); @@ -3736,11 +3769,11 @@ void Compiler::generateClassStaticField(ClassScope& scope, SyntaxNode node, Fiel } TypeInfo typeInfo = attrs.typeInfo; - bool isConst = attrs.isConstant; + bool isConst = attrs.isConstant; if (attrs.size < 0) { if (!attrs.inlineArray) { - typeInfo.typeRef = resolveArrayTemplate(*scope.moduleScope, attrs.typeInfo.typeRef, attrs.typeInfo.nillable, true); + typeInfo.typeRef = resolveArrayTemplate(*scope.moduleScope, attrs.typeInfo.typeRef, attrs.typeInfo.nillable, true, false); } else scope.raiseError(errIllegalField, node); } @@ -3809,7 +3842,9 @@ bool Compiler::generateClassField(ClassScope& scope, FieldAttributes& attrs, ust sizeInfo.size *= attrs.size; typeInfo.elementRef = typeInfo.typeRef; - typeInfo.typeRef = _logic->definePrimitiveArray(*scope.moduleScope, typeInfo.elementRef, true); + typeInfo.typeRef = _logic->definePrimitiveArray(*scope.moduleScope, typeInfo.elementRef, + true); + typeInfo.constant = test(scope.info.header.flags, elReadOnlyRole); } else return false; } @@ -3843,6 +3878,7 @@ bool Compiler::generateClassField(ClassScope& scope, FieldAttributes& attrs, ust typeInfo.typeRef = _logic->definePrimitiveArray(*scope.moduleScope, typeInfo.elementRef, test(scope.info.header.flags, elStructureRole)); + typeInfo.constant = test(scope.info.header.flags, elReadOnlyRole) || readOnly; scope.info.fields.add(name, { -2, typeInfo, readOnly, privateOne }); } @@ -3903,7 +3939,7 @@ DeclResult Compiler::checkAndGenerateClassField(ClassScope& scope, /*SyntaxNode scope.info.header.flags |= elDynamicRole; } else if (!test(scope.info.header.flags, elStructureRole)) { - typeInfo.typeRef = resolveArrayTemplate(*scope.moduleScope, attrs.typeInfo.typeRef, attrs.typeInfo.nillable, true); + typeInfo.typeRef = resolveArrayTemplate(*scope.moduleScope, attrs.typeInfo.typeRef, attrs.typeInfo.nillable, true, false); typeInfo.nillable = false; } else return DeclResult::Illegal; @@ -4537,6 +4573,9 @@ void Compiler :: declareVMTMessage(MethodScope& scope, SyntaxNode node, bool wit // Compiler Magic : if it is a mixin function - argument size cannot be directly defined scope.message = overwriteArgCount(scope.message, 0); } + + if (!weakSignature && !noSignature) + scope.info.nillableArgs |= EnforcedNillableArgs; } } @@ -4734,7 +4773,7 @@ ObjectInfo Compiler::evalExprValueOperation(Interpreter& interpreter, Scope& sco } if (lnode == SyntaxKey::KeyValueExpression) { - return evalExpression(interpreter, scope, lnode.findChild(SyntaxKey::Expression), ignoreErrors); + return evalExpression(interpreter, scope, lnode.findChild(SyntaxKey::Expression), {}, ignoreErrors); } else if (lnode == SyntaxKey::Object) { SyntaxNode terminalNode = lnode.firstChild(SyntaxKey::TerminalMask); @@ -4752,7 +4791,7 @@ ObjectInfo Compiler::evalSizeOperation(Interpreter& interpreter, Scope& scope, S { SyntaxNode lnode = node.firstChild(SyntaxKey::DeclarationMask); - ObjectInfo loperand = evalExpression(interpreter, scope, lnode, ignoreErrors); + ObjectInfo loperand = evalExpression(interpreter, scope, lnode, {}, ignoreErrors); SizeInfo sizeInfo = {}; switch (loperand.kind) { case ObjectKind::LocalAddress: @@ -4788,8 +4827,8 @@ ObjectInfo Compiler :: evalBoolOperation(Interpreter& interpreter, Scope& scope, ObjectInfo retVal = {}; ArgumentsInfo arguments; - arguments.add(evalExpression(interpreter, scope, lnode, ignoreErrors)); - arguments.add(evalExpression(interpreter, scope, rnode, ignoreErrors)); + arguments.add(evalExpression(interpreter, scope, lnode, {}, ignoreErrors)); + arguments.add(evalExpression(interpreter, scope, rnode, {}, ignoreErrors)); if (!interpreter.evalBoolOp(operator_id, arguments, retVal)) { if (!ignoreErrors) { @@ -4814,9 +4853,9 @@ ObjectInfo Compiler::evalOperation(Interpreter& interpreter, Scope& scope, Synta SyntaxNode sublnode = lnode.firstChild(SyntaxKey::DeclarationMask); SyntaxNode subrnode = sublnode.nextNode(SyntaxKey::DeclarationMask); - loperand = evalExpression(interpreter, scope, sublnode, ignoreErrors); - ioperand = evalExpression(interpreter, scope, subrnode, ignoreErrors); - roperand = evalExpression(interpreter, scope, rnode, ignoreErrors); + loperand = evalExpression(interpreter, scope, sublnode, {}, ignoreErrors); + ioperand = evalExpression(interpreter, scope, subrnode, {}, ignoreErrors); + roperand = evalExpression(interpreter, scope, rnode, {}, ignoreErrors); if (operator_id == SET_OPERATOR_ID) { operator_id = SET_INDEXER_OPERATOR_ID; @@ -4829,10 +4868,10 @@ ObjectInfo Compiler::evalOperation(Interpreter& interpreter, Scope& scope, Synta argCount = 3; } else { - loperand = evalExpression(interpreter, scope, lnode, ignoreErrors); + loperand = evalExpression(interpreter, scope, lnode, {}, ignoreErrors); if (rnode != SyntaxKey::None) { argCount = 2; - roperand = evalExpression(interpreter, scope, rnode, ignoreErrors); + roperand = evalExpression(interpreter, scope, rnode, {}, ignoreErrors); } } @@ -4865,9 +4904,9 @@ ObjectInfo Compiler::evalOperation(Interpreter& interpreter, Scope& scope, Synta return retVal; } -ObjectInfo Compiler::evalObject(/*Interpreter& interpreter, */Scope& scope, SyntaxNode node) +ObjectInfo Compiler::evalObject(/*Interpreter& interpreter, */Scope& scope, SyntaxNode node, ExpressionAttribute exprMode) { - EAttrs mode = ExpressionAttribute::Meta; + EAttrs mode = ExpressionAttribute::Meta | exprMode; return mapObject(scope, node, mode); } @@ -4887,7 +4926,7 @@ ObjectInfo Compiler::evalPropertyOperation(Interpreter& interpreter, Scope& scop { SyntaxNode lnode = node.firstChild(); - ObjectInfo loperand = evalExpression(interpreter, scope, lnode, ignoreErrors); + ObjectInfo loperand = evalExpression(interpreter, scope, lnode, {}, ignoreErrors); mssg_t message = mapMessage(scope, node.findChild(SyntaxKey::Message), true, false, false); switch (loperand.kind) { @@ -4917,7 +4956,7 @@ ObjectInfo Compiler::evalPropertyOperation(Interpreter& interpreter, Scope& scop return {}; } -ObjectInfo Compiler::evalCollection(Interpreter& interpreter, Scope& scope, SyntaxNode node, bool anonymousOne, bool ignoreErrors) +ObjectInfo Compiler::evalCollection(Interpreter& interpreter, Scope& scope, SyntaxNode node, TypeInfo targetInfo, bool anonymousOne, bool ignoreErrors) { SyntaxNode current = node.firstChild(); @@ -4926,10 +4965,17 @@ ObjectInfo Compiler::evalCollection(Interpreter& interpreter, Scope& scope, Synt bool numericOne = false; if (!anonymousOne) { - ObjectInfo objectInfo = evalObject(/*interpreter, */scope, current); + ObjectInfo objectInfo = evalObject(/*interpreter, */scope, current, EAttr::ProbeMode); if (objectInfo.kind != ObjectKind::Class) scope.raiseError(errInvalidOperation, node); + if (objectInfo.typeInfo.typeRef == V_AUTO && targetInfo.typeRef) + objectInfo.typeInfo = targetInfo; + + // NOTE : only const array type can be saved as a constant + if (!objectInfo.typeInfo.constant) + return {}; + current = current.nextNode(); collectionTypeRef = resolveStrongType(scope, objectInfo.typeInfo); @@ -4953,7 +4999,7 @@ ObjectInfo Compiler::evalCollection(Interpreter& interpreter, Scope& scope, Synt ArgumentsInfo arguments; while (current != SyntaxKey::None) { if (current == SyntaxKey::Expression) { - auto argInfo = evalExpression(interpreter, scope, current, ignoreErrors); + auto argInfo = evalExpression(interpreter, scope, current, {}, ignoreErrors); argInfo.typeInfo.typeRef = resolveStrongType(scope, argInfo.typeInfo); @@ -4992,16 +5038,17 @@ ObjectInfo Compiler::evalCollection(Interpreter& interpreter, Scope& scope, Synt return interpreter.createConstCollection(nestedRef, collectionTypeRef, arguments, byValue, size); } -ObjectInfo Compiler::evalExpression(Interpreter& interpreter, Scope& scope, SyntaxNode node, bool ignoreErrors, bool resolveMode) +ObjectInfo Compiler::evalExpression(Interpreter& interpreter, Scope& scope, SyntaxNode node, TypeInfo targetInfo, bool ignoreErrors, bool resolveMode) { ObjectInfo retVal = {}; switch (node.key) { case SyntaxKey::Expression: - retVal = evalExpression(interpreter, scope, node.firstChild(SyntaxKey::DeclarationMask), ignoreErrors, resolveMode); + retVal = evalExpression(interpreter, scope, node.firstChild(SyntaxKey::DeclarationMask), targetInfo, ignoreErrors, resolveMode); break; case SyntaxKey::AndOperation: case SyntaxKey::OrOperation: + case SyntaxKey::XorOperation: retVal = evalBoolOperation(interpreter, scope, node, (int)node.key - OPERATOR_MAKS, ignoreErrors); break; case SyntaxKey::AssignOperation: @@ -5042,10 +5089,10 @@ ObjectInfo Compiler::evalExpression(Interpreter& interpreter, Scope& scope, Synt retVal = evalPropertyOperation(interpreter, scope, node, ignoreErrors); break; case SyntaxKey::CollectionExpression: - retVal = evalCollection(interpreter, scope, node, false, ignoreErrors); + retVal = evalCollection(interpreter, scope, node, targetInfo, false, ignoreErrors); break; case SyntaxKey::PrimitiveCollection: - retVal = evalCollection(interpreter, scope, node, true, ignoreErrors); + retVal = evalCollection(interpreter, scope, node, {}, true, ignoreErrors); break; case SyntaxKey::NestedBlock: { @@ -5115,7 +5162,7 @@ void Compiler :: evalStatement(MetaScope& scope, SyntaxNode node) { Interpreter interpreter(scope.moduleScope, _logic); - ObjectInfo retVal = evalExpression(interpreter, scope, node.findChild(SyntaxKey::Expression)); + ObjectInfo retVal = evalExpression(interpreter, scope, node.findChild(SyntaxKey::Expression), {}); if (retVal.kind == ObjectKind::Unknown) scope.raiseError(errCannotEval, node); } @@ -5124,7 +5171,7 @@ ObjectInfo Compiler :: evalExpression(MetaScope& scope, SyntaxNode node) { Interpreter interpreter(scope.moduleScope, _logic); - ObjectInfo retVal = evalExpression(interpreter, scope, node); + ObjectInfo retVal = evalExpression(interpreter, scope, node, {}); if (retVal.kind == ObjectKind::Unknown) scope.raiseError(errCannotEval, node); @@ -5305,15 +5352,15 @@ ref_t Compiler :: resolvePrimitiveType(ModuleScopeBase& moduleScope, TypeInfo ty case V_INT32ARRAY: case V_FLOAT64ARRAY: case V_BINARYARRAY: - return resolveArrayTemplate(moduleScope, typeInfo.elementRef, typeInfo.nillableElement, declarationMode); - //case V_NULLABLE: + return resolveArrayTemplate(moduleScope, typeInfo.elementRef, typeInfo.nillableElement, declarationMode, typeInfo.constant); + //case V_NULLABLE: // return resolveNullableTemplate(moduleScope, ns, typeInfo.elementRef, declarationMode); case V_NIL: return moduleScope.buildins.superReference; case V_ARGARRAY: return resolveArgArrayTemplate(moduleScope, typeInfo.elementRef, declarationMode); case V_OBJARRAY: - return resolveArrayTemplate(moduleScope, typeInfo.elementRef, typeInfo.nillableElement, declarationMode); + return resolveArrayTemplate(moduleScope, typeInfo.elementRef, typeInfo.nillableElement, declarationMode, typeInfo.constant); case V_PTR32: case V_PTR64: return moduleScope.buildins.pointerReference; @@ -5392,6 +5439,7 @@ void Compiler::declareSymbolAttributes(SymbolScope& scope, SyntaxNode node, bool { bool constant = false; SyntaxNode current = node.firstChild(); + TypeInfo targetInfo = {}; while (current != SyntaxKey::None) { switch (current.key) { case SyntaxKey::Attribute: @@ -5404,10 +5452,13 @@ void Compiler::declareSymbolAttributes(SymbolScope& scope, SyntaxNode node, bool case SyntaxKey::ArrayType: case SyntaxKey::TemplateType: if (!identifierDeclarationMode) { - auto typeInfo = resolveStrongTypeAttribute(scope, current, true, false); - scope.info.typeRef = typeInfo.typeRef; + targetInfo = resolveStrongTypeAttribute(scope, current, true, false, constant, true); + if (targetInfo.isPrimitive()) { + scope.info.typeRef = resolvePrimitiveType(*scope.moduleScope, targetInfo, true); + } + else scope.info.typeRef = targetInfo.typeRef; - if (typeInfo.nillable) + if (targetInfo.nillable) scope.raiseError(errInvalidOperation, node); } @@ -5428,9 +5479,10 @@ void Compiler::declareSymbolAttributes(SymbolScope& scope, SyntaxNode node, bool scope.raiseError(errInvalidOperation, node); // !! currently external variable cannot be constant scope.info.symbolType = SymbolType::Constant; + targetInfo.constant = true; Interpreter interpreter(scope.moduleScope, _logic); - ObjectInfo operand = evalExpression(interpreter, scope, node.findChild(SyntaxKey::GetExpression).firstChild(), true); + ObjectInfo operand = evalExpression(interpreter, scope, node.findChild(SyntaxKey::GetExpression).firstChild(), targetInfo, true); if (operand.kind == ObjectKind::IntLiteral) { NamespaceScope* nsScope = Scope::getScope(scope, Scope::ScopeLevel::Namespace); nsScope->defineIntConstant(scope.reference, operand.extra); @@ -5443,7 +5495,7 @@ static inline bool isMethodKind(ref_t hint) return (hint & (ref_t)MethodHint::Mask) != 0; } -void Compiler::declareArgumentAttributes(MethodScope& scope, SyntaxNode node, TypeInfo& typeInfo, +void Compiler :: declareArgumentAttributes(MethodScope& scope, SyntaxNode node, TypeInfo& typeInfo, bool declarationMode) { SyntaxNode current = node.firstChild(); @@ -5452,16 +5504,16 @@ void Compiler::declareArgumentAttributes(MethodScope& scope, SyntaxNode node, Ty switch (current.key) { case SyntaxKey::Type: // if it is a type attribute - typeInfo = resolveTypeAttribute(scope, current, attributes, declarationMode, false); + typeInfo = resolveTypeAttribute(scope, current, attributes, declarationMode, false, false); break; case SyntaxKey::TemplateType: // if it is a template type attribute - typeInfo = resolveTypeAttribute(scope, current, attributes, declarationMode, false); + typeInfo = resolveTypeAttribute(scope, current, attributes, declarationMode, false, false); break; case SyntaxKey::NullableType: case SyntaxKey::ArrayType: // if it is a type attribute - typeInfo = resolveTypeScope(scope, current, attributes, declarationMode, false); + typeInfo = resolveTypeScope(scope, current, attributes, declarationMode, false, false); break; case SyntaxKey::Attribute: if (!_logic->validateArgumentAttribute(current.arg.reference, attributes)) { @@ -5498,7 +5550,7 @@ ref_t Compiler::declareMultiType(Scope& scope, SyntaxNode& current, ref_t elemen while (current != SyntaxKey::None) { if (current == SyntaxKey::Type) { - items.add({ ObjectKind::Class, resolveStrongTypeAttribute(scope, current, true, false), 0 }); + items.add({ ObjectKind::Class, resolveStrongTypeAttribute(scope, current, true, false, false), 0 }); } else break; @@ -5563,7 +5615,7 @@ void Compiler::declareMethodAttributes(MethodScope& scope, SyntaxNode node, bool continue; } else { - auto typeInfo = resolveStrongTypeAttribute(scope, current, true, false); + auto typeInfo = resolveStrongTypeAttribute(scope, current, true, false, false); scope.info.outputRef = typeInfo.typeRef; if (typeInfo.nillable) scope.info.hints |= (ref_t)MethodHint::Nillable; @@ -5677,7 +5729,7 @@ void Compiler::registerTemplateSignature(TemplateScope& scope, SyntaxNode node, if (argNode == SyntaxKey::Type) { signature.append('&'); - auto classInfo = resolveStrongTypeAttribute(scope, argNode, false, false); + auto classInfo = resolveStrongTypeAttribute(scope, argNode, false, false, false); if (!classInfo.typeRef) scope.raiseError(errUnknownClass, current); @@ -5733,7 +5785,7 @@ void Compiler::registerExtensionTemplateMethod(TemplateScope& scope, SyntaxNode& registerTemplateSignature(scope, typeAttr, signaturePattern); } else if (typeAttr != SyntaxKey::None) { - auto classInfo = resolveStrongTypeAttribute(scope, typeAttr, true, false); + auto classInfo = resolveStrongTypeAttribute(scope, typeAttr, true, false, false); ustr_t className = scope.module->resolveReference(classInfo.typeRef); if (isWeakReference(className)) @@ -5949,7 +6001,7 @@ void Compiler::declareDictionaryAttributes(Scope& scope, SyntaxNode node, TypeIn } else if (current == SyntaxKey::Type) { TypeAttributes typeAttributes = {}; - TypeInfo dictTypeInfo = resolveTypeAttribute(scope, current, typeAttributes, true, false); + TypeInfo dictTypeInfo = resolveTypeAttribute(scope, current, typeAttributes, true, false, false); if (!typeAttributes.isNonempty() && _logic->isCompatible(*scope.moduleScope, dictTypeInfo, { V_STRING }, true)) { typeInfo.typeRef = V_DICTIONARY; typeInfo.elementRef = V_STRING; @@ -5980,7 +6032,8 @@ void Compiler::declareExpressionAttributes(Scope& scope, SyntaxNode node, TypeIn case SyntaxKey::NullableType: if (!EAttrs::test(mode.attrs, EAttr::NoTypeAllowed)) { TypeAttributes attributes = {}; - typeInfo = resolveTypeAttribute(scope, current, attributes, false, false); + typeInfo = resolveTypeAttribute(scope, current, attributes, false, false, + mode.test(EAttr::ReadOnly)); if (attributes.mssgNameLiteral) { mode |= ExpressionAttribute::MssgNameLiteral; @@ -6149,7 +6202,7 @@ void Compiler::declareTemplateAttributes(Scope& scope, SyntaxNode node, case SyntaxKey::Type: case SyntaxKey::TemplateType: { - auto typeInfo = resolveStrongTypeAttribute(scope, current, declarationMode, attributes.mssgNameLiteral); + auto typeInfo = resolveStrongTypeAttribute(scope, current, declarationMode, attributes.mssgNameLiteral, false); parameters.add(typeInfo); break; @@ -6179,7 +6232,7 @@ void Compiler::declareIncludeAttributes(Scope& scope, SyntaxNode node, bool& tex } } -ref_t Compiler::defineArrayType(Scope& scope, ref_t elementRef, bool declarationMode) +ref_t Compiler :: defineArrayType(Scope& scope, ref_t elementRef, bool declarationMode) { ref_t retVal = _logic->definePrimitiveArray(*scope.moduleScope, elementRef, _logic->isEmbeddable(*scope.moduleScope, elementRef)); @@ -6190,13 +6243,14 @@ ref_t Compiler::defineArrayType(Scope& scope, ref_t elementRef, bool declaration return retVal; } -ObjectInfo Compiler::defineArrayType(Scope& scope, ObjectInfo info, bool declarationMode) +ObjectInfo Compiler::defineArrayType(Scope& scope, ObjectInfo info, bool declarationMode, bool readOnly) { ref_t elementRef = info.typeInfo.typeRef; ref_t arrayRef = defineArrayType(scope, elementRef, declarationMode); info.typeInfo.typeRef = arrayRef; info.typeInfo.elementRef = elementRef; + info.typeInfo.constant = readOnly; if (info.mode == TargetMode::Creating) info.mode = TargetMode::CreatingArray; @@ -6301,9 +6355,10 @@ ref_t Compiler::resolveWrapperTemplate(ModuleScopeBase& moduleScope, ref_t eleme return resolveTemplate(moduleScope, moduleScope.buildins.wrapperTemplateReference, elementRef, false, declarationMode); } -ref_t Compiler::resolveArrayTemplate(ModuleScopeBase& moduleScope, ref_t elementRef, bool nullableElement, bool declarationMode) +ref_t Compiler::resolveArrayTemplate(ModuleScopeBase& moduleScope, ref_t elementRef, bool nullableElement, bool declarationMode, bool constAttr) { - return resolveTemplate(moduleScope, moduleScope.buildins.arrayTemplateReference, elementRef, nullableElement, declarationMode); + return resolveTemplate(moduleScope, + constAttr ? moduleScope.buildins.constArrayTemplateReference : moduleScope.buildins.arrayTemplateReference, elementRef, nullableElement, declarationMode); } // //ref_t Compiler :: resolveNullableTemplate(ModuleScopeBase& moduleScope, ustr_t ns, ref_t elementRef, bool declarationMode) @@ -6316,8 +6371,8 @@ ref_t Compiler::resolveArgArrayTemplate(ModuleScopeBase& moduleScope, ref_t elem return resolveTemplate(moduleScope, moduleScope.buildins.argArrayTemplateReference, elementRef, false, declarationMode); } -TypeInfo Compiler::resolveTypeScope(Scope& scope, SyntaxNode node, TypeAttributes& attributes, - bool declarationMode, bool allowRole) +TypeInfo Compiler :: resolveTypeScope(Scope& scope, SyntaxNode node, TypeAttributes& attributes, + bool declarationMode, bool allowRole, bool constAttr) { bool nullable = false; ref_t elementRef = 0; @@ -6331,16 +6386,17 @@ TypeInfo Compiler::resolveTypeScope(Scope& scope, SyntaxNode node, TypeAttribute break; case SyntaxKey::Type: { - auto info = resolveStrongTypeAttribute(scope, current, declarationMode, false); + auto info = resolveStrongTypeAttribute(scope, current, declarationMode, false, constAttr); elementRef = info.typeRef; nullable = info.nillable; + constAttr |= info.constant; break; } case SyntaxKey::TemplateType: - elementRef = resolveTypeAttribute(scope, current, attributes, declarationMode, allowRole).typeRef; + elementRef = resolveTypeAttribute(scope, current, attributes, declarationMode, allowRole, constAttr).typeRef; break; case SyntaxKey::NullableType: - elementRef = resolveTypeAttribute(scope, current, attributes, declarationMode, allowRole).typeRef; + elementRef = resolveTypeAttribute(scope, current, attributes, declarationMode, allowRole, constAttr).typeRef; nullable = true; break; case SyntaxKey::identifier: @@ -6350,7 +6406,7 @@ TypeInfo Compiler::resolveTypeScope(Scope& scope, SyntaxNode node, TypeAttribute break; case SyntaxKey::ArrayType: elementRef = resolvePrimitiveType(*scope.moduleScope, - resolveTypeAttribute(scope, current, attributes, declarationMode, allowRole), declarationMode); + resolveTypeAttribute(scope, current, attributes, declarationMode, allowRole, constAttr), declarationMode); break; default: assert(false); @@ -6362,23 +6418,23 @@ TypeInfo Compiler::resolveTypeScope(Scope& scope, SyntaxNode node, TypeAttribute if (node == SyntaxKey::ArrayType) { if (attributes.variadicOne) { - return { V_ARGARRAY, elementRef }; + return { V_ARGARRAY, elementRef, false, false, constAttr }; } - else return { defineArrayType(scope, elementRef, declarationMode), elementRef, false, nullable }; + else return { defineArrayType(scope, elementRef, declarationMode), elementRef, false, nullable, constAttr }; } else if (node == SyntaxKey::NullableType) { - return { elementRef, 0, true }; + return { elementRef, 0, true, false, constAttr }; } else return {}; } -TypeInfo Compiler::resolveTypeAttribute(Scope& scope, SyntaxNode node, TypeAttributes& attributes, - bool declarationMode, bool allowRole) +TypeInfo Compiler :: resolveTypeAttribute(Scope& scope, SyntaxNode node, TypeAttributes& attributes, + bool declarationMode, bool allowRole, bool constAttr) { TypeInfo typeInfo = {}; switch (node.key) { case SyntaxKey::TemplateArg: - typeInfo = resolveTypeAttribute(scope, node.firstChild(), attributes, declarationMode, allowRole); + typeInfo = resolveTypeAttribute(scope, node.firstChild(), attributes, declarationMode, allowRole, constAttr); break; case SyntaxKey::Type: case SyntaxKey::ClosureReturnType: @@ -6389,7 +6445,7 @@ TypeInfo Compiler::resolveTypeAttribute(Scope& scope, SyntaxNode node, TypeAttri SyntaxNode current = node.firstChild(); if (current == SyntaxKey::Type || current == SyntaxKey::ArrayType || current == SyntaxKey::NullableType) { // !! should be refactored - typeInfo = resolveTypeAttribute(scope, current, attributes, declarationMode, allowRole); + typeInfo = resolveTypeAttribute(scope, current, attributes, declarationMode, allowRole, constAttr); } else if (current == SyntaxKey::TemplateType) { typeInfo = resolveTypeTemplate(scope, current, attributes, declarationMode); @@ -6409,14 +6465,14 @@ TypeInfo Compiler::resolveTypeAttribute(Scope& scope, SyntaxNode node, TypeAttri break; case SyntaxKey::ArrayType: { - typeInfo = resolveTypeScope(scope, node, attributes, declarationMode, allowRole); + typeInfo = resolveTypeScope(scope, node, attributes, declarationMode, allowRole, constAttr); if (attributes.variadicOne) scope.raiseError(errInvalidOperation, node); break; } case SyntaxKey::NullableType: - typeInfo = resolveTypeScope(scope, node, attributes, declarationMode, allowRole); + typeInfo = resolveTypeScope(scope, node, attributes, declarationMode, allowRole, constAttr); break; default: if (SyntaxTree::test(node.key, SyntaxKey::TerminalMask)) { @@ -6426,19 +6482,22 @@ TypeInfo Compiler::resolveTypeAttribute(Scope& scope, SyntaxNode node, TypeAttri break; } + if (constAttr) + typeInfo.constant = true; + validateType(scope, typeInfo.typeRef, node, declarationMode); return typeInfo; } -TypeInfo Compiler::resolveStrongTypeAttribute(Scope& scope, SyntaxNode node, bool declarationMode, bool allowRole) +TypeInfo Compiler :: resolveStrongTypeAttribute(Scope& scope, SyntaxNode node, bool declarationMode, bool allowRole, bool constAttr, bool allowPrimitive) { TypeAttributes typeAttributes = {}; - TypeInfo typeInfo = resolveTypeAttribute(scope, node, typeAttributes, declarationMode, allowRole); + TypeInfo typeInfo = resolveTypeAttribute(scope, node, typeAttributes, declarationMode, allowRole, constAttr); if (typeAttributes.isNonempty()) scope.raiseError(errInvalidOperation, node); - if (isPrimitiveRef(typeInfo.typeRef)) { + if (!allowPrimitive && isPrimitiveRef(typeInfo.typeRef)) { return { resolvePrimitiveType(*scope.moduleScope, typeInfo, declarationMode) }; } else return typeInfo; @@ -6466,7 +6525,7 @@ void Compiler::readFieldAttributes(ClassScope& scope, SyntaxNode node, FieldAttr while (current != SyntaxKey::None) { switch (current.key) { case SyntaxKey::Autogenerated: - attrs.autogenerated = true; + attrs.ignoreDuplicates = attrs.autogenerated = true; break; case SyntaxKey::Attribute: if (!_logic->validateFieldAttribute(current.arg.reference, attrs)) @@ -6479,7 +6538,7 @@ void Compiler::readFieldAttributes(ClassScope& scope, SyntaxNode node, FieldAttr TypeAttributes typeAttributes = {}; // HOTFIX : we have to resolve a field type immediately for the structures even in declaration mode - attrs.typeInfo = resolveTypeAttribute(scope, current, typeAttributes, declarationMode && !test(scope.info.header.flags, elStructureRole), false); + attrs.typeInfo = resolveTypeAttribute(scope, current, typeAttributes, declarationMode && !test(scope.info.header.flags, elStructureRole), false, attrs.isConstant); if (typeAttributes.isNonempty()) scope.raiseError(errInvalidHint, current); } @@ -6506,14 +6565,14 @@ void Compiler::readFieldAttributes(ClassScope& scope, SyntaxNode node, FieldAttr if (!declarationMode) { resolveArrayTemplate(*scope.moduleScope, - attrs.typeInfo.typeRef, attrs.typeInfo.nillable, declarationMode); + attrs.typeInfo.typeRef, attrs.typeInfo.nillable, declarationMode, false); } } else if (attrs.size == -1) { // if it is a nested array readFieldAttributes(scope, current, attrs, declarationMode); attrs.typeInfo = { resolveArrayTemplate(*scope.moduleScope, - attrs.typeInfo.typeRef, attrs.typeInfo.nillable, declarationMode)}; + attrs.typeInfo.typeRef, attrs.typeInfo.nillable, declarationMode, false)}; } else scope.raiseError(errInvalidHint, current); break; @@ -6711,7 +6770,7 @@ int Compiler::allocateLocalAddress(Scope& scope, int size, bool binaryArray) int Compiler::resolveArraySize(Scope& scope, SyntaxNode node) { Interpreter interpreter(scope.moduleScope, _logic); - ObjectInfo retVal = evalExpression(interpreter, scope, node); + ObjectInfo retVal = evalExpression(interpreter, scope, node, {}); switch (retVal.kind) { case ObjectKind::IntLiteral: return retVal.extra; @@ -6767,13 +6826,13 @@ DeclarationError Compiler :: declareVariable(Scope& scope, ustr_t identifier, Ty // HOTFIX : recognize binary array actual size localInfo.size *= _logic->defineStructSize(*scope.moduleScope, variable.typeInfo.elementRef).size; - if (_logic->isEmbeddableArray(localInfo) && size != 0) { + if (_logic->isEmbeddableArray(localInfo.header.flags) && size != 0) { //binaryArray = true; size = size * (-((int)localInfo.size)); variable.reference = allocateLocalAddress(*codeScope, size, true); } - else if (_logic->isEmbeddableStruct(localInfo) && size == 0 && !variable.typeInfo.nillable) { + else if (_logic->isEmbeddableStruct(localInfo.header.flags) && size == 0 && !variable.typeInfo.nillable) { size = align(_logic->defineStructSize(localInfo).size, scope.moduleScope->rawStackAlingment); @@ -6802,7 +6861,7 @@ DeclarationError Compiler :: declareVariable(Scope& scope, ustr_t identifier, Ty return DeclarationError::None; } -bool Compiler::declareVariable(Scope& scope, SyntaxNode terminal, TypeInfo typeInfo, bool ignoreDuplicate) +bool Compiler :: declareVariable(Scope& scope, SyntaxNode terminal, TypeInfo typeInfo, bool ignoreDuplicate) { int size = 0; if (terminal == SyntaxKey::IndexerOperation) { @@ -6922,7 +6981,7 @@ bool Compiler::evalAccumClassConstant(ustr_t constName, ClassScope& scope, Synta auto fieldInfo = *(collectionInfo.fields.start()); /*ref_t elementTypeRef = */resolveStrongType(scope, { fieldInfo.typeInfo.elementRef }); - ObjectInfo value = evalExpression(interpreter, scope, node); + ObjectInfo value = evalExpression(interpreter, scope, node, {}); if (value.kind == ObjectKind::Symbol && value.reference == scope.reference) { // HOTFIX : recognize the class value = { ObjectKind::Class, { scope.info.header.classRef }, scope.reference }; @@ -6951,7 +7010,7 @@ bool Compiler::evalClassConstant(ustr_t constName, ClassScope& scope, SyntaxNode auto it = scope.info.statics.getIt(constName); assert(!it.eof()); - ObjectInfo retVal = evalExpression(interpreter, metaScope, node, false, false); + ObjectInfo retVal = evalExpression(interpreter, metaScope, node, {}, false, false); bool setIndex = false; switch (retVal.kind) { case ObjectKind::SelfName: @@ -7229,22 +7288,6 @@ mssg_t Compiler::resolveOperatorMessage(ModuleScopeBase* scope, int operatorId) } } -static inline bool isPrimitiveArray(ref_t typeRef) -{ - switch (typeRef) { - case V_BINARYARRAY: - case V_OBJARRAY: - case V_INT32ARRAY: - case V_INT8ARRAY: - case V_UINT8ARRAY: - case V_INT16ARRAY: - case V_FLOAT64ARRAY: - return true; - default: - return false; - } -} - static inline bool DoesOperationSupportConvertableIntLiteral(int operatorId) { switch (operatorId) { @@ -7277,6 +7320,20 @@ static inline bool DoesOperationSupportConvertableIntLiteral(int operatorId) } } +static inline bool isLOperandMutable(int operatorId) +{ + switch (operatorId) { + case ADD_ASSIGN_OPERATOR_ID: + case SUB_ASSIGN_OPERATOR_ID: + case MUL_ASSIGN_OPERATOR_ID: + case DIV_ASSIGN_OPERATOR_ID: + case SET_INDEXER_OPERATOR_ID: + return true; + default: + return false; + } +} + mssg_t Compiler::mapMessage(Scope& scope, SyntaxNode current, bool propertyMode, bool extensionMode, bool probeMode) { @@ -7695,7 +7752,7 @@ ObjectInfo Compiler::mapMessageConstant(Scope& scope, SyntaxNode node, ref_t act pos_t argCount = 0; Interpreter interpreter(scope.moduleScope, _logic); - ObjectInfo retVal = evalExpression(interpreter, scope, node.findChild(SyntaxKey::Expression)); + ObjectInfo retVal = evalExpression(interpreter, scope, node.findChild(SyntaxKey::Expression), {}); switch (retVal.kind) { case ObjectKind::IntLiteral: argCount = retVal.extra; @@ -7718,7 +7775,7 @@ ObjectInfo Compiler :: mapExtMessageConstant(Scope& scope, SyntaxNode node, ref_ pos_t argCount = 0; Interpreter interpreter(scope.moduleScope, _logic); - ObjectInfo retVal = evalExpression(interpreter, scope, node.findChild(SyntaxKey::Expression)); + ObjectInfo retVal = evalExpression(interpreter, scope, node.findChild(SyntaxKey::Expression), {}); switch (retVal.kind) { case ObjectKind::IntLiteral: argCount = retVal.extra; @@ -7729,6 +7786,13 @@ ObjectInfo Compiler :: mapExtMessageConstant(Scope& scope, SyntaxNode node, ref_ } mssg_t message = encodeMessage(actionRef, argCount, 0); + + if (argCount >= ARG_COUNT) + scope.raiseError(errInvalidOperation, node); + + // NOTE : we need to increase the argument number to include the target + message++; + IdentifierString messageName; ByteCodeUtil::resolveMessageName(messageName, scope.module, message); @@ -7772,7 +7836,8 @@ ObjectInfo Compiler::defineTerminalInfo(Scope& scope, SyntaxNode node, TypeInfo case SyntaxKey::TemplateType: { TypeAttributes typeAttributes = {}; - TypeInfo typeInfo = resolveTypeAttribute(scope, node, typeAttributes, false, false); + TypeInfo typeInfo = resolveTypeAttribute(scope, node, typeAttributes, false, false, + EAttrs::test(attrs, EAttr::ReadOnly)); retVal = { ObjectKind::Class, typeInfo, 0u }; retVal = mapClassSymbol(scope, resolveStrongType(scope, retVal.typeInfo)); @@ -7996,13 +8061,21 @@ ObjectInfo Compiler::mapTerminal(Scope& scope, SyntaxNode node, TypeInfo declare case SyntaxKey::reference: { TypeAttributes typeAttributes = {}; - TypeInfo typeInfo = resolveTypeAttribute(scope, node, typeAttributes, false, false); + TypeInfo typeInfo = resolveTypeAttribute(scope, node, typeAttributes, false, false, + EAttrs::test(attrs, ExpressionAttribute::ReadOnly)); retVal = { ObjectKind::Class, typeInfo, 0u, newOp ? TargetMode::Creating : TargetMode::Casting }; if (CompilerLogic::isPrimitiveArrRef(retVal.typeInfo.typeRef) && newOp) retVal.mode = TargetMode::CreatingArray; break; } + case SyntaxKey::None: + if (probeMode && newOp) { + retVal = { ObjectKind::Class, V_AUTO, 0u, TargetMode::Creating }; + probeMode = false; + } + else invalid = true; + break; default: invalid = true; break; @@ -8340,7 +8413,7 @@ ObjectInfo Compiler::compileRootExpression(BuildTreeWriter& writer, CodeScope& c ArgumentsInfo updatedOuterArgs; Expression expression(this, codeScope, writer, !EAttrs::test(mode, EAttr::NoDebugInfo), &updatedOuterArgs); - ObjectInfo retVal = expression.compileRoot(node, mode); + ObjectInfo retVal = expression.compileRoot(node, mode | EAttr::Root); if (EAttrs::test(mode, EAttr::RetValExpected)) { retVal = expression.unboxArguments(retVal, false); @@ -9319,7 +9392,7 @@ mssg_t Compiler::compileInplaceConstructorHandler(BuildTreeWriter& writer, Metho privateScope.byRefReturnMode = true; privateScope.nestedMode = invokerScope.nestedMode; privateScope.functionMode = false; - privateScope.isEmbeddable = _logic->isEmbeddableStruct(classScope->info); + privateScope.isEmbeddable = _logic->isEmbeddableStruct(classScope->info.header.flags); privateScope.constructorMode = true; // NOTE self local is a first argument @@ -9410,7 +9483,7 @@ void Compiler::compileByRefRedirectHandler(BuildTreeWriter& writer, MethodScope& redirectScope.message = byRefHandler; // HOTFIX : mark it as stacksafe if required - if (_logic->isEmbeddableStruct(classScope->info)) + if (_logic->isEmbeddableStruct(classScope->info.header.flags)) redirectScope.info.hints |= (ref_t)MethodHint::Stacksafe; redirectScope.nestedMode = invokerScope.nestedMode; @@ -9644,19 +9717,24 @@ void Compiler :: writeParameterDebugInfo(BuildTreeWriter& writer, Scope& scope, } } else if (size < 0) { - if (typeInfo.typeRef == V_INT16ARRAY) { - writer.newNode(BuildKey::ShortArrayParameter, name); - } - else if (typeInfo.typeRef == V_INT8ARRAY || typeInfo.typeRef == V_UINT8ARRAY) { - writer.newNode(BuildKey::ByteArrayParameter, name); - } - else if (typeInfo.typeRef == V_INT32ARRAY) { - writer.newNode(BuildKey::IntArrayParameter, name); - } - else if (typeInfo.typeRef == V_FLOAT64ARRAY) { - writer.newNode(BuildKey::RealArrayParameter, name); - } - else writer.newNode(BuildKey::Parameter, name); // !! temporal + switch (typeInfo.typeRef) { + case V_INT16ARRAY: + writer.newNode(BuildKey::ShortArrayParameter, name); + break; + case V_INT8ARRAY: + case V_UINT8ARRAY: + writer.newNode(BuildKey::ByteArrayParameter, name); + break; + case V_INT32ARRAY: + writer.newNode(BuildKey::IntArrayParameter, name); + break; + case V_FLOAT64ARRAY: + writer.newNode(BuildKey::RealArrayParameter, name); + break; + default: + writer.newNode(BuildKey::Parameter, name); // !! temporal + break; + } } else writer.newNode(BuildKey::Parameter, name); @@ -9792,7 +9870,7 @@ ref_t Compiler :: resolveYieldType(Scope& scope, SyntaxNode node) { SyntaxNode current = node.findChild(SyntaxKey::TemplateType); if (current != SyntaxKey::None) { - auto typeInfo = resolveStrongTypeAttribute(scope, current.findChild(SyntaxKey::TemplateArg), true, false); + auto typeInfo = resolveStrongTypeAttribute(scope, current.findChild(SyntaxKey::TemplateArg), true, false, false); return typeInfo.typeRef; } @@ -9804,7 +9882,7 @@ ref_t Compiler :: declareAsyncStatemachine(StatemachineClassScope& scope, Syntax { SyntaxNode current = node.findChild(SyntaxKey::TemplateType); if (current != SyntaxKey::None) { - auto typeInfo = resolveStrongTypeAttribute(scope, current.findChild(SyntaxKey::TemplateArg), true, false); + auto typeInfo = resolveStrongTypeAttribute(scope, current.findChild(SyntaxKey::TemplateArg), true, false, false); scope.typeRef = resolveStateMachine(scope, scope.moduleScope->buildins.taskReference, typeInfo.typeRef); scope.resultRef = typeInfo.typeRef; @@ -10268,7 +10346,7 @@ void Compiler::initializeMethod(ClassScope& scope, MethodScope& methodScope, Syn if (methodScope.info.outputRef) { SyntaxNode typeNode = current.findChild(SyntaxKey::Type, SyntaxKey::ArrayType, SyntaxKey::TemplateType); if (typeNode != SyntaxKey::None) { - resolveStrongTypeAttribute(scope, typeNode, false, false); + resolveStrongTypeAttribute(scope, typeNode, false, false, false); //TypeAttributes typeAttributes = {}; //resolveTypeAttribute(scope, typeNode, typeAttributes, false, false); @@ -10633,12 +10711,12 @@ void Compiler :: compileVMT(BuildTreeWriter& writer, ClassScope& scope, SyntaxNo break; } case SyntaxKey::Constructor: - if (_logic->isRole(scope.info)) { + if (_logic->isRole(scope.info.header.flags)) { scope.raiseError(errIllegalConstructor, node); } break; case SyntaxKey::StaticMethod: - if (_logic->isRole(scope.info)) { + if (_logic->isRole(scope.info.header.flags)) { scope.raiseError(errIllegalStaticMethod, node); } break; @@ -10844,6 +10922,11 @@ void Compiler :: compileNestedClass(BuildTreeWriter& writer, ClassScope& scope, scope.save(); + // validate field types + if (scope.info.fields.count() > 0 || scope.info.statics.count() > 0) { + validateClassFields(scope, node); + } + BuildNode buildNode = writer.CurrentNode(); while (buildNode != BuildKey::Root) buildNode = buildNode.parentNode(); @@ -11075,7 +11158,7 @@ void Compiler::createPackageInfo(ModuleScopeBase* moduleScope, ManifestInfo& man MetaScope scope(nullptr, Scope::ScopeLevel::Namespace); scope.module = moduleScope->module; scope.moduleScope = moduleScope; - evalCollection(interpreter, scope, tempTree.readRoot(), true, false); + evalCollection(interpreter, scope, tempTree.readRoot(), {}, true, false); } void Compiler :: prepare(ModuleScopeBase* moduleScope, ForwardResolverBase* forwardResolver, @@ -11100,6 +11183,7 @@ void Compiler :: prepare(ModuleScopeBase* moduleScope, ForwardResolverBase* forw moduleScope->buildins.extMessageReference = safeMapReference(moduleScope, forwardResolver, EXT_MESSAGE_FORWARD); moduleScope->buildins.wrapperTemplateReference = safeMapReference(moduleScope, forwardResolver, WRAPPER_FORWARD); moduleScope->buildins.arrayTemplateReference = safeMapReference(moduleScope, forwardResolver, ARRAY_FORWARD); + moduleScope->buildins.constArrayTemplateReference = safeMapReference(moduleScope, forwardResolver, CONST_ARRAY_FORWARD); moduleScope->buildins.argArrayTemplateReference = safeMapReference(moduleScope, forwardResolver, VARIADIC_ARRAY_FORWARD); moduleScope->buildins.nullableTemplateReference = safeMapReference(moduleScope, forwardResolver, NULLABLE_FORWARD); @@ -11116,6 +11200,11 @@ void Compiler :: prepare(ModuleScopeBase* moduleScope, ForwardResolverBase* forw moduleScope->branchingInfo.trueRef = safeMapReference(moduleScope, forwardResolver, TRUE_FORWARD); moduleScope->branchingInfo.falseRef = safeMapReference(moduleScope, forwardResolver, FALSE_FORWARD); + if (_verbose) { + if (!moduleScope->buildins.constArrayTemplateReference) + _errorProcessor->info(infoMissingTemplate, CONST_ARRAY_FORWARD); + } + // cache the frequently used messages moduleScope->buildins.dispatch_message = encodeMessage( moduleScope->module->mapAction(DISPATCH_MESSAGE, 0, false), 1, 0); @@ -12216,7 +12305,7 @@ bool Compiler::Class :: isParentDeclared(SyntaxNode node) SyntaxNode child = parentNode.firstChild(); if (child != SyntaxKey::TemplateType && child != SyntaxKey::ParameterizedPostfix && child != SyntaxKey::None) { - ref_t parentRef = compiler->resolveStrongTypeAttribute(scope, child, true, false).typeRef; + ref_t parentRef = compiler->resolveStrongTypeAttribute(scope, child, true, false, false).typeRef; return scope.moduleScope->isDeclared(parentRef); } @@ -12259,7 +12348,7 @@ void Compiler::Class::declare(SyntaxNode node) // due to dynamic array implementation (auto-generated default constructor should be removed) compiler->generateClassDeclaration(scope, node, declaredFlags); - if (compiler->_logic->isRole(scope.info)) { + if (compiler->_logic->isRole(scope.info.header.flags)) { // class is its own class class scope.info.header.classRef = scope.reference; } @@ -12330,7 +12419,7 @@ void Compiler::Class::resolveClassPostfixes(SyntaxNode node, bool extensionMode) else if (!parentRef) { parentNode = current; - parentRef = compiler->resolveStrongTypeAttribute(scope, child, extensionMode, false).typeRef; + parentRef = compiler->resolveStrongTypeAttribute(scope, child, extensionMode, false, false).typeRef; } else if (!compiler->importTemplate(scope, child, node, false)) scope.raiseError(errUnknownTemplate, current); @@ -12342,7 +12431,7 @@ void Compiler::Class::resolveClassPostfixes(SyntaxNode node, bool extensionMode) else if (!parentRef) { parentNode = current; - parentRef = compiler->resolveStrongTypeAttribute(scope, child, extensionMode, false).typeRef; + parentRef = compiler->resolveStrongTypeAttribute(scope, child, extensionMode, false, false).typeRef; } else scope.raiseError(errInvalidSyntax, current); @@ -12715,6 +12804,9 @@ ObjectInfo Compiler::Expression :: compileReturning(SyntaxNode node, ExpressionA scope.raiseError(errInvalidOperation, node); } + if (retVal.kind == ObjectKind::TempLocal) + unboxRetVal(retVal); + retVal = boxArgument(retVal, !dynamicRequired && retVal.kind == ObjectKind::SelfBoxableLocal, true, false); @@ -12806,6 +12898,7 @@ ObjectInfo Compiler::Expression :: compile(SyntaxNode node, ref_t targetRef, Exp case SyntaxKey::ShlOperation: case SyntaxKey::ShrOperation: case SyntaxKey::NegateOperation: + case SyntaxKey::XorOperation: retVal = compileOperation(current, (int)current.key - OPERATOR_MAKS, targetRef, mode); break; case SyntaxKey::ExprValOperation: @@ -12817,8 +12910,8 @@ ObjectInfo Compiler::Expression :: compile(SyntaxNode node, ref_t targetRef, Exp retVal = compileSpecialOperation(/*current, */(int)current.key - OPERATOR_MAKS/*, targetRef*/); break; case SyntaxKey::AsyncOperation: - retVal = compileAsyncOperation(current, targetRef, paramMode || EAttrs::test(mode, EAttr::RetValExpected), dynamicRequired, false); - targetRef = 0; + retVal = compileAsyncOperation(current, /*targetRef*/0, paramMode || EAttrs::test(mode, EAttr::RetValExpected), dynamicRequired, false); + //targetRef = 0; break; case SyntaxKey::YieldOperation: compileYieldOperation(current); @@ -12897,7 +12990,7 @@ ObjectInfo Compiler::Expression :: compile(SyntaxNode node, ref_t targetRef, Exp compileSwitchOperation(current, EAttrs::test(mode, EAttr::NoDebugInfo)); break; case SyntaxKey::CollectionExpression: - retVal = compileCollection(current, mode); + retVal = compileCollection(current, mode, targetRef); break; case SyntaxKey::KeyValueExpression: retVal = compileKeyValue(current/*, mode*/); @@ -13168,7 +13261,7 @@ ObjectInfo Compiler::Expression :: compileMessageOperationR(SyntaxNode node, Syn if (messageNode.nextNode() == SyntaxKey::TemplateArg) { messageNode = messageNode.nextNode(); while (messageNode == SyntaxKey::TemplateArg) { - templateArgs[callContext.templateArgCount++] = compiler->resolveStrongTypeAttribute(scope, messageNode, false, false).typeRef; + templateArgs[callContext.templateArgCount++] = compiler->resolveStrongTypeAttribute(scope, messageNode, false, false, false).typeRef; messageNode = messageNode.nextNode(); } @@ -13578,7 +13671,7 @@ ObjectInfo Compiler::Expression :: compileAsyncOperation(SyntaxNode node, ref_t writer->newNode(BuildKey::YieldingOp, -scope.moduleScope->ptrSize); writer->newNode(BuildKey::Tape); - ObjectInfo exprVal = compile(node.firstChild(), retMode ? targetRef: currentField.typeInfo.typeRef, EAttr::AsyncOp | EAttr::StackUnsafe); + ObjectInfo exprVal = compile(node.firstChild(), retMode ? targetRef : currentField.typeInfo.typeRef, EAttr::AsyncOp | EAttr::StackUnsafe); // !! HOTFIX - add the temporal boxed variable whic hrequires unboxing as yield variables (to be resued) for (auto it = scope.tempLocals.start(); !it.eof(); ++it) { @@ -13617,8 +13710,6 @@ ObjectInfo Compiler::Expression :: compileAsyncOperation(SyntaxNode node, ref_t writer->appendNode(BuildKey::IncludeTry); // include the current try blocks again - - if (valueExpected) { // to ingnore the compatibility errors, replace Task with Task type, if applicable if (compiler->_logic->isCompatible(*scope.moduleScope, currentField.typeInfo, exprVal.typeInfo, false)) @@ -13753,6 +13844,10 @@ ObjectInfo Compiler::Expression::compileAssignOperation(SyntaxNode node, int ope BuildKey op = compiler->_logic->resolveOp(*scope.moduleScope, operatorId, arguments, argLen, dummy); // !! temporal : use weak operation when assigning outer variable requiring a special type of unboxing (to avoid duplicate boxing) if (op != BuildKey::None && loperand.mode != TargetMode::LocalAddressUnboxingRequired) { + // HTOFIX : mutable operation is not allowed for read-only loperand + if (isReadOnlyOperand(loperand.kind) && isLOperandMutable(operatorId)) + scope.raiseError(errAssigningRealOnly, node); + // box argument locally if required loperand = boxArgumentLocally(loperand, true, true); @@ -14395,7 +14490,7 @@ void Compiler::Expression :: compileSwitchOperation(SyntaxNode node, bool withou writer->newNode(BuildKey::SwitchOption); int operator_id = EQUAL_OPERATOR_ID; - ObjectInfo value = compiler->evalExpression(interpreter, scope, optionNode); + ObjectInfo value = compiler->evalExpression(interpreter, scope, optionNode, {}); arguments.clear(); arguments.add(loperand); arguments.add(value); @@ -14428,14 +14523,25 @@ void Compiler::Expression :: compileSwitchOperation(SyntaxNode node, bool withou writer->appendNode(BuildKey::OpenStatement); } -ObjectInfo Compiler::Expression::compileCollection(SyntaxNode node, ExpressionAttribute mode) +ObjectInfo Compiler::Expression :: compileCollection(SyntaxNode node, ExpressionAttribute mode, ref_t targetRef) { bool constOne = EAttrs::testAndExclude(mode, EAttr::ConstantExpr); + // HOTFIX : if the constant array was already declared, no need to create it again + if (!constOne || !node.arg.reference) { + Interpreter interpreter(scope.moduleScope, compiler->_logic); + ObjectInfo evalRetVal = compiler->evalExpression(interpreter, scope, node.parentNode(), { targetRef, 0, false, false, constOne }, true); + if (evalRetVal.kind == ObjectKind::Constant || evalRetVal.kind == ObjectKind::ConstArray) + return evalRetVal; + } + SyntaxNode current = node.firstChild(); - ObjectInfo objectInfo = compileObject(node.firstChild(), EAttr::NestedDecl); - if (objectInfo.kind != ObjectKind::Class) + ObjectInfo objectInfo = compileObject(node.firstChild(), EAttr::NestedDecl | EAttr::ProbeMode); + if (objectInfo.typeInfo.typeRef == V_AUTO && targetRef) + objectInfo.typeInfo = { targetRef }; + + if (objectInfo.kind != ObjectKind::Class || objectInfo.typeInfo.typeRef == V_AUTO) scope.raiseError(errInvalidOperation, node); ref_t collectionTypeRef = compiler->resolveStrongType(scope, objectInfo.typeInfo); @@ -15360,6 +15466,45 @@ ObjectInfo Compiler::Expression::declareTempLocal(ref_t typeRef, bool dynamicOnl } } +inline bool isNillable(ObjectInfo obj) +{ + return obj.kind == ObjectKind::Nil || obj.typeInfo.nillable; +} + +void Compiler::Expression :: handleNillableArguments(SyntaxNode node, ArgumentsInfo& arguments, int nillableArgs) +{ + bool warning = false; + + if (!compiler->checkNullableTypeFlag()) + return; + + CodeScope* codeScope = Scope::getScope(scope, Scope::ScopeLevel::Code); + + // box the arguments if required + int argMask = 1; + unsigned int argCount = arguments.count_pos(); + for (unsigned int i = 1; i < argCount; i++) { + auto arg = arguments[i]; + if (isNillable(arg) && !test(nillableArgs, argMask)) { + if (codeScope && codeScope->verifiedObjects.exist(arg)) { + // validate if the target was checked as not nil - no need to warn + } + else { + warning = true; + break; + } + } + + argMask <<= 1; + } + + if (warning) { + SyntaxNode messageNode = findMessageNode(node); + + scope.raiseWarning(WARNING_LEVEL_1, wrnNonNillableArgument, node); + } +} + void Compiler::Expression :: handleUnsupportedMessageCall(SyntaxNode node, mssg_t message, ref_t targetRef, bool weakTarget, bool strongResolved) { IdentifierString userFriendlyTypeName; @@ -15399,7 +15544,7 @@ void Compiler::Expression :: handleUnsupportedMessageCall(SyntaxNode node, mssg_ } else scope.raiseWarning(WARNING_LEVEL_1, wrnUnknownTypecast, node); } - else if (message == scope.moduleScope->buildins.refer_message) { + else if (message == scope.moduleScope->buildins.refer_message || message == scope.moduleScope->buildins.set_refer_message) { if (compiler->_strictTypeEnforcing && compiler->_logic->isClosedClass(*scope.moduleScope, targetRef)) { scope.raiseError(errUnsupportedOperator, node); } @@ -15560,7 +15705,17 @@ ObjectInfo Compiler::Expression :: compileMessageCall(SyntaxNode node, ObjectInf operation = BuildKey::SemiDirectCallOp; break; case MethodHint::ByIndex: - operation = BuildKey::SemiDirectCallOp; + if (compiler->_logic->isSealedClass(*scope.moduleScope, targetRef)) { + operation = BuildKey::DirectCallOp; + // HOTFIX : resolve the origin of the static method + if (test(resolution.message, STATIC_MESSAGE)) { + targetRef = compiler->_logic->resolveStaticMethodOrigin(*scope.moduleScope, targetRef, resolution.message); + + assert(targetRef != 0); + } + } + else operation = BuildKey::SemiDirectCallOp; + indexedCallMode = true; break; default: @@ -15574,6 +15729,9 @@ ObjectInfo Compiler::Expression :: compileMessageCall(SyntaxNode node, ObjectInf if (EAttrs::testAndExclude(mode.attrs, EAttr::StackUnsafe)) resolution.stackSafeAttr = 0; + + if (result.checkNillableArgs) + handleNillableArguments(node, arguments, result.nillableArgs); } else if (targetRef) { handleUnsupportedMessageCall(node, resolution.message, targetRef, @@ -15663,7 +15821,7 @@ ObjectInfo Compiler::Expression::compileOperation(SyntaxNode node, SyntaxNode rn { if (compiler->_evaluateOp) { Interpreter interpreter(scope.moduleScope, compiler->_logic); - ObjectInfo evalRetVal = compiler->evalExpression(interpreter, scope, node.parentNode(), true); + ObjectInfo evalRetVal = compiler->evalExpression(interpreter, scope, node.parentNode(), { expectedRef }, true); if (evalRetVal.kind != ObjectKind::Unknown) return evalRetVal; } @@ -15717,12 +15875,16 @@ ObjectInfo Compiler::Expression::compileAssigning(SyntaxNode loperand, SyntaxNod ObjectInfo exprVal = {}; + EAttr exprMode = EAttr::RetValExpected; + if (target.typeInfo.constant) + exprMode = exprMode| EAttr::ConstantExpr; + // HOTFIX : allow to assign ref argument in place ref_t targetRef = (target.kind == ObjectKind::LocalAddress && target.typeInfo.typeRef == V_WRAPPER) ? target.typeInfo.elementRef : compiler->resolveStrongType(scope, target.typeInfo); if (targetRef == V_AUTO) { // support auto attribute - exprVal = compile(roperand, 0, EAttr::RetValExpected); + exprVal = compile(roperand, 0, exprMode); if (resolveAutoType(exprVal, target)) { targetRef = compiler->resolveStrongType(scope, exprVal.typeInfo); @@ -15730,7 +15892,7 @@ ObjectInfo Compiler::Expression::compileAssigning(SyntaxNode loperand, SyntaxNod } else scope.raiseError(errInvalidOperation, roperand.parentNode()); } - else exprVal = compile(roperand, targetRef, EAttr::RetValExpected); + else exprVal = compile(roperand, targetRef, exprMode); if (target.kind == ObjectKind::Shortcut) { CodeScope* codeScope = Scope::getScope(scope, Scope::ScopeLevel::Code); @@ -15754,6 +15916,11 @@ ObjectInfo Compiler::Expression::compileAssigning(SyntaxNode loperand, SyntaxNod } } + // HOTFIX : if the expression result must be unboxed - do it before the operation + if (exprVal.kind == ObjectKind::TempLocal && isUnboxingRequiredForTempLocal(exprVal)) { + unboxArguments({}, EAttrs::test(mode, EAttr::Root)); + } + bool nillableOp = false; if (!compileAssigningOp(target, exprVal, nillableOp)) { switch (target.kind) { @@ -15939,7 +16106,7 @@ bool Compiler::Expression::writeObjectInfo(ObjectInfo info, bool allowMeta) return true; } -ObjectInfo Compiler::Expression::boxArgumentLocally(ObjectInfo info, +ObjectInfo Compiler::Expression :: boxArgumentLocally(ObjectInfo info, bool stackSafe, bool forced) { switch (info.kind) { @@ -15949,7 +16116,7 @@ ObjectInfo Compiler::Expression::boxArgumentLocally(ObjectInfo info, case ObjectKind::StaticField: case ObjectKind::StaticThreadField: if (forced) { - return boxLocally(info, stackSafe); + return boxLocally(info, stackSafe, false); } return info; case ObjectKind::ReadOnlyFieldAddress: @@ -15964,7 +16131,7 @@ ObjectInfo Compiler::Expression::boxArgumentLocally(ObjectInfo info, return retVal; } - else return boxLocally(info, stackSafe); + else return boxLocally(info, stackSafe, compiler->_logic->isReadOnly(*scope.moduleScope, info.typeInfo.typeRef) && !forced); case ObjectKind::StaticConstField: case ObjectKind::ClassStaticConstField: if (info.mode == TargetMode::BoxingPtr) { @@ -15976,6 +16143,62 @@ ObjectInfo Compiler::Expression::boxArgumentLocally(ObjectInfo info, } } +void Compiler::Expression :: unboxArgument(ObjectKey key, ObjectInfo temp) +{ + bool dummy = false; + + // unbox the temporal variable + if (temp.mode == TargetMode::LocalUnboxingRequired || temp.mode == TargetMode::LocalAddressUnboxingRequired) { + unboxArgumentLocaly(temp, key); + } + else if (temp.mode == TargetMode::RefUnboxingRequired) { + if (temp.kind == ObjectKind::LocalReference) { + temp.kind = ObjectKind::Local; + + compileAssigningOp({ ObjectKind::Local, temp.typeInfo, key.value2 }, temp, dummy); + } + else { + writeObjectInfo(temp); + writer->appendNode(BuildKey::Field); + compileAssigningOp( + { ObjectKind::Local, temp.typeInfo, key.value2 }, + { ObjectKind::Object, temp.typeInfo, 0 }, dummy); + } + } + else if (key.value1 == ObjectKind::RefLocal) { + writeObjectInfo(temp); + writer->appendNode(BuildKey::Field); + compileAssigningOp( + { ObjectKind::Local, temp.typeInfo, key.value2 }, + { ObjectKind::Object, temp.typeInfo, 0 }, dummy); + } + else if (key.value1 == ObjectKind::FieldAddress) { + unboxArgumentLocaly(temp, key); + } + else if (temp.mode == TargetMode::ConditionalUnboxingRequired) { + writeObjectInfo({ key.value1, temp.typeInfo, key.value2 }); + writer->newNode(BuildKey::StackCondOp); + compileAssigningOp({ key.value1, temp.typeInfo, key.value2 }, temp, dummy); + writer->closeNode(); + } + else compileAssigningOp({ key.value1, temp.typeInfo, key.value2 }, temp, dummy); +} + +void Compiler::Expression :: unboxRetVal(ObjectInfo retVal) +{ + // find the original variable + auto key = scope.tempLocals.retrieve({}, retVal.reference, [](ref_t reference, ObjectKey key, ObjectInfo) + { + return key.value2 == reference; + }); + + if (key.value1 != ObjectKind::Unknown) { + ObjectInfo temp = scope.tempLocals.get(key); + if (isUnboxingRequired(temp.mode)) + unboxArgument(key, temp); + } +} + ObjectInfo Compiler::Expression :: unboxArguments(ObjectInfo retVal, bool clearInfo) { // unbox the arguments if required @@ -15983,9 +16206,7 @@ ObjectInfo Compiler::Expression :: unboxArguments(ObjectInfo retVal, bool clearI bool dummy = false; for (auto it = scope.tempLocals.start(); !it.eof(); ++it) { ObjectInfo temp = *it; - - if (isUnboxingRequired(temp.mode)) - { + if (isUnboxingRequired(temp.mode)) { if (!resultSaved && retVal.kind != ObjectKind::Unknown) { // presave the result ObjectInfo tempResult = declareTempLocal(retVal.typeInfo.typeRef, false); @@ -15995,42 +16216,7 @@ ObjectInfo Compiler::Expression :: unboxArguments(ObjectInfo retVal, bool clearI resultSaved = true; } - // unbox the temporal variable - auto key = it.key(); - if (temp.mode == TargetMode::LocalUnboxingRequired || temp.mode == TargetMode::LocalAddressUnboxingRequired) { - unboxArgumentLocaly(temp, key); - } - else if (temp.mode == TargetMode::RefUnboxingRequired) { - if (temp.kind == ObjectKind::LocalReference) { - temp.kind = ObjectKind::Local; - - compileAssigningOp({ ObjectKind::Local, temp.typeInfo, key.value2 }, temp, dummy); - } - else { - writeObjectInfo(temp); - writer->appendNode(BuildKey::Field); - compileAssigningOp( - { ObjectKind::Local, temp.typeInfo, key.value2 }, - { ObjectKind::Object, temp.typeInfo, 0 }, dummy); - } - } - else if (key.value1 == ObjectKind::RefLocal) { - writeObjectInfo(temp); - writer->appendNode(BuildKey::Field); - compileAssigningOp( - { ObjectKind::Local, temp.typeInfo, key.value2 }, - { ObjectKind::Object, temp.typeInfo, 0 }, dummy); - } - else if (key.value1 == ObjectKind::FieldAddress) { - unboxArgumentLocaly(temp, key); - } - else if (temp.mode == TargetMode::ConditionalUnboxingRequired) { - writeObjectInfo({ key.value1, temp.typeInfo, key.value2 }); - writer->newNode(BuildKey::StackCondOp); - compileAssigningOp({ key.value1, temp.typeInfo, key.value2 }, temp, dummy); - writer->closeNode(); - } - else compileAssigningOp({ key.value1, temp.typeInfo, key.value2 }, temp, dummy); + unboxArgument(it.key(), temp); } } @@ -16326,6 +16512,11 @@ ObjectInfo Compiler::Expression :: compileBranchingOperation(SyntaxNode node, Ob op = compiler->_logic->resolveOp(*scope.moduleScope, operatorId, arguments, argLen, outputRef); if (op != BuildKey::None) { + if (hasToBePresaved(loperand)) { + loperand = unboxArguments(loperand, true); + } + else unboxArguments({}, true); + writeObjectInfo(loperand); if (branchVerification && operatorId == ELSE_OPERATOR_ID) @@ -16580,7 +16771,7 @@ ref_t Compiler::Expression::mapNested(ExpressionAttribute mode) if (owner) nestedRef = owner->reference; } - else if (EAttrs::testAndExclude(mode, EAttr::Root)) { + else if (EAttrs::testAndExclude(mode, EAttr::Root) && EAttrs::test(mode, EAttr::RetValExpected)) { MethodScope* ownerMeth = Scope::getScope(scope, Scope::ScopeLevel::Method); if (ownerMeth && ownerMeth->checkHint(MethodHint::Constant)) { ref_t dummyRef = 0; @@ -16658,7 +16849,7 @@ ObjectInfo Compiler::Expression :: compileOperation(SyntaxNode node, ArgumentsIn } if (operatorId == SET_INDEXER_OPERATOR_ID) { - if (isPrimitiveArray(arguments[0]) && compiler->_logic->isCompatible(*scope.moduleScope, { arguments[1] }, { loperand.typeInfo.elementRef }, false)) + if (CompilerLogic::isPrimitiveArrRef(arguments[0]) && compiler->_logic->isCompatible(*scope.moduleScope, { arguments[1] }, { loperand.typeInfo.elementRef }, false)) // HOTFIX : for the generic binary array, recognize the element type arguments[1] = V_ELEMENT; } @@ -16669,6 +16860,10 @@ ObjectInfo Compiler::Expression :: compileOperation(SyntaxNode node, ArgumentsIn ObjectInfo retVal = {}; if (op != BuildKey::None) { + // HTOFIX : mutable operation is not allowed for read-only loperand + if (isReadOnlyOperand(loperand.kind) && isLOperandMutable(operatorId)) + scope.raiseError(errAssigningRealOnly, node); + ObjectInfo roperand = {}; ObjectInfo ioperand = {}; @@ -16786,49 +16981,49 @@ ObjectInfo Compiler::Expression::compileNativeConversion(SyntaxNode node, Object source = boxArgumentLocally(source, false, false); switch (operationKey) { - case INT8_32_CONVERSION: - retVal = allocateResult(compiler->resolvePrimitiveType(*scope.moduleScope, { V_INT32 }, false)); + case INT8_32_CONVERSION: + retVal = allocateResult(compiler->resolvePrimitiveType(*scope.moduleScope, { V_INT32 }, false)); - writeObjectInfo(retVal); - writer->appendNode(BuildKey::SavingInStack, 0); + writeObjectInfo(retVal); + writer->appendNode(BuildKey::SavingInStack, 0); - writeObjectInfo(source); + writeObjectInfo(source); - writer->appendNode(BuildKey::ConversionOp, operationKey); - break; - case INT16_32_CONVERSION: - retVal = allocateResult(compiler->resolvePrimitiveType(*scope.moduleScope, { V_INT32 }, false)); + writer->appendNode(BuildKey::ConversionOp, operationKey); + break; + case INT16_32_CONVERSION: + retVal = allocateResult(compiler->resolvePrimitiveType(*scope.moduleScope, { V_INT32 }, false)); - writeObjectInfo(retVal); - writer->appendNode(BuildKey::SavingInStack, 0); + writeObjectInfo(retVal); + writer->appendNode(BuildKey::SavingInStack, 0); - writeObjectInfo(source); + writeObjectInfo(source); - writer->appendNode(BuildKey::ConversionOp, operationKey); - break; - case INT32_64_CONVERSION: - retVal = allocateResult(compiler->resolvePrimitiveType(*scope.moduleScope, { V_INT64 }, false)); + writer->appendNode(BuildKey::ConversionOp, operationKey); + break; + case INT32_64_CONVERSION: + retVal = allocateResult(compiler->resolvePrimitiveType(*scope.moduleScope, { V_INT64 }, false)); - writeObjectInfo(retVal); - writer->appendNode(BuildKey::SavingInStack, 0); + writeObjectInfo(retVal); + writer->appendNode(BuildKey::SavingInStack, 0); - writeObjectInfo(source); + writeObjectInfo(source); - writer->appendNode(BuildKey::ConversionOp, operationKey); - break; - case INT32_FLOAT64_CONVERSION: - retVal = allocateResult(compiler->resolvePrimitiveType(*scope.moduleScope, { V_FLOAT64 }, false)); + writer->appendNode(BuildKey::ConversionOp, operationKey); + break; + case INT32_FLOAT64_CONVERSION: + retVal = allocateResult(compiler->resolvePrimitiveType(*scope.moduleScope, { V_FLOAT64 }, false)); - writeObjectInfo(retVal); - writer->appendNode(BuildKey::SavingInStack, 0); + writeObjectInfo(retVal); + writer->appendNode(BuildKey::SavingInStack, 0); - writeObjectInfo(source); + writeObjectInfo(source); - writer->appendNode(BuildKey::ConversionOp, operationKey); - break; - default: - scope.raiseError(errInvalidOperation, node); - break; + writer->appendNode(BuildKey::ConversionOp, operationKey); + break; + default: + scope.raiseError(errInvalidOperation, node); + break; } return retVal; @@ -17145,7 +17340,7 @@ ObjectInfo Compiler::Expression::boxArgument(ObjectInfo info, bool stackSafe, bo return retVal; } -ObjectInfo Compiler::Expression::boxLocally(ObjectInfo info, bool stackSafe) +ObjectInfo Compiler::Expression::boxLocally(ObjectInfo info, bool stackSafe, bool noLocalUnboxing) { // allocating temporal variable ObjectInfo tempLocal = {}; @@ -17163,7 +17358,7 @@ ObjectInfo Compiler::Expression::boxLocally(ObjectInfo info, bool stackSafe) } else tempLocal = declareTempLocal(info.typeInfo.typeRef, false); - if (stackSafe) { + if (stackSafe && !noLocalUnboxing) { tempLocal.mode = TargetMode::LocalUnboxingRequired; scope.tempLocals.add({ info.kind, info.reference }, tempLocal); @@ -17298,6 +17493,14 @@ void Compiler::Expression::unboxOuterArgs() } } +bool Compiler::Expression :: isUnboxingRequiredForTempLocal(ObjectInfo tempLocal) +{ + ObjectKey key = { ObjectKind::RefLocal, tempLocal.reference }; + ObjectInfo temp = scope.tempLocals.get(key); + + return (temp.kind != ObjectKind::Unknown && isUnboxingRequired(temp.mode)); +} + void Compiler::Expression::convertIntLiteralForOperation(SyntaxNode node, int operatorId, ArgumentsInfo& messageArguments) { if (!DoesOperationSupportConvertableIntLiteral(operatorId)) @@ -17349,7 +17552,7 @@ ObjectInfo Compiler::Expression::boxArgumentInPlace(ObjectInfo info, ref_t targe compiler->_logic->defineClassInfo(*scope.moduleScope, argInfo, typeRef, false, true); ObjectInfo lenLocal = {}; - bool isBinaryArray = compiler->_logic->isEmbeddableArray(argInfo); + bool isBinaryArray = compiler->_logic->isEmbeddableArray(argInfo.header.flags); if (isBinaryArray) { int elementSize = -(int)argInfo.size; @@ -17382,7 +17585,7 @@ ObjectInfo Compiler::Expression::boxArgumentInPlace(ObjectInfo info, ref_t targe copyArray(*writer, elementSize); } - else if (compiler->_logic->isDynamic(argInfo)) { + else if (compiler->_logic->isDynamic(argInfo.header.flags)) { // get the length lenLocal = declareTempLocal(V_INT32, false); @@ -17428,7 +17631,7 @@ ObjectInfo Compiler::Expression::boxArgumentInPlace(ObjectInfo info, ref_t targe writer->appendNode(BuildKey::Assigning, tempLocal.argument); } - if (!compiler->_logic->isReadOnly(argInfo)) + if (!compiler->_logic->isReadOnly(argInfo.header.flags)) tempLocal.mode = condBoxing ? TargetMode::ConditionalUnboxingRequired : TargetMode::UnboxingRequired; return tempLocal; @@ -17582,7 +17785,7 @@ void Compiler::MetaExpression::generateObject(SyntaxTreeWriter& writer, SyntaxNo void Compiler::MetaExpression::generateNameOperation(SyntaxTreeWriter& writer, SyntaxNode node) { - ObjectInfo info = compiler->evalExpression(*interpreter, *scope, node, true, true); + ObjectInfo info = compiler->evalExpression(*interpreter, *scope, node, {}, true, true); if (info.kind == ObjectKind::StringLiteral) { writer.newNode(SyntaxKey::Object); @@ -17816,7 +18019,7 @@ void Compiler::LambdaClosure :: declareClosureMessage(MethodScope& methodScope, SyntaxNode outputNode = node.findChild(SyntaxKey::ClosureReturnType); if (outputNode != SyntaxKey::None) { TypeAttributes typeAttr = {}; - outputInfo = compiler->resolveTypeAttribute(scope, outputNode, typeAttr, false, false); + outputInfo = compiler->resolveTypeAttribute(scope, outputNode, typeAttr, false, false, false); methodScope.info.outputRef = outputInfo.typeRef; methodScope.info.nillableArgs = outputInfo.nillable; diff --git a/elenasrc3/elc/compiler.h b/elenasrc3/elc/compiler.h index 64c0cb85d..d8b6aaa64 100644 --- a/elenasrc3/elc/compiler.h +++ b/elenasrc3/elc/compiler.h @@ -1594,6 +1594,7 @@ namespace elena_lang void handleNillableMessageCall(SyntaxNode node, mssg_t message, ObjectInfo target); void handleNillableReturn(SyntaxNode node, ObjectInfo target); void handleNillableAssign(SyntaxNode node, ObjectInfo target); + void handleNillableArguments(SyntaxNode node, ArgumentsInfo& arguments, int nillableArgs); ObjectInfo compileMessageCall(SyntaxNode node, ObjectInfo target, MessageCallContext& context, MessageResolution resolution, ArgumentsInfo& arguments, ExpressionAttributes mode); @@ -1619,7 +1620,7 @@ namespace elena_lang ObjectInfo boxArgument(ObjectInfo info, bool stackSafe, bool boxInPlace, bool allowingRefArg, ref_t targetRef = 0); ObjectInfo boxArgumentLocally(ObjectInfo info, bool stackSafe, bool forced); - ObjectInfo boxLocally(ObjectInfo info, bool stackSafe); + ObjectInfo boxLocally(ObjectInfo info, bool stackSafe, bool noLocalUnboxing); ObjectInfo boxPtrLocally(ObjectInfo info); ObjectInfo boxArgumentInPlace(ObjectInfo info, ref_t targetRef = 0); ObjectInfo boxRefArgumentLocallyInPlace(ObjectInfo info, ref_t targetRef = 0); @@ -1627,6 +1628,9 @@ namespace elena_lang ObjectInfo boxVariadicArgument(ObjectInfo info); ObjectInfo unboxArguments(ObjectInfo retVal, bool clearInfo); + + void unboxRetVal(ObjectInfo retVal); + void unboxArgument(ObjectKey key, ObjectInfo temp); void unboxArgumentLocaly(ObjectInfo tempLocal, ObjectKey targetKey); void unboxOuterArgs(); @@ -1660,6 +1664,8 @@ namespace elena_lang void convertIntLiteralForOperation(SyntaxNode node, int operatorId, ArgumentsInfo& messageArguments); + bool isUnboxingRequiredForTempLocal(ObjectInfo tempLocal); + public: bool writeObjectInfo(ObjectInfo info, bool allowMeta = false); void writeObjectInfo(ObjectInfo info, SyntaxNode node) @@ -1677,7 +1683,7 @@ namespace elena_lang ObjectInfo compile(SyntaxNode node, ref_t targetRef, ExpressionAttribute mode); ObjectInfo compileObject(SyntaxNode node, ExpressionAttribute mode); - ObjectInfo compileCollection(SyntaxNode node, ExpressionAttribute mode); + ObjectInfo compileCollection(SyntaxNode node, ExpressionAttribute mode, ref_t targetRef); ObjectInfo compileTupleCollection(SyntaxNode node, ref_t targetRef); ObjectInfo compileKeyValue(SyntaxNode node/*, ExpressionAttribute mode*/); ObjectInfo compileClosureOperation(SyntaxNode node, ref_t targetRef); @@ -1795,7 +1801,7 @@ namespace elena_lang static int defineFieldSize(Scope& scope, ObjectInfo info); - ObjectInfo defineArrayType(Scope& scope, ObjectInfo info, bool declarationMode); + ObjectInfo defineArrayType(Scope& scope, ObjectInfo info, bool declarationMode, bool readOnly); ref_t defineArrayType(Scope& scope, ref_t elementRef, bool declarationMode); ref_t resolveStrongType(Scope& scope, TypeInfo typeInfo, bool declarationMode = false); @@ -1811,17 +1817,17 @@ namespace elena_lang //ref_t resolveClosure(Scope& scope, mssg_t closureMessage, ref_t outputRef); ref_t resolveStateMachine(Scope& scope, ref_t templateRef, ref_t stateRef); ref_t resolveWrapperTemplate(ModuleScopeBase& moduleScope, ref_t elementRef, bool declarationMode); - ref_t resolveArrayTemplate(ModuleScopeBase& moduleScope, ref_t elementRef, bool nullableElement, bool declarationMode); + ref_t resolveArrayTemplate(ModuleScopeBase& moduleScope, ref_t elementRef, bool nullableElement, bool declarationMode, bool constAttr); //ref_t resolveNullableTemplate(ModuleScopeBase& moduleScope, ustr_t ns, ref_t elementRef, bool declarationMode); ref_t resolveArgArrayTemplate(ModuleScopeBase& moduleScope, ref_t elementRef, bool declarationMode); ref_t resolveTupleClass(Scope& scope, SyntaxNode node, ArgumentsInfo& items); int resolveSize(Scope& scope, SyntaxNode node); TypeInfo resolveTypeAttribute(Scope& scope, SyntaxNode node, TypeAttributes& attributes, - bool declarationMode, bool allowRole); + bool declarationMode, bool allowRole, bool constAttr); TypeInfo resolveTypeScope(Scope& scope, SyntaxNode node, TypeAttributes& attributes, - bool declarationMode, bool allowRole); - TypeInfo resolveStrongTypeAttribute(Scope& scope, SyntaxNode node, bool declarationMode, bool allowRole); + bool declarationMode, bool allowRole, bool constAttr); + TypeInfo resolveStrongTypeAttribute(Scope& scope, SyntaxNode node, bool declarationMode, bool allowRole, bool constAttr, bool allowPrimitive = false); ref_t retrieveTemplate(NamespaceScope& scope, SyntaxNode node, List& parameters, ustr_t prefix, SyntaxKey argKey, ustr_t postFix); @@ -1975,9 +1981,9 @@ namespace elena_lang ObjectInfo evalOperation(Interpreter& interpreter, Scope& scope, SyntaxNode node, ref_t operator_id, bool ignoreErrors = false); ObjectInfo evalBoolOperation(Interpreter& interpreter, Scope& scope, SyntaxNode node, ref_t operator_id, bool ignoreErrors = false); - ObjectInfo evalExpression(Interpreter& interpreter, Scope& scope, SyntaxNode node, bool ignoreErrors = false, bool resolveMode = true); - ObjectInfo evalObject(/*Interpreter& interpreter, */Scope& scope, SyntaxNode node); - ObjectInfo evalCollection(Interpreter& interpreter, Scope& scope, SyntaxNode node, bool anonymousOne, bool ignoreErrors); + ObjectInfo evalExpression(Interpreter& interpreter, Scope& scope, SyntaxNode node, TypeInfo targetInfo, bool ignoreErrors = false, bool resolveMode = true); + ObjectInfo evalObject(/*Interpreter& interpreter, */Scope& scope, SyntaxNode node, ExpressionAttribute exprMode = ExpressionAttribute::None); + ObjectInfo evalCollection(Interpreter& interpreter, Scope& scope, SyntaxNode node, TypeInfo targetInfo, 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, bool metaMode = false); diff --git a/elenasrc3/elc/compilerlogic.cpp b/elenasrc3/elc/compilerlogic.cpp index 05d6025dc..b96bd279a 100644 --- a/elenasrc3/elc/compilerlogic.cpp +++ b/elenasrc3/elc/compilerlogic.cpp @@ -3,7 +3,7 @@ // // This file contains ELENA compiler logic class implementation. // -// (C)2021-2025, by Aleksey Rakov +// (C)2021-2026, by Aleksey Rakov // (C)2024, by ELENA-LANG Org //--------------------------------------------------------------------------- @@ -977,6 +977,9 @@ bool CompilerLogic :: validateFieldAttribute(ref_t attribute, FieldAttributes& a attrs.typeInfo = { V_AUTO }; attrs.isAuto = true; break; + case V_IGNOREDUPLICATE: + attrs.ignoreDuplicates = true; + break; default: return false; } @@ -1185,6 +1188,9 @@ bool CompilerLogic :: validateExpressionAttribute(ref_t attrValue, ExpressionAtt case V_HEAPALLOCATED: attrs |= ExpressionAttribute::HeapAllocated; return true; + case V_CONST: + attrs |= ExpressionAttribute::ReadOnly; + return true; default: return false; } @@ -1300,16 +1306,16 @@ static inline bool existsNormalMethod(ModuleScopeBase& scope, ClassInfo& info, m void CompilerLogic :: validateClassDeclaration(ModuleScopeBase& scope, ErrorProcessorBase* errorProcessor, ClassInfo& info, bool& emptyStructure, bool& dispatcherNotAllowed, bool& withAbstractMethods, mssg_t& mixedUpVariadicMessage) { - bool abstractOne = isAbstract(info); - bool withVariadic = withVariadicsMethods(info); + bool abstractOne = isAbstract(info.header.flags); + bool withVariadic = withVariadicsMethods(info.header.flags); // check abstract methods if (!abstractOne || withVariadic) { for (auto it = info.methods.start(); !it.eof(); ++it) { auto mssg = it.key(); - auto methodInfo = *it; + //auto methodInfo = *it; - if (!abstractOne && test(methodInfo.hints, (ref_t)MethodHint::Abstract)) { + if (!abstractOne && test(/*methodInfo*/(*it).hints, (ref_t)MethodHint::Abstract)) { IdentifierString messageName; ByteCodeUtil::resolveMessageName(messageName, scope.module, mssg); @@ -1345,7 +1351,7 @@ bool CompilerLogic :: validateAutoType(ModuleScopeBase& scope, TypeInfo& typeInf if (!defineClassInfo(scope, info, typeInfo.typeRef)) return false; - while (isRole(info)) { + while (isRole(info.header.flags)) { typeInfo = { info.header.parentRef }; if (!defineClassInfo(scope, info, typeInfo.typeRef)) @@ -1375,62 +1381,54 @@ ref_t CompilerLogic :: defineByRefSignature(ModuleScopeBase& scope, ref_t signRe return scope.module->mapSignature(targetSignatures, len, false); } -bool CompilerLogic :: isRole(ClassInfo& info) +bool CompilerLogic :: isRole(ref_t flags) { - return test(info.header.flags, elRole); + return test(flags, elRole); } -bool CompilerLogic :: isAbstract(ClassInfo& info) +bool CompilerLogic :: isAbstract(ref_t flags) { - return test(info.header.flags, elAbstract); + return test(flags, elAbstract); } -bool CompilerLogic :: withVariadicsMethods(ClassInfo& info) +bool CompilerLogic :: withVariadicsMethods(ref_t flags) { - return test(info.header.flags, elWithVariadics); + return test(flags, elWithVariadics); } -bool CompilerLogic :: isReadOnly(ClassInfo& info) +bool CompilerLogic :: isReadOnly(ref_t flags) { - return test(info.header.flags, elReadOnlyRole); + return test(flags, elReadOnlyRole); } bool CompilerLogic :: isEmbeddableArray(ModuleScopeBase& scope, ref_t reference) { - if (scope.cachedEmbeddableArrays.exist(reference)) - return scope.cachedEmbeddableArrays.get(reference); - - ClassInfo info; - if (defineClassInfo(scope, info, reference, true)) { - auto retVal = isEmbeddableArray(info); - - scope.cachedEmbeddableArrays.add(reference, retVal); - - return retVal; - } + return isEmbeddableArray(getFlags(scope, reference)); +} - return false; +bool CompilerLogic :: isReadOnly(ModuleScopeBase& scope, ref_t reference) +{ + return isReadOnly(getFlags(scope, reference)); } -bool CompilerLogic :: isDynamic(ClassInfo& info) +bool CompilerLogic :: isDynamic(ref_t flags) { - return test(info.header.flags, elDynamicRole | elWrapper); + return test(flags, elDynamicRole | elWrapper); } -bool CompilerLogic :: isEmbeddableArray(ClassInfo& info) +bool CompilerLogic :: isEmbeddableArray(ref_t flags) { - return test(info.header.flags, elDynamicRole | elStructureRole | elWrapper); + return test(flags, elDynamicRole | elStructureRole | elWrapper); } -bool CompilerLogic :: isEmbeddableStruct(ClassInfo& info) +bool CompilerLogic :: isEmbeddableStruct(ref_t flags) { - return test(info.header.flags, elStructureRole) - && !test(info.header.flags, elDynamicRole); + return test(flags, elStructureRole) && !test(flags, elDynamicRole); } -bool CompilerLogic :: isNumericData(ClassInfo& info) +bool CompilerLogic :: isNumericData(ref_t flags) { - int dataMask = info.header.flags & elDebugMask; + int dataMask = flags & elDebugMask; return dataMask == elDebugDWORD || dataMask == elDebugQWORD || dataMask == elDebugFLOAT64; } @@ -1440,142 +1438,97 @@ bool CompilerLogic :: isEmbeddable(ModuleScopeBase& scope, TypeInfo typeInfo) if (typeInfo.nillable) return false; - if (scope.cachedEmbeddables.exist(typeInfo.typeRef)) - return scope.cachedEmbeddables.get(typeInfo.typeRef); - - ClassInfo info; - if (defineClassInfo(scope, info, typeInfo.typeRef, true)) { - auto retVal = isEmbeddable(info); - - scope.cachedEmbeddables.add(typeInfo.typeRef, retVal); - - return retVal; - } - - return false; + return isEmbeddable(getFlags(scope, typeInfo.typeRef)); } -bool CompilerLogic :: isEmbeddable(ClassInfo& info) +bool CompilerLogic :: isEmbeddable(ref_t flags) { - if (test(info.header.flags, elDynamicRole)) { - return isEmbeddableArray(info); + if (test(flags, elDynamicRole)) { + return isEmbeddableArray(flags); } - else return isEmbeddableStruct(info); + else return isEmbeddableStruct(flags); } -bool CompilerLogic :: isEmbeddableAndReadOnly(ClassInfo& info) +bool CompilerLogic :: isEmbeddableAndReadOnly(ref_t flags) { - return isReadOnly(info) && isEmbeddable(info); + return isReadOnly(flags) && isEmbeddable(flags); } -bool CompilerLogic::isEmbeddableAndReadOnly(ModuleScopeBase& scope, TypeInfo typeInfo) +ref_t CompilerLogic :: getFlags(ModuleScopeBase& scope, ref_t reference) { - if (typeInfo.nillable) - return false; - - if (scope.cachedEmbeddableReadonlys.exist(typeInfo.typeRef)) - return scope.cachedEmbeddableReadonlys.get(typeInfo.typeRef); - - ClassInfo info; - if (defineClassInfo(scope, info, typeInfo.typeRef, true)) { - auto retVal = isEmbeddableAndReadOnly(info); + ref_t flags = 0; + if (!scope.cachedFlags.exist(reference)) { + ClassInfo info; + if (defineClassInfo(scope, info, reference, true)) { + flags = info.header.flags; - scope.cachedEmbeddableReadonlys.add(typeInfo.typeRef, retVal); + scope.cachedFlags.add(reference, flags); - return retVal; + return flags; + } + else return 0; } - - return false; + else return scope.cachedFlags.get(reference); } -bool CompilerLogic :: isEmbeddableStruct(ModuleScopeBase& scope, TypeInfo typeInfo) +bool CompilerLogic :: isEmbeddableAndReadOnly(ModuleScopeBase& scope, TypeInfo typeInfo) { if (typeInfo.nillable) return false; - if (scope.cachedEmbeddableStructs.exist(typeInfo.typeRef)) - return scope.cachedEmbeddableStructs.get(typeInfo.typeRef); - - ClassInfo info; - if (defineClassInfo(scope, info, typeInfo.typeRef, true)) { - auto retVal = isEmbeddableStruct(info); - - scope.cachedEmbeddableStructs.add(typeInfo.typeRef, retVal); + return isEmbeddableAndReadOnly(getFlags(scope, typeInfo.typeRef)); +} - return retVal; - } +bool CompilerLogic :: isEmbeddableStruct(ModuleScopeBase& scope, TypeInfo typeInfo) +{ + if (typeInfo.nillable) + return false; - return false; + return isEmbeddableStruct(getFlags(scope, typeInfo.typeRef)); } -bool CompilerLogic :: isStacksafeArg(ClassInfo& info) +bool CompilerLogic :: isStacksafeArg(ref_t flags) { - if (test(info.header.flags, elDynamicRole)) { - return isEmbeddableArray(info); + if (test(flags, elDynamicRole)) { + return isEmbeddableArray(flags); } - else return isEmbeddable(info); + else return isEmbeddable(flags); } bool CompilerLogic :: isStacksafeArg(ModuleScopeBase& scope, ref_t reference) { - if (scope.cachedStacksafeArgs.exist(reference)) - return scope.cachedStacksafeArgs.get(reference); - - ClassInfo info; - if (defineClassInfo(scope, info, reference, true)) { - auto retVal = isStacksafeArg(info); - - scope.cachedStacksafeArgs.add(reference, retVal); - - return retVal; - } - - return false; + return isStacksafeArg(getFlags(scope, reference)); } bool CompilerLogic :: isWrapper(ModuleScopeBase& scope, ref_t reference) { - if (scope.cachedWrappers.exist(reference)) - return scope.cachedWrappers.get(reference); - - ClassInfo info; - if (defineClassInfo(scope, info, reference, true)) { - auto retVal = isWrapper(info); - - scope.cachedWrappers.add(reference, retVal); - - return retVal; - } - - return false; + return isWrapper(getFlags(scope, reference)); } -bool CompilerLogic :: isWrapper(ClassInfo& info) +bool CompilerLogic :: isWrapper(ref_t flags) { - return test(info.header.flags, elWrapper) - && !test(info.header.flags, elDynamicRole); + return test(flags, elWrapper) + && !test(flags, elDynamicRole); } bool CompilerLogic ::isClosedClass(ModuleScopeBase& scope, ref_t reference) { - if (scope.cachedClosed.exist(reference)) - return scope.cachedClosed.get(reference); - - ClassInfo info; - if (defineClassInfo(scope, info, reference, true)) { - auto retVal = isClosedClass(info); - - scope.cachedClosed.add(reference, retVal); + return isClosedClass(getFlags(scope, reference)); +} - return retVal; - } +bool CompilerLogic :: isClosedClass(ref_t flags) +{ + return test(flags, elClosed); +} - return false; +bool CompilerLogic :: isSealedClass(ModuleScopeBase& scope, ref_t reference) +{ + return isSealedClass(getFlags(scope, reference)); } -bool CompilerLogic :: isClosedClass(ClassInfo& info) +bool CompilerLogic :: isSealedClass(ref_t flags) { - return test(info.header.flags, elClosed); + return test(flags, elSealed); } bool CompilerLogic :: isMultiMethod(/*ClassInfo& info, */MethodInfo& methodInfo) @@ -1625,7 +1578,7 @@ void CompilerLogic :: tweakClassFlags(ModuleScopeBase& scope, ref_t classRef, Cl } } - if (isEmbeddableArray(info)) { + if (isEmbeddableArray(info.header.flags)) { auto inner = *info.fields.start(); switch (inner.typeInfo.typeRef) { case V_INT32ARRAY: @@ -1638,7 +1591,7 @@ void CompilerLogic :: tweakClassFlags(ModuleScopeBase& scope, ref_t classRef, Cl break; } } - else if (isWrapper(info)) { + else if (isWrapper(info.header.flags)) { auto inner = *info.fields.start(); switch (inner.typeInfo.typeRef) { case V_INT32: @@ -1679,9 +1632,9 @@ void CompilerLogic :: tweakClassFlags(ModuleScopeBase& scope, ref_t classRef, Cl // verify if it is a weak interface (an interface without output type specified) bool isWeakInterface = true; for (auto it = info.methods.start(); !it.eof(); ++it) { - auto methodInfo = *it; + ref_t outputRef = (*it).outputRef; - if (!methodInfo.inherited && methodInfo.outputRef && methodInfo.outputRef != classRef) { + if (!(*it).inherited && outputRef && outputRef != classRef) { isWeakInterface = false; break; } @@ -1962,13 +1915,13 @@ SizeInfo CompilerLogic :: defineStructSize(ClassInfo& info) { SizeInfo sizeInfo = { 0, test(info.header.flags, elReadOnlyRole), false }; - if (isEmbeddableStruct(info)) { + if (isEmbeddableStruct(info.header.flags)) { sizeInfo.size = info.size; - sizeInfo.numeric = isNumericData(info); + sizeInfo.numeric = isNumericData(info.header.flags); return sizeInfo; } - else if (isEmbeddableArray(info)) { + else if (isEmbeddableArray(info.header.flags)) { sizeInfo.size = info.size; return sizeInfo; @@ -2004,7 +1957,7 @@ ref_t CompilerLogic :: definePrimitiveArray(ModuleScopeBase& scope, ref_t elemen if (!defineClassInfo(scope, info, elementRef, true)) return 0; - if (isEmbeddableStruct(info) && structOne) { + if (isEmbeddableStruct(info.header.flags) && structOne) { if (isCompatible(scope, { V_INT8 }, { elementRef }, true) && info.size == 1) return V_INT8ARRAY; @@ -2299,7 +2252,7 @@ mssg_t CompilerLogic :: resolveMultimethod(ModuleScopeBase& scope, mssg_t weakMe ClassInfo info; if (defineClassInfo(scope, info, targetRef)) { - if (isStacksafeArg(info)) + if (isStacksafeArg(info.header.flags)) stackSafeAttr |= 1; // check if it is non public message @@ -2512,6 +2465,7 @@ bool CompilerLogic :: checkMethod(ClassInfo& info, mssg_t message, CheckMethodRe result.stackSafe = test(methodInfo.hints, (ref_t)MethodHint::Stacksafe); result.nillableArgs = methodInfo.nillableArgs; + result.checkNillableArgs = test(methodInfo.nillableArgs, EnforcedNillableArgs); result.byRefHandler = methodInfo.byRefHandler; if (test(methodInfo.hints, (ref_t)MethodHint::Constant)) { @@ -2612,9 +2566,7 @@ bool CompilerLogic :: isNeedVerification(ClassInfo& info, VirtualMethodList& imp { // HOTFIX : Make sure the multi-method methods have the same output type as generic one for (auto it = implicitMultimethods.start(); !it.eof(); it++) { - auto vm = *it; - - mssg_t message = vm.message; + mssg_t message = (*it).message; auto methodInfo = info.methods.get(message); ref_t outputRef = methodInfo.outputRef; @@ -2662,8 +2614,7 @@ ref_t CompilerLogic :: generateOverloadList(CompilerBase* compiler, ModuleScopeB // sort the overloadlist CachedList list; for (auto m_it = methods.start(); !m_it.eof(); ++m_it) { - auto methodInfo = *m_it; - if (methodInfo.multiMethod == message) { + if ((*m_it).multiMethod == message) { bool added = false; mssg_t omsg = m_it.key(); pos_t len = list.count_pos(); @@ -2755,10 +2706,9 @@ void CompilerLogic :: generateVirtualDispatchMethod(ModuleScopeBase& scope, ref_ scope.loadClassInfo(info, parentRef); for (auto it = info.methods.start(); !it.eof(); ++it) { auto mssg = it.key(); - auto methodInfo = *it; - if (test(methodInfo.hints, (ref_t)MethodHint::Abstract)) { - methods.add({ mssg, methodInfo.outputRef }); + if (test((*it).hints, (ref_t)MethodHint::Abstract)) { + methods.add({ mssg, (*it).outputRef }); } } } @@ -3102,7 +3052,7 @@ ref_t CompilerLogic :: retrievePrimitiveType(ModuleScopeBase& scope, ref_t refer if (!scope.loadClassInfo(info, reference)) return 0; - if (isWrapper(info)) { + if (isWrapper(info.header.flags)) { auto inner = *info.fields.start(); if (isPrimitiveRef(inner.typeInfo.typeRef)) @@ -3250,3 +3200,25 @@ bool CompilerLogic :: validateDispatcherType(ClassInfo& classInfo) return false; } + + +ref_t CompilerLogic :: resolveStaticMethodOrigin(ModuleScopeBase& scope, ref_t targetRef, mssg_t staticMethod) +{ + ref_t originRef = targetRef; + + while (originRef) { + ClassInfo info; + if (!defineClassInfo(scope, info, originRef)) + return 0; + + if (!info.methods.exist(staticMethod)) + return 0; + + if (!info.methods.get(staticMethod).inherited) + return originRef; + + originRef = info.header.parentRef; + } + + return 0; +} \ No newline at end of file diff --git a/elenasrc3/elc/compilerlogic.h b/elenasrc3/elc/compilerlogic.h index ad26e633c..9bdb0eb9e 100644 --- a/elenasrc3/elc/compilerlogic.h +++ b/elenasrc3/elc/compilerlogic.h @@ -3,7 +3,7 @@ // // This file contains ELENA compiler logic class. // -// (C)2021-2025, by Aleksey Rakov +// (C)2021-2026, by Aleksey Rakov //--------------------------------------------------------------------------- #ifndef COMPILERLOGIC_H @@ -28,6 +28,7 @@ namespace elena_lang bool withVariadicDispatcher; bool withCustomDispatcher; bool throwOp; + bool checkNillableArgs; int nillableArgs; mssg_t byRefHandler; @@ -92,6 +93,8 @@ namespace elena_lang void loadOperations(); + ref_t getFlags(ModuleScopeBase& scope, ref_t reference); + public: BuildKey resolveOp(ModuleScopeBase& scope, int operatorId, ref_t* arguments, size_t length, ref_t& outputRef); BuildKey resolveNewOp(ModuleScopeBase& scope, ref_t loperand, ref_t* arguments, pos_t length); @@ -125,33 +128,37 @@ namespace elena_lang mssg_t defineTryDispatcher(ModuleScopeBase& scope/*, mssg_t message*/); ref_t defineByRefSignature(ModuleScopeBase& scope, ref_t signRef, ref_t resultRef); - bool isRole(ClassInfo& info); - bool isAbstract(ClassInfo& info); - bool isReadOnly(ClassInfo& info); - bool withVariadicsMethods(ClassInfo& info); + bool isRole(ref_t flags); + bool isAbstract(ref_t flags); + bool isReadOnly(ref_t flags); + bool withVariadicsMethods(ref_t flags); + + bool isNumericData(ref_t flags); - bool isNumericData(ClassInfo& info); + bool isReadOnly(ModuleScopeBase& scope, ref_t reference); - bool isDynamic(ClassInfo& info); - bool isEmbeddableArray(ClassInfo& info); + bool isDynamic(ref_t flags); + bool isEmbeddableArray(ref_t flags); bool isEmbeddableArray(ModuleScopeBase& scope, ref_t reference); - bool isEmbeddableStruct(ClassInfo& info); + bool isEmbeddableStruct(ref_t flags); bool isEmbeddableStruct(ModuleScopeBase& scope, TypeInfo typeInfo); bool isEmbeddableAndReadOnly(ModuleScopeBase& scope, TypeInfo typeInfo); - bool isEmbeddableAndReadOnly(ClassInfo& info); + bool isEmbeddableAndReadOnly(ref_t flags); bool isEmbeddable(ModuleScopeBase& scope, TypeInfo typeInfo); - bool isEmbeddable(ClassInfo& info); + bool isEmbeddable(ref_t flags); bool isWrapper(ModuleScopeBase& scope, ref_t reference); - bool isWrapper(ClassInfo& info); + bool isWrapper(ref_t flags); bool isStacksafeArg(ModuleScopeBase& scope, ref_t reference); - bool isStacksafeArg(ClassInfo& info); + bool isStacksafeArg(ref_t flags); - bool isClosedClass(ClassInfo& info); + bool isClosedClass(ref_t flags); bool isClosedClass(ModuleScopeBase& scope, ref_t reference); + bool isSealedClass(ref_t flags); + bool isSealedClass(ModuleScopeBase& scope, ref_t reference); bool isMultiMethod(/*ClassInfo& info, */MethodInfo& methodInfo); @@ -233,6 +240,8 @@ namespace elena_lang virtual ref_t resolveExtensionTemplateByTemplateArgs(ModuleScopeBase& scope, CompilerBase* compiler, ustr_t pattern, /*ustr_t ns, */size_t argumentLen, ref_t* arguments, ExtensionMap* outerExtensionList); + ref_t resolveStaticMethodOrigin(ModuleScopeBase& scope, ref_t targetRef, mssg_t staticMethod); + bool isValidType(ModuleScopeBase& scope, ref_t classReference, bool ignoreUndeclared); pos_t definePadding(ModuleScopeBase& scope, pos_t offset, pos_t size); diff --git a/elenasrc3/elc/compiling.cpp b/elenasrc3/elc/compiling.cpp index 56cd2624a..a1dd9f60d 100644 --- a/elenasrc3/elc/compiling.cpp +++ b/elenasrc3/elc/compiling.cpp @@ -3,7 +3,7 @@ // // This file contains the compiling processor body // -// (C)2021-2025, by Aleksey Rakov +// (C)2021-2026, by Aleksey Rakov //--------------------------------------------------------------------------- #include "elena.h" diff --git a/elenasrc3/elc/errors.h b/elenasrc3/elc/errors.h index 971567859..7788b6443 100644 --- a/elenasrc3/elc/errors.h +++ b/elenasrc3/elc/errors.h @@ -107,6 +107,7 @@ namespace elena_lang constexpr auto wrnMsgUnassignedVariable = "\n%s(%d:%d): warning 428: an unassigned variable - '%s'\n"; constexpr auto wrnMsgLessAccessible = "\n%s(%d:%d): warning 429: the returning type is less accessible than '%s'\n"; constexpr auto wrnMsgUnknownModule = "\n%s(%d:%d): warning 430: Unknown module '%s'\n"; + constexpr auto wrnMsgNonNillableArgument = "\n%s(%d:%d): warning 414: A nillable argument is not supported by the message signature\n"; constexpr auto wrnMsgSyntaxFileNotFound = "\nwarning 500: cannot open syntax file '%s'\n"; constexpr auto wrnMsgInvalidConfig = "\nwarning 501: invalid or unknown config file %s\n"; @@ -143,6 +144,7 @@ namespace elena_lang constexpr auto infoMsgInternalDefConstructor = "\ninfo 710: default constructor cannot be internal\n"; constexpr auto infoMsgMessageInfo = "\ninfo 711: message: %s\n"; constexpr auto infoMsgSourceClass = "info 712: source class: %s\n"; + constexpr auto infoMsgMissingTemplate = "info 713: template %s is not defined\n"; } // _ELENA_ diff --git a/elenasrc3/elc/messages.h b/elenasrc3/elc/messages.h index 159eec47a..bcffa9221 100644 --- a/elenasrc3/elc/messages.h +++ b/elenasrc3/elc/messages.h @@ -3,14 +3,14 @@ // // Copmpiler messages // -// (C)2021-2025, by Aleksey Rakov +// (C)2021-2026, by Aleksey Rakov //--------------------------------------------------------------------------- #include "errors.h" namespace elena_lang { - constexpr auto MessageLength = 116; + constexpr auto MessageLength = 118; const Pair Messages[MessageLength] = { {errDuplicatedSymbol, errMsgDuplicatedSymbol}, @@ -129,6 +129,8 @@ namespace elena_lang {wrnUnknownRedirectMethod, wrnMsgUnknownRedirectMethod}, {errUnknownRedirectMethod, errMsgUnknownRedirectMethod}, {errIncompatibleClosure, errMsgIncompatibleClosure }, + {infoMissingTemplate, infoMsgMissingTemplate}, + {wrnNonNillableArgument, wrnMsgNonNillableArgument }, }; } diff --git a/elenasrc3/elc/modulescope.cpp b/elenasrc3/elc/modulescope.cpp index 439565a09..34a579507 100644 --- a/elenasrc3/elc/modulescope.cpp +++ b/elenasrc3/elc/modulescope.cpp @@ -3,7 +3,7 @@ // // This file contains Module scope class implementation. // -// (C)2021-2025, by Aleksey Rakov +// (C)2021-2026, by Aleksey Rakov //--------------------------------------------------------------------------- #include "modulescope.h" @@ -47,6 +47,11 @@ bool ModuleScope :: withPrologEpilog() return !test(hints, mhNoPrologEpilog); } +bool ModuleScope :: isNoTemplateReuse() +{ + return test(hints, mhNoTemplateCache); +} + static inline void findUninqueName(ModuleBase* module, IdentifierString& name) { size_t pos = name.length(); @@ -70,14 +75,21 @@ ref_t ModuleScope :: mapAnonymous(ustr_t prefix) return module->mapReference(*name); } +inline bool isNeedToBeGenerated(ustr_t resolved, ustr_t ns, bool noReuse) +{ + return resolved.empty() || (noReuse && !NamespaceString::compareNs(resolved, ns)); +} + ref_t ModuleScope :: mapTemplateIdentifier(ustr_t templateName, Visibility visibility, bool& alreadyDeclared, bool declarationMode) { IdentifierString forwardName(TEMPLATE_PREFIX_NS, templateName); if (!declarationMode) { + ustr_t ns = module->name(); ustr_t resolved = forwardResolver->resolveForward(templateName); - if (resolved.empty()) { - ReferenceName fullName(module->name()); + //if (resolved.empty()) { + if (isNeedToBeGenerated(resolved, ns, isNoTemplateReuse())) { + ReferenceName fullName(ns); fullName.combine(templateName); forwardResolver->addForward(templateName, *fullName); diff --git a/elenasrc3/elc/modulescope.h b/elenasrc3/elc/modulescope.h index bb5bf50ac..76b991a93 100644 --- a/elenasrc3/elc/modulescope.h +++ b/elenasrc3/elc/modulescope.h @@ -3,7 +3,7 @@ // // This file contains Module scope class declaration. // -// (C)2021-2025, by Aleksey Rakov +// (C)2021-2026, by Aleksey Rakov //--------------------------------------------------------------------------- #ifndef MODULESCOPE_H @@ -34,6 +34,7 @@ class ModuleScope : public ModuleScopeBase, public LibraryLoaderListenerBase bool isStandardOne() override; bool withValidation() override; bool withPrologEpilog() override; + bool isNoTemplateReuse() override; ref_t mapAnonymous(ustr_t prefix) override; diff --git a/elenasrc3/elc/project.cpp b/elenasrc3/elc/project.cpp index c5da81ca0..1857918fa 100644 --- a/elenasrc3/elc/project.cpp +++ b/elenasrc3/elc/project.cpp @@ -3,7 +3,7 @@ // // This file contains the project class body // -// (C)2021-2024, by Aleksey Rakov +// (C)2021-2026, by Aleksey Rakov //--------------------------------------------------------------------------- #include "elena.h" @@ -543,7 +543,7 @@ static inline void loadModuleCollection(PlatformType platform, path_t collection } } -bool ProjectCollection :: load(PlatformType platform, path_t path) +bool ProjectCollection :: load(PlatformType platform, path_t path, ustr_t nameAttr) { PathString collectionPath; collectionPath.copySubPath(path, false); @@ -558,6 +558,13 @@ bool ProjectCollection :: load(PlatformType platform, path_t path) ConfigFile::Collection collections; if (config.select(COLLECTIONS_CATEGORY, collections)) { for (auto it = collections.start(); !it.eof(); ++it) { + DynamicString nameStr; + if (!(*it).readAttribute(NAME_ATTR, nameStr)) + nameStr.clear(); + + if (!nameAttr.empty() && !nameAttr.compare(nameStr.str())) + continue; + ConfigFile::Collection subModules; if (config.select(*it, "*", subModules)) { loadModuleCollection(platform, *collectionPath, subModules, projectSpecs); diff --git a/elenasrc3/elc/project.h b/elenasrc3/elc/project.h index 37c8fb6f0..470b0413a 100644 --- a/elenasrc3/elc/project.h +++ b/elenasrc3/elc/project.h @@ -3,7 +3,7 @@ // // This file contains the project class declaration // -// (C)2021-2025, by Aleksey Rakov +// (C)2021-2026, by Aleksey Rakov //--------------------------------------------------------------------------- #ifndef PROJECT_H @@ -168,7 +168,7 @@ namespace elena_lang ProjectSpecs projectSpecs; - bool load(PlatformType platform, path_t path); + bool load(PlatformType platform, path_t path, ustr_t nameAttr); ProjectCollection() : projectSpecs(nullptr) diff --git a/elenasrc3/elena-tests/bt_optimization.h b/elenasrc3/elena-tests/bt_optimization.h index e4cc0a737..a7ba6b936 100644 --- a/elenasrc3/elena-tests/bt_optimization.h +++ b/elenasrc3/elena-tests/bt_optimization.h @@ -94,6 +94,13 @@ namespace elena_lang void SetUp() override; }; + // Optimization #7 : "native branching + class BTOptimization7 : public BTOptimization + { + protected: + void SetUp() override; + }; + // Optimization #12 (inplaceCallOp) : "struct X ( int x; ) .. X x := new X() => call in-place constructor class BTOptimization12 : public BTOptimization { @@ -268,6 +275,12 @@ namespace elena_lang protected: void SetUp() override; }; + + class StructFieldAssigning : public MethodScenarioTest + { + protected: + void SetUp() override; + }; } #endif diff --git a/elenasrc3/elena-tests/compile_tests.h b/elenasrc3/elena-tests/compile_tests.h index 18d54cd1e..579a5858f 100644 --- a/elenasrc3/elena-tests/compile_tests.h +++ b/elenasrc3/elena-tests/compile_tests.h @@ -38,6 +38,18 @@ namespace elena_lang void SetUp() override; }; + class CallingIndexedMethod : public ExprTest + { + protected: + void SetUp() override; + }; + + class CallingSealedByRefDeclaredInParent : public ExprTest + { + protected: + void SetUp() override; + }; + class DuplicateBoxingTest : public ExprTest { protected: @@ -52,6 +64,18 @@ namespace elena_lang void SetUp() override; }; + + class RetoverloadHandlerTest : public ExprTest + { + protected: + void SetUp() override; + }; + + class RetOverloadInRetExprTest : public MethodScenarioTest + { + protected: + void SetUp() override; + }; } #endif diff --git a/elenasrc3/elena-tests/scenario_consts.h b/elenasrc3/elena-tests/scenario_consts.h index 9b9ed1796..6f146b10e 100644 --- a/elenasrc3/elena-tests/scenario_consts.h +++ b/elenasrc3/elena-tests/scenario_consts.h @@ -3,11 +3,12 @@ constexpr auto S_DefaultNamespace_1 = "namespace (class (nameattr (identifier \" constexpr auto S_DefaultNamespace_2 = "namespace (class (nameattr (identifier \"Object\" ()) method (nameattr (identifier \"dispatch\" ())redirect (expression (object (identifier \"nil\" ()))))) $1)"; constexpr auto S_DefaultNamespace_4 = "namespace (class (nameattr (identifier \"Object\" ()) method (nameattr (identifier \"dispatch\" ())redirect (expression (object (identifier \"nil\" ()))))) $1)"; constexpr auto S_DefaultNamespace_3 = "namespace (class (nameattr (identifier \"Object\" ())) $1)"; +constexpr auto S_DefaultNamespace_5 = "namespace (class (nameattr (identifier \"Object\" ())) class (nameattr (identifier \"A\" ())) $1)"; // scenario basic types -constexpr auto S_IntNumber = "class (attribute -2147467263 () attribute -2147475455 () attribute -2147479550 () nameattr (identifier \"IntNumber\" ()) field (attribute -2147475454 () attribute -2147481597 () nameattr (identifier \"_value\" ())dimension (integer \"4\" ())))"; -constexpr auto S_ByteNumber = "class (attribute -2147467263 () attribute -2147475455 () attribute -2147479550 () nameattr (identifier \"ByteNumber\" ()) field (attribute -2147475454 () attribute -2147481596 () nameattr (identifier \"_value\" ())dimension (integer \"1\" ())))"; -constexpr auto S_IntRefeference = "class ( attribute -2147471359 () nameattr (identifier \"IntReference\" ()) field (attribute -2147475454 () type (identifier \"IntNumber\" ()) nameattr (identifier \"_value\" ())) )"; +constexpr auto S_IntNumber = "class (attribute -2147467263 () attribute -2147475455 () attribute -2147479550 () nameattr (identifier \"IntNumber\" ()) field (attribute -2147471356 () attribute -2147481597 () nameattr (identifier \"_value\" ())dimension (integer \"4\" ())))"; +constexpr auto S_ByteNumber = "class (attribute -2147467263 () attribute -2147475455 () attribute -2147479550 () nameattr (identifier \"ByteNumber\" ()) field (attribute -2147471356 () attribute -2147481596 () nameattr (identifier \"_value\" ())dimension (integer \"1\" ())))"; +constexpr auto S_IntRefeference = "class ( attribute -2147471359 () nameattr (identifier \"IntReference\" ()) field (attribute -2147471356 () type (identifier \"IntNumber\" ()) nameattr (identifier \"_value\" ())) )"; // scenario symbols constexpr auto S2_Scenario_Sync = "public_symbol (attribute -2147479537 () nameattr (identifier \"sync\" ())get_expression (expression (message_operation (object (attribute -2147479534 () identifier \"object\" ())))))"; @@ -16,13 +17,20 @@ constexpr auto S2_Scenario_Sync = "public_symbol (attribute -2147479537 () namea 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\" ())))"; -constexpr auto S_DummyByteArray = " class (attribute -2147467263 ()attribute -2147471359 ()nameattr (identifier \"ByteArray\" ())field (attribute -2147475454 ()attribute -2147481599 ()array_type (type (identifier \"ByteNumber\" ()))nameattr (identifier \"array\" ())))"; +constexpr auto S1_VariadicTemplates = " class (attribute -2147467263 ()attribute -2147471359 ()attribute -2147479542 ()nameattr (identifier \"VariadicArray\" ())field (attribute -2147471356 ()attribute -2147481599 ()array_type (type (identifier \"Object\" ()))nameattr (identifier \"array\" ()))) class (attribute -2147467263 ()attribute -2147471359 ()attribute -2147479542 ()nameattr (identifier \"VariadicBArray\" ())field (attribute -2147471356 ()attribute -2147481599 ()array_type (type (identifier \"B\" ()))nameattr (identifier \"array\" ())))"; +constexpr auto S_DummyByteArray = " class (attribute -2147467263 ()attribute -2147471359 ()nameattr (identifier \"ByteArray\" ())field (attribute -2147471356 ()attribute -2147481599 ()array_type (type (identifier \"ByteNumber\" ()))nameattr (identifier \"array\" ())))"; constexpr auto Tester_2Args = "class (attribute -2147467263 ()attribute -2147479546 () nameattr (identifier \"Tester\" ()) method (nameattr (identifier \"testArg2\" ()) parameter (nameattr (identifier \"arg1\" ())) parameter (nameattr (identifier \"arg2\" ())) code ()))"; constexpr auto IndexedClass_Scenario1 = "class (attribute -2147479545 ()nameattr 67 (identifier \"X\" ())method (type (identifier \"IntNumber\" ())nameattr (identifier \"calc\" ())parameter (type (identifier \"IntNumber\" ())nameattr (identifier \"arg\" ()))returning ())) class (attribute -2147479546 ()nameattr (identifier \"Y\" ())parent (type (identifier \"X\" ())))"; +constexpr auto IndexedClass_Scenario2 = "class (attribute -2147479545 ()nameattr 67 (identifier \"X\" ())method (attribute -2147459071() nameattr (identifier \"calc\" ())parameter (type (identifier \"IntNumber\" ())nameattr (identifier \"arg\" ()))returning ()))"; + +constexpr auto SealedByRefDeclaredInParent_Scenario1 = "class (attribute -2147479545 ()nameattr (identifier \"I\" ())method (type (identifier \"IntNumber\" ())nameattr (identifier \"foo\" ())parameter (type (identifier \"IntNumber\" ())nameattr (identifier \"n\" ())) code ())) class (attribute -2147467263 () attribute -2147479546 ()nameattr (identifier \"A\" ())parent (type (identifier \"I\" ())))"; constexpr auto S_ByRefHandlerTest_Class = "class (attribute -2147479551 (identifier \"class\" ())nameattr (identifier \"A\" ()) method (type (identifier \"IntNumber\" ()) nameattr (identifier \"incSum\" ()) parameter (type (identifier \"IntNumber\" ()) nameattr (identifier \"arg1\" ()))returning (expression (add_operation (object (identifier \"arg1\" ())expression (object (integer \"1\" ())))))))"; -constexpr auto S2_Scenario_IntermediateVar = "class (attribute -2147467263 ()nameattr (identifier \"program\" ())attribute -2147479546 ()method (attribute -2147479540 ()code (code (expression (assign_operation (object (attribute -2147479506 ()identifier \"v\" ())expression (expression (attribute -2147479505 () object (identifier \"sync\" ())))))expression (message_operation (object (identifier \"v\" ())message (identifier \"enterCriticalSection\" ()))) expression (final_operation (code () final_block (expression (message_operation (object (identifier \"v\" ()) message (identifier \"leaveCriticalSection\" ()))))))) EOP ()))))"; \ No newline at end of file +constexpr auto S2_Scenario_IntermediateVar = "class (attribute -2147467263 ()nameattr (identifier \"program\" ())attribute -2147479546 ()method (attribute -2147479540 ()code (code (expression (assign_operation (object (attribute -2147479506 ()identifier \"v\" ())expression (expression (attribute -2147479505 () object (identifier \"sync\" ())))))expression (message_operation (object (identifier \"v\" ())message (identifier \"enterCriticalSection\" ()))) expression (final_operation (code () final_block (expression (message_operation (object (identifier \"v\" ()) message (identifier \"leaveCriticalSection\" ()))))))) EOP ()))))"; + +constexpr auto S1_StructFieldAssigning = "class (attribute -2147479550 ()nameattr (identifier \"X\" ())field (type (identifier \"IntNumber\" ())nameattr (identifier \"dVal\" ()))field (type (identifier \"IntNumber\" ())nameattr (identifier \"dLen\" ()))method (nameattr (identifier \"test\" ())code (expression (assign_operation (object (type (identifier \"IntNumber\" ())identifier \"i\" ())expression (object (integer \"3\" ()))))code (expression (if_operation (expression (less_operation (object (identifier \"dLen\" ())expression (object (identifier \"i\" ()))))expression (closure (code (expression (code (expression (assign_operation (object (identifier \"dLen\" ())expression (object (identifier \"i\" ())))))))))))))))"; + +constexpr auto RetOverloadInRetExprTest_Scenario1 = "class (nameattr (identifier \"B\" ())method (attribute -2147475446 ()type (identifier \"A\" ())nameattr (identifier \"get\" ())returning (expression (object (identifier \"default\" ())))))class (attribute -2147479546 ()nameattr (identifier \"Tester\" ())method (type (identifier \"A\" ())nameattr (identifier \"test\" ())parameter (type (identifier \"B\" ())nameattr (identifier \"b\" ()))returning (expression (message_operation (object (identifier \"b\" ())message (identifier \"get\" ()))))))"; \ No newline at end of file diff --git a/elenasrc3/elena-tests/tape_consts.h b/elenasrc3/elena-tests/tape_consts.h index ab044dc00..2f00b0a23 100644 --- a/elenasrc3/elena-tests/tape_consts.h +++ b/elenasrc3/elena-tests/tape_consts.h @@ -3,9 +3,15 @@ constexpr auto B_NillableIntAssigning = "tape (open_frame ()assigning 1 ()nil ()assigning 2 ()int_literal 2 (value 2 ())assigning 3 ()local 1 ()close_frame ()exit ())reserved 4 ())"; constexpr auto B_IntermediateVar = "tape (open_frame ()assigning 1 ()symbol_call_op 2 ()assigning 2 ()local 2 ()saving_stack ()argument ()call_op 2049 ()final_op -4 (stack_index 3 ()tape ()tape (local 2 ()saving_stack ()argument ()call_op 2561 ()))local 1 ()close_frame ()exit ())reserved 4 ()reserved_n 16 ())"; +constexpr auto BuildTree_StructFieldAssigning_1 = "tape (open_frame ()assigning 1 () int_literal 2 (value 3 ()) copying -4 (size 4 ()) local_address -8 ()saving_stack ()local 1 ()copying_acc_field 4 (size 4 ())local_address -8 ()saving_stack ()local_address -4 ()saving_stack 1 ()intcondop 8 (operator_id 8() true_const 10() false_const 11 ()) assigning 2() local 2 () branchop 7 ( const_param 10 () tape (local_address -4 ()saving_stack ()local 1 ()copying_to_acc_field 4 (size 4 ())) ) local 1() close_frame () exit ()) reserved 4 () reserved_n 8 ()"; +constexpr auto OptimizedTree_StructFieldAssigning_1 = "tape (open_frame ()assigning 1 ()saving_int -4 (size 4 ()value 3 ())local_address -8 ()saving_stack ()local 1 ()copying_acc_field 4 (size 4 ())local_address -8 ()saving_stack ()local_address -4 ()saving_stack 1 ()intbranchop 8 (const_param 10 ()tape (local_address -4 ()saving_stack ()local 1 ()copying_to_acc_field 4 (size 4 ())))local 1 ()close_frame () exit ()) reserved 4 () reserved_n 8 ()"; + #elif _M_X64 constexpr auto B_NillableIntAssigning = "tape (open_frame ()assigning 1 ()nil ()assigning 2 ()int_literal 2 (value 2 ())assigning 3 ()local 1 ()close_frame ()exit ())reserved 6 ())"; constexpr auto B_IntermediateVar = "tape (open_frame ()assigning 1 ()symbol_call_op 2 ()assigning 2 ()local 2 ()saving_stack ()argument ()call_op 2049 ()final_op -8 (stack_index 3 ()tape ()tape (local 2 ()saving_stack ()argument ()call_op 2561 ()))local 1 ()close_frame ()exit ())reserved 6 ()reserved_n 32 ())"; +constexpr auto BuildTree_StructFieldAssigning_1 = "tape (open_frame ()assigning 1 () int_literal 2 (value 3 ()) copying -8 (size 4 ()) local_address -24 ()saving_stack ()local 1 ()copying_acc_field 4 (size 4 ())local_address -24 ()saving_stack ()local_address -8 ()saving_stack 1 ()intcondop 8 (operator_id 8() true_const 10() false_const 11 ()) assigning 2() local 2 () branchop 7 ( const_param 10 () tape (local_address -8 ()saving_stack ()local 1 ()copying_to_acc_field 4 (size 4 ())) ) local 1() close_frame () exit ()) reserved 4 () reserved_n 32 ()"; +constexpr auto OptimizedTree_StructFieldAssigning_1 = "tape (open_frame ()assigning 1 ()saving_int -8 (size 4 ()value 3 ())local_address -24 ()saving_stack ()local 1 ()copying_acc_field 4 (size 4 ())local_address -24 ()saving_stack ()local_address -8 ()saving_stack 1 ()intbranchop 8 (const_param 10 ()tape (local_address -8 ()saving_stack ()local 1 ()copying_to_acc_field 4 (size 4 ())))local 1 ()close_frame () exit ()) reserved 4 () reserved_n 32 ()"; + #endif diff --git a/elenasrc3/elena-tests/tests_bt.cpp b/elenasrc3/elena-tests/tests_bt.cpp index 6a0f130f4..64dabb68b 100644 --- a/elenasrc3/elena-tests/tests_bt.cpp +++ b/elenasrc3/elena-tests/tests_bt.cpp @@ -25,6 +25,9 @@ using namespace elena_lang; * BTOptimization12 * --------------- * +* BTOptimization7 +* --------------- +* */ TEST_F(BTOptimization1_1, BuildTapeTest) @@ -66,3 +69,8 @@ TEST_F(BTOptimization12_2, BuildTapeTest) { runBTTest(); } + +TEST_F(BTOptimization7, BuildTapeTest) +{ + runBTTest(); +} diff --git a/elenasrc3/elena-tests/tests_bt_optimization.cpp b/elenasrc3/elena-tests/tests_bt_optimization.cpp index 8c2d1e3e0..76eee38db 100644 --- a/elenasrc3/elena-tests/tests_bt_optimization.cpp +++ b/elenasrc3/elena-tests/tests_bt_optimization.cpp @@ -2,7 +2,7 @@ // E L E N A P r o j e c t: ELENA Compiler // // This header contains ELENA Test Optimization Fixture implementation -// (C)2024, by Aleksey Rakov +// (C)2024-2025, by Aleksey Rakov //--------------------------------------------------------------------------- #include "bt_optimization.h" @@ -18,10 +18,10 @@ constexpr auto BT_RULES_FILE = "bt_rules60.dat"; // --- BTOptimization1 --- -constexpr auto Declaration1_1 = "namespace (class ( nameattr (identifier \"Object\" ())) class (attribute -2147467263 () attribute -2147475455 () attribute -2147479550 () nameattr (identifier \"Struct\" ()) field (attribute -2147475454 () attribute -2147481597 () nameattr (identifier \"_value\" ())dimension (integer \"4\" ()))) class ( attribute -2147471359 () nameattr (identifier \"TestReference\" ()) field (attribute -2147475454 () type (identifier \"Struct\" ()) nameattr (identifier \"_value\" ())) ) class (attribute -2147467263 ()attribute -2147479546 () nameattr (identifier \"Tester\" ()) method (type (identifier \"Struct\" ()) nameattr (identifier \"getValue\" ())code ())))"; +constexpr auto Declaration1_1 = "namespace (class ( nameattr (identifier \"Object\" ())) class (attribute -2147467263 () attribute -2147475455 () attribute -2147479550 () nameattr (identifier \"Struct\" ()) field (attribute -2147471356 () attribute -2147481597 () nameattr (identifier \"_value\" ())dimension (integer \"4\" ()))) class ( attribute -2147471359 () nameattr (identifier \"TestReference\" ()) field (attribute -2147471356 () type (identifier \"Struct\" ()) nameattr (identifier \"_value\" ())) ) class (attribute -2147467263 ()attribute -2147479546 () nameattr (identifier \"Tester\" ()) method (type (identifier \"Struct\" ()) nameattr (identifier \"getValue\" ())code ())))"; constexpr auto SyntaxTree1_1 = "expression(assign_operation(object(type(identifier \"Struct\"())identifier \"r\"())expression(message_operation(object(identifier \"Tester\"())message(identifier \"getValue\" ())))))"; -constexpr auto Declaration1_2 = "namespace (class ( nameattr (identifier \"Object\" ())) class (attribute -2147467263 () attribute -2147475455 () attribute -2147479550 () nameattr (identifier \"Struct\" ()) field (attribute -2147475454 () attribute -2147481597 () nameattr (identifier \"_value\" ())dimension (integer \"4\" ()))) class ( attribute -2147471359 () nameattr (identifier \"TestReference\" ()) field (attribute -2147475454 () type (identifier \"Struct\" ()) nameattr (identifier \"_value\" ())) ) class (attribute -2147467263 ()attribute -2147479546 () nameattr (identifier \"Tester\" ()) method (attribute -2147463167 () type (identifier \"Struct\" ()) nameattr (identifier \"Value\" ())code ())))"; +constexpr auto Declaration1_2 = "namespace (class ( nameattr (identifier \"Object\" ())) class (attribute -2147467263 () attribute -2147475455 () attribute -2147479550 () nameattr (identifier \"Struct\" ()) field (attribute -2147471356 () attribute -2147481597 () nameattr (identifier \"_value\" ())dimension (integer \"4\" ()))) class ( attribute -2147471359 () nameattr (identifier \"TestReference\" ()) field (attribute -2147471356 () type (identifier \"Struct\" ()) nameattr (identifier \"_value\" ())) ) class (attribute -2147467263 ()attribute -2147479546 () nameattr (identifier \"Tester\" ()) method (attribute -2147463167 () type (identifier \"Struct\" ()) nameattr (identifier \"Value\" ())code ())))"; constexpr auto SyntaxTree1_2 = "expression(assign_operation(object(type(identifier \"Struct\"())identifier \"r\"())expression(property_operation(object(identifier \"Tester\"())message(identifier \"Value\" ())))))"; constexpr auto S_Declaration1_4 = "class (attribute -2147467263 ()attribute -2147479546 () nameattr (identifier \"Tester\" ()) method (type (identifier \"IntNumber\" ()) nameattr (identifier \"at\" ()) parameter (type (identifier \"IntNumber\" ()) nameattr (identifier \"o\" ())) code ())"; @@ -29,34 +29,34 @@ constexpr auto S_Declaration1_4 = "class (attribute -2147467263 ()attribute -214 constexpr auto SyntaxTree1_3 = "expression(assign_operation(object(type(identifier \"Struct\" ())identifier \"r\"())expression(value_operation(expression(object(identifier \"Tester\"()))))))"; constexpr auto SyntaxTree1_4 = "expression(assign_operation(object(type(identifier \"IntNumber\" ())identifier \"r\"())expression(index_operation(expression(object(identifier \"Tester\"())) expression(object(integer \"0\")))))))"; -constexpr auto Declaration2 = "namespace (class ( nameattr (identifier \"Object\" ())) class (attribute -2147467263 () attribute -2147475455 () attribute -2147479550 () nameattr (identifier \"IntNumber\" ()) field (attribute -2147475454 () attribute -2147481597 () nameattr (identifier \"_value\" ())dimension (integer \"4\" ()))) class ( attribute -2147471359 () nameattr (identifier \"IntNumberReference\" ()) field (attribute -2147475454 () type (identifier \"IntNumber\" ()) nameattr (identifier \"_value\" ())) ))"; +constexpr auto Declaration2 = "namespace (class ( nameattr (identifier \"Object\" ())) class (attribute -2147467263 () attribute -2147475455 () attribute -2147479550 () nameattr (identifier \"IntNumber\" ()) field (attribute -2147471356 () attribute -2147481597 () nameattr (identifier \"_value\" ())dimension (integer \"4\" ()))) class ( attribute -2147471359 () nameattr (identifier \"IntNumberReference\" ()) field (attribute -2147471356 () type (identifier \"IntNumber\" ()) nameattr (identifier \"_value\" ())) ))"; constexpr auto SyntaxTree2 = "expression (assign_operation (object (type (identifier \"IntNumber\" ()) identifier \"n\" ()) expression (object (integer \"2\"))))"; constexpr auto SyntaxTree4 = "expression ( code( expression (assign_operation (object (type (identifier \"IntNumber\" ())identifier \"n\" ())expression (object (integer \"3\" ()))))expression (assign_operation (object (type (identifier \"IntNumber\" ())identifier \"r\" ())expression (add_operation (object (identifier \"n\" ())expression (object (integer \"2\" ()))))))))"; -constexpr auto Declaration12 = "namespace (class ( nameattr (identifier \"Object\" ())) class (attribute -2147467263 () attribute -2147475455 () attribute -2147479550 () nameattr (identifier \"IntNumber\" ()) field (attribute -2147475454 () attribute -2147481597 () nameattr (identifier \"_value\" ())dimension (integer \"4\" ()))) class (attribute -2147479550 () nameattr (identifier \"X\" ())field (type (identifier \"IntNumber\" ())nameattr (identifier \"x\" ()))))"; -constexpr auto SyntaxTree12 = "expression (assign_operation (object (type (identifier \"X\" ())identifier \"x\" ())expression (message_operation (object (attribute -2147479534 ()identifier \"X\" ())))))"; -//constexpr auto Declaration12_2 = "namespace (class ( nameattr (identifier \"Object\" ())) class (attribute -2147467263 () attribute -2147475455 () attribute -2147479550 () nameattr (identifier \"IntNumber\" ()) field (attribute -2147475454 () attribute -2147481597 () nameattr (identifier \"_value\" ())dimension (integer \"4\" ()))) class (attribute -2147479550 ()nameattr (identifier \"X\" ()) field (type (identifier \"IntNumber\" ()) nameattr (identifier \"x\" ())) method ( nameattr (identifier \"constructor\" ()) parameter(type(identifier \"IntNumber\" ()) nameattr (identifier \"x\" ())) code ()) ))"; -constexpr auto Declaration12_2 = "namespace (class ( nameattr (identifier \"Object\" ())) class (attribute -2147467263 () attribute -2147475455 () attribute -2147479550 () nameattr (identifier \"IntNumber\" ()) field (attribute -2147475454 () attribute -2147481597 () nameattr (identifier \"_value\" ())dimension (integer \"4\" ()))) class (attribute -2147479550 ()nameattr (identifier \"X\" ()) field (type (identifier \"IntNumber\" ()) nameattr (identifier \"x\" ())) method (nameattr (identifier \"constructor\" ()) parameter (type (identifier \"IntNumber\" ()) nameattr (identifier \"x\" ())) code ())))"; +constexpr auto Declaration12 = "namespace (class ( nameattr (identifier \"Object\" ())) class (attribute -2147467263 () attribute -2147475455 () attribute -2147479550 () nameattr (identifier \"IntNumber\" ()) field (attribute -2147471356 () attribute -2147481597 () nameattr (identifier \"_value\" ())dimension (integer \"4\" ()))) class (attribute -2147479550 () nameattr (identifier \"X\" ())field (type (identifier \"IntNumber\" ())nameattr (identifier \"x\" ()))))"; +constexpr auto SyntaxTree12 = "expression (assign_operation (object (type (identifier \"X\" ())identifier \"x\" ())expression (message_operation (object (attribute -2147471342 ()identifier \"X\" ())))))"; +//constexpr auto Declaration12_2 = "namespace (class ( nameattr (identifier \"Object\" ())) class (attribute -2147467263 () attribute -2147475455 () attribute -2147479550 () nameattr (identifier \"IntNumber\" ()) field (attribute -2147471356 () attribute -2147481597 () nameattr (identifier \"_value\" ())dimension (integer \"4\" ()))) class (attribute -2147479550 ()nameattr (identifier \"X\" ()) field (type (identifier \"IntNumber\" ()) nameattr (identifier \"x\" ())) method ( nameattr (identifier \"constructor\" ()) parameter(type(identifier \"IntNumber\" ()) nameattr (identifier \"x\" ())) code ()) ))"; +constexpr auto Declaration12_2 = "namespace (class ( nameattr (identifier \"Object\" ())) class (attribute -2147467263 () attribute -2147475455 () attribute -2147479550 () nameattr (identifier \"IntNumber\" ()) field (attribute -2147471356 () attribute -2147481597 () nameattr (identifier \"_value\" ())dimension (integer \"4\" ()))) class (attribute -2147479550 ()nameattr (identifier \"X\" ()) field (type (identifier \"IntNumber\" ()) nameattr (identifier \"x\" ())) method (nameattr (identifier \"constructor\" ()) parameter (type (identifier \"IntNumber\" ()) nameattr (identifier \"x\" ())) code ())))"; constexpr auto SyntaxTree12_2 = "expression (assign_operation (object (type (identifier \"X\" ())identifier \"x\" ())expression (object (integer \"2\" ()))))"; -constexpr auto Struct_Declaration1 = "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\" ())) field (type (identifier \"byte\" ())nameattr (identifier \"b3\" ()))field (type (identifier \"long\" ()) nameattr (identifier \"l\" ()))))"; -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 Struct_Declaration1 = "namespace (class ( nameattr (identifier \"Object\" ())) class (attribute -2147479550 () nameattr (identifier \"IntNumber\" ()) field (attribute -2147471356 () attribute -2147481597 () nameattr ( identifier \"_value\" ()) dimension ( integer \"4\" ()))) class (attribute -2147479550 () nameattr (identifier \"ByteNumber\" ()) field (attribute -2147471356 () attribute -2147481596 () nameattr (identifier \"_value\" ()) dimension (integer \"1\" ())))class (attribute -2147479550 () nameattr 60 (identifier \"ShortNumber\" ()) field (attribute -2147471356 () attribute -2147481597 ()nameattr ( identifier \"_value\" ()) dimension ( integer \"2\" ()))) class (attribute -2147479550 ()nameattr (identifier \"LongNumber\" ())field (attribute -2147471356 () 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\" ())) field (type (identifier \"byte\" ())nameattr (identifier \"b3\" ()))field (type (identifier \"long\" ()) nameattr (identifier \"l\" ()))))"; +constexpr auto Struct_Declaration2 = "namespace (class ( nameattr (identifier \"Object\" ())) class (attribute -2147479550 () nameattr (identifier \"IntNumber\" ()) field (attribute -2147471356 () attribute -2147481597 () nameattr ( identifier \"_value\" ()) dimension ( integer \"4\" ()))) class (attribute -2147479550 () nameattr (identifier \"ByteNumber\" ()) field (attribute -2147471356 () attribute -2147481596 () nameattr (identifier \"_value\" ()) dimension (integer \"1\" ())))class (attribute -2147479550 () nameattr 60 (identifier \"ShortNumber\" ()) field (attribute -2147471356 () attribute -2147481597 ()nameattr ( identifier \"_value\" ()) dimension ( integer \"2\" ()))) class (attribute -2147479550 ()nameattr (identifier \"LongNumber\" ())field (attribute -2147471356 () 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 -2147471356 () attribute -2147481597 () nameattr ( identifier \"_value\" ()) dimension ( integer \"4\" ()))) class (attribute -2147479550 () nameattr (identifier \"ByteNumber\" ()) field (attribute -2147471356 () attribute -2147481596 () nameattr (identifier \"_value\" ()) dimension (integer \"1\" ())))class (attribute -2147479550 () nameattr 60 (identifier \"ShortNumber\" ()) field (attribute -2147471356 () attribute -2147481597 ()nameattr ( identifier \"_value\" ()) dimension ( integer \"2\" ()))) class (attribute -2147479550 ()nameattr (identifier \"LongNumber\" ())field (attribute -2147471356 () 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_VariadicSingleDispatch_1 = "class (attribute -2147479546 () nameattr (identifier \"E\" ()) method (nameattr (identifier \"load\" ()) parameter (attribute -2147475445 () array_type (type (identifier \"B\" ())) nameattr (identifier \"o\" ())) code ()))"; -constexpr auto S1_VariadicSingleDispatch_2 = "class (attribute -2147467263 () nameattr (identifier \"program\" ()) attribute -2147479546 () method 2592 (attribute -2147479540 ()code ( expression (assign_operation (object (attribute -2147479539 () identifier \"b\" ())expression (message_operation (object (attribute -2147479534 () identifier \"B\" ()))))) expression (assign_operation (object (attribute -2147479539 () identifier \"c\" ()) expression (message_operation (object (attribute -2147479534 ()identifier \"C\" ()))))) expression (message_operation (object (identifier \"E\" ())message (identifier \"load\" ())expression (object (identifier \"b\" ()))expression (object (identifier \"c\" ()))))))) class (nameattr (identifier \"C\" ()) method (type (identifier \"B\" ())attribute -2147479535 () returning (expression (message_operation (object (attribute -2147479534 () identifier \"B\" ())))))"; +constexpr auto S1_VariadicSingleDispatch_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 -2147471342 () identifier \"B\" ()))))) expression (assign_operation (object (attribute -2147479539 () identifier \"c\" ()) expression (message_operation (object (attribute -2147471342 ()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 -2147471343 () returning (expression (message_operation (object (attribute -2147471343 () identifier \"B\" ())))))"; constexpr auto S1_VariadicSingleDispatch_3a = "class (nameattr(identifier \"C\" ())parent (type (identifier \"B\" ())))class (nameattr (identifier \"D\" ())parent (type (identifier \"B\" ())))"; -constexpr auto S1_VariadicSingleDispatch_3b = "class (attribute -2147467263 ()nameattr (identifier \"program\" ())attribute -2147479546 ()method (attribute -2147479540 ()code (expression (message_operation (object (identifier \"E\" ())message (identifier \"load\" ())expression (message_operation (object (attribute -2147479534 ()identifier \"C\" ())))expression (message_operation (object (attribute -2147479534 ()identifier \"D\" ()))))))))"; +constexpr auto S1_VariadicSingleDispatch_3b = "class (attribute -2147467263 ()nameattr (identifier \"program\" ())attribute -2147479546 ()method (attribute -2147479540 ()code (expression (message_operation (object (identifier \"E\" ())message (identifier \"load\" ())expression (message_operation (object (attribute -2147471342 ()identifier \"C\" ())))expression (message_operation (object (attribute -2147471342 ()identifier \"D\" ()))))))))"; constexpr auto S1_DirectCall_1 = "class (nameattr (identifier \"myMethod\" ())attribute -2147479546 ()method (attribute -2147479540 ()parameter (type (identifier \"B\" ())nameattr (identifier \"arg\" ()))code ()))"; -constexpr auto S1_DirectCall_2 = "class (attribute -2147479546 ()nameattr (identifier \"TestHelper\" ())method (nameattr (identifier \"myMethodInvoker\" ())code (expression (message_operation (object (identifier \"myMethod\" ())expression (message_operation (object (attribute -2147479534 ()identifier \"B\" ())))))))method (nameattr (identifier \"myMethod\" ())parameter (type (identifier \"B\" ())nameattr (identifier \"arg\" ()))code ()))"; +constexpr auto S1_DirectCall_2 = "class (attribute -2147479546 ()nameattr (identifier \"TestHelper\" ())method (nameattr (identifier \"myMethodInvoker\" ())code (expression (message_operation (object (identifier \"myMethod\" ())expression (message_operation (object (attribute -2147471342 ()identifier \"B\" ())))))))method (nameattr (identifier \"myMethod\" ())parameter (type (identifier \"B\" ())nameattr (identifier \"arg\" ()))code ()))"; constexpr auto S1_DirectCallWithNil_1 = "class (attribute -2147479546 ()nameattr (identifier \"X\" ())method (nameattr (identifier \"printMe\" ())parameter (type (nullable (identifier \"B\" ()))nameattr (identifier \"arg\" ()))code ()))"; constexpr auto S1_DirectCallWithNil_2 = "class (attribute -2147467263 ()nameattr (identifier \"program\" ())attribute -2147479546 ()method (attribute -2147479540 ()code (expression (message_operation (object (identifier \"X\" ())message (identifier \"printMe\" ())expression (object (identifier \"nil\" ())))))))"; -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_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 -2147471342 ()identifier \"B\" ())))))expression (assign_operation (object (attribute -2147479539 ()identifier \"b2\" ())expression (message_operation (object (attribute -2147471342 ()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_MethodWithSignatureOfObject = "class (attribute -2147479546 ()nameattr (identifier \"Helper\" ())method (nameattr (identifier \"test\" ())parameter (type (identifier \"Object\" ())nameattr (identifier \"arg\" ()))code ())) class (attribute -2147467263 ()nameattr (identifier \"program\" ())attribute -2147479546 ()method (attribute -2147479540 ()code (expression (assign_operation (object (type (identifier \"Object\" ())identifier \"arg\" ())expression (object (integer \"2\" ()))))expression (message_operation (object (identifier \"Helper\" ()) message(identifier \"test\" ())expression (object (identifier \"arg\" ())))))))"; @@ -322,6 +322,16 @@ void BTOptimization4 :: SetUp() BuildTreeSerializer::load(OptimizedBuildTree4, afterOptimization); } +// --- BTOptimization7 --- + +void BTOptimization7::SetUp() +{ + BTOptimization::SetUp(); + + BuildTreeSerializer::load(BuildTree_StructFieldAssigning_1, buildNode); + BuildTreeSerializer::load(OptimizedTree_StructFieldAssigning_1, afterOptimization); +} + // --- BTOptimization12 --- void BTOptimization12 :: SetUp() @@ -789,3 +799,20 @@ void IntermediateVar :: SetUp() targetRef = 3; } + +// --- VariadicRuntimeSingleDispatch --- + +void StructFieldAssigning :: SetUp() +{ + MethodScenarioTest::SetUp(); + + LoadDeclarationScenario(S_DefaultNamespace_3, S_IntNumber, S1_StructFieldAssigning); + + BuildTreeSerializer::load(BuildTree_StructFieldAssigning_1, controlOutputNode); + + targetRef = 3; + intNumberRef = 2; + + trueRef = 10; // !! virtual references + falseRef = 11; +} diff --git a/elenasrc3/elena-tests/tests_build.cpp b/elenasrc3/elena-tests/tests_build.cpp index a43bfe23e..e91724c52 100644 --- a/elenasrc3/elena-tests/tests_build.cpp +++ b/elenasrc3/elena-tests/tests_build.cpp @@ -58,6 +58,9 @@ * * IntermediateVar * --------------- +* +* StructFieldAssigning +* -------------------- */ @@ -181,6 +184,11 @@ TEST_F(ByteArrayOperation2, BuildTest) } TEST_F(IntermediateVar, BuildTest) +{ + runTest(); +} + +TEST_F(StructFieldAssigning, BuildTest) { runTest(); } \ No newline at end of file diff --git a/elenasrc3/elena-tests/tests_common.cpp b/elenasrc3/elena-tests/tests_common.cpp index ff2925ada..2a98139e2 100644 --- a/elenasrc3/elena-tests/tests_common.cpp +++ b/elenasrc3/elena-tests/tests_common.cpp @@ -2,7 +2,7 @@ // E L E N A P r o j e c t: ELENA Compiler // // This header contains ELENA Test Common implementation -// (C)2024-2025, by Aleksey Rakov +// (C)2024-2026, by Aleksey Rakov //--------------------------------------------------------------------------- #include "pch.h" @@ -58,6 +58,11 @@ bool TestModuleScope :: withPrologEpilog() return false; } +bool TestModuleScope :: isNoTemplateReuse() +{ + return false; +} + ref_t TestModuleScope :: mapAnonymous(ustr_t prefix) { IdentifierString name("'", prefix, INLINE_CLASSNAME); @@ -467,6 +472,8 @@ void MethodScenarioTest :: runTest(bool withProtectedConstructor, bool withAttri ModuleScopeBase* moduleScope = env.createModuleScope(true, withAttributes); moduleScope->buildins.superReference = 1; moduleScope->buildins.intReference = intNumberRef; + moduleScope->branchingInfo.trueRef = trueRef; + moduleScope->branchingInfo.falseRef = falseRef; if (argArrayTemplateRef != INVALID_REF) { moduleScope->buildins.argArrayTemplateReference = argArrayTemplateRef; diff --git a/elenasrc3/elena-tests/tests_common.h b/elenasrc3/elena-tests/tests_common.h index 0246f1ba6..a275463e6 100644 --- a/elenasrc3/elena-tests/tests_common.h +++ b/elenasrc3/elena-tests/tests_common.h @@ -2,7 +2,7 @@ // E L E N A P r o j e c t: ELENA Compiler // // This header contains ELENA Test Common declarations -// (C)2024, by Aleksey Rakov +// (C)2024-2026, by Aleksey Rakov //--------------------------------------------------------------------------- #ifndef TESTS_COMMON_H @@ -88,6 +88,7 @@ namespace elena_lang bool isStandardOne() override; bool withValidation() override; bool withPrologEpilog() override; + bool isNoTemplateReuse() override; ref_t mapAnonymous(ustr_t prefix) override; @@ -299,6 +300,8 @@ namespace elena_lang ref_t targetVargRef; ref_t intNumberRef; ref_t intByRefRef; + ref_t trueRef; + ref_t falseRef; SyntaxNode findAutoGenerated(SyntaxNode classNode); @@ -314,6 +317,7 @@ namespace elena_lang genericVargRef = targetVargRef = intNumberRef = 0; intByRefRef = 0; + trueRef = falseRef = 0; } }; diff --git a/elenasrc3/elena-tests/tests_compile.cpp b/elenasrc3/elena-tests/tests_compile.cpp index d4d69aaae..4a9f8a89b 100644 --- a/elenasrc3/elena-tests/tests_compile.cpp +++ b/elenasrc3/elena-tests/tests_compile.cpp @@ -45,8 +45,47 @@ * } * * +* RetoverloadHandlerInvoker +* ----------------------------- +* check if retoverload method was properly called +* +* A; +* +* public singleton Tester +* { +* getValue() +* = self; +* +* retoverload A getValue() +* = new A(); +* } +* +* public Program() +* { +* A a := Tester.getValue(); +* } +* +* Calling retoverload method in a returning expression +* ---------------------------------------------------- +* +* A; +* +* B +* { +* retoverload A get() = default; +* } +* +* singleton Tester +* { +* A test(B b) = b.get(); +* } +* */ + + + + #include "pch.h" // ------------------------------------------------ #include "serializer.h" @@ -63,22 +102,46 @@ constexpr auto PrivateField_Scenario1 = "class (nameattr (identifier \"A\" ())fi constexpr auto CallingIndexedethodFromSealed_Scenario1 = "expression (assign_operation (object (type (identifier \"IntNumber\" ())identifier \"ret\" ())expression (message_operation (object (identifier \"Y\" ())message (identifier \"calc\" ())expression (object (integer \"3\" ())))))"; +constexpr auto CallingIndexedethod_Scenario1 = "expression ( code ( expression ( object (type (identifier \"X\" ())identifier \"x\" ())) expression (message_operation (object (identifier \"x\" ())message (identifier \"calc\" ())expression (object (integer \"3\" ())))))"; + +constexpr auto CallingSealedByRefDeclaredInParent_Scenario1 = "expression (assign_operation (object (type (identifier \"IntNumber\" ())identifier \"n\" ())expression (message_operation (object (identifier \"A\" ())message (identifier \"foo\" ())expression (object (integer \"1\" ()))))))"; + constexpr auto DuplicateBoxing_Scenario1 = "expression (code (expression (assign_operation (object (type (identifier \"IntNumber\" ())identifier \"x\" ())expression (object (integer \"2\" ()))))expression (message_operation (object (identifier \"Tester\" ())message (identifier \"testArg2\" ())expression (closure (code (returning (expression (object (identifier \"x\" ()))))))expression (closure (code (returning (expression (object (identifier \"x\" ()))))))))))"; +constexpr auto RetoverloadHandler_Scenario1 = "class (nameattr (identifier \"A\" ())) class (attribute -2147467263 () attribute -2147479546 () nameattr (identifier \"Tester\" ())method (nameattr (identifier \"getValue\" ())returning (expression (object (identifier \"self\" ())))) method (attribute -2147475446 () type (identifier \"A\" ())nameattr (identifier \"getValue\" ())returning (expression (message_operation (object (attribute -2147471342 () identifier \"A\" ()))))))"; + +constexpr auto RetoverloadHandlerInvoker_Scenario1 = "expression (assign_operation (object (type (identifier \"A\" ())identifier \"a\" ()) expression (message_operation (object (identifier \"Tester\" ()) message (identifier \"getValue\" ()))))))"; + #ifdef _M_IX86 -constexpr auto Build_CallingIndexedethodFromSealed_Scenario1 = "byrefmark -8 () local_address -8 () saving_stack 2() int_literal 2 (value 3 ())saving_stack 1 ()class_reference 5 ()saving_stack ()argument ()semi_direct_call_op 6403 (type 5 ()index_table_mode ())local_address -8 ()copying -4 (size 4 ())"; +constexpr auto Build_CallingIndexedethod_Scenario1 = "int_literal 2 (value 3 ())saving_stack 1 ()local 1 ()saving_stack ()argument ()semi_direct_call_op 4610 (type 4 ()index_table_mode ())"; + +constexpr auto Build_CallingSealedByRefDeclaredInParent_Scenario1 = "byrefmark -8 () local_address -8 () saving_stack 2 () int_literal 2 (value 1 ()) saving_stack 1 () class_reference 5 () saving_stack () argument () direct_call_op 6403 (type 4 () index_table_mode ()) local_address -8 () copying -4 (size 4 ())"; + +constexpr auto Build_CallingIndexedethodFromSealed_Scenario1 = "byrefmark -8 () local_address -8 () saving_stack 2() int_literal 2 (value 3 ())saving_stack 1 ()class_reference 5 ()saving_stack ()argument ()direct_call_op 6403 (type 4 ()index_table_mode ())local_address -8 ()copying -4 (size 4 ())"; constexpr auto Build_DuplicateBoxing_Scenario1 = "int_literal 2 (value 2 ()) copying -4 (size 4 ())local_address -4 ()saving_stack ()create_struct 4 (type 2 ())copying_to_acc 1 (size 4 ())assigning 1 ()create_class 1 (type 6 ())assign_local_to_stack 1 ()set_imm_field ()assigning 2 ()create_class 1 (type 7 ())assign_local_to_stack 1 ()set_imm_field ()assigning 3 ()local 3 ()saving_stack 2 ()local 2 ()saving_stack 1 ()class_reference 3 ()saving_stack ()argument ()direct_call_op 3587 (type 3 ())"; constexpr auto Build_S_ByRefHandlerTest_Class = "class 4 (method 5891 (tape ( open_frame () assigning 1 () local -2 () saving_stack () int_literal 2 (value 1 ())saving_stack 1 ()intop -4 (operator_id 4 ())local_address -4 ()saving_stack ()local -3 ()copying_to_acc -3 (size 4 ()) going_to_eop ()close_frame ()exit ())reserved 3 ()reserved_n 4 ())method 4098 (tape (open_frame ()assigning 1 ()local_address -4 ()saving_stack 2 ()local -2 ()saving_stack 1 ()local 1 ()saving_stack ()argument ()semi_direct_call_op 5891 (type 4 ()index_table_mode ())local_address -4 ()saving_stack ()create_struct 4 (type 2 ())copying_to_acc 2 (size 4 ())assigning 2 ()local 2 ()close_frame ()exit ())reserved 5 ()reserved_n 4 ()))"; +constexpr auto Build_RetoverloadHandlerInvoker_Scenario1 = "local 2 () assigning 3 () local_reference 3 () saving_stack 1 () class_reference 3 () saving_stack () argument () direct_call_op 3586 (type 3 ()) local 3 () assigning 2 () local 2 () assigning 1 ()"; + +constexpr auto Build_RetOverloadInRetExprTest_Scenario1 = "tape(open_frame ()assigning 1 ()local 2 ()assigning 3 ()local_reference 3 ()saving_stack 1 ()local -2 ()saving_stack ()argument ()call_op 1538 (type 3 ())local 3 ()assigning 2 ()local 2 () going_to_eop() close_frame ()exit ())reserved 5 ())"; + #elif _M_X64 -constexpr auto Build_CallingIndexedethodFromSealed_Scenario1 = "byrefmark -24 () local_address -24 () saving_stack 2() int_literal 2 (value 3 ())saving_stack 1 ()class_reference 5 ()saving_stack ()argument ()semi_direct_call_op 6403 (type 5 ()index_table_mode ())local_address -24 ()copying -8 (size 4 ())"; +constexpr auto Build_CallingIndexedethod_Scenario1 = "int_literal 2 (value 3 ())saving_stack 1 ()local 1 ()saving_stack ()argument ()semi_direct_call_op 4610 (type 4 ()index_table_mode ())"; + +constexpr auto Build_CallingSealedByRefDeclaredInParent_Scenario1 = "byrefmark -24 () local_address -24 () saving_stack 2 () int_literal 2 (value 1 ()) saving_stack 1 () class_reference 5 () saving_stack () argument () direct_call_op 6403 (type 4 () index_table_mode ()) local_address -24 () copying -8 (size 4 ())"; + +constexpr auto Build_CallingIndexedethodFromSealed_Scenario1 = "byrefmark -24 () local_address -24 () saving_stack 2() int_literal 2 (value 3 ())saving_stack 1 ()class_reference 5 ()saving_stack ()argument ()direct_call_op 6403 (type 4 ()index_table_mode ())local_address -24 ()copying -8 (size 4 ())"; constexpr auto Build_DuplicateBoxing_Scenario1 = "int_literal 2 (value 2 ()) copying -8 (size 4 ())local_address -8 ()saving_stack ()create_struct 4 (type 2 ())copying_to_acc 1 (size 4 ())assigning 1 ()create_class 1 (type 6 ())assign_local_to_stack 1 ()set_imm_field ()assigning 2 ()create_class 1 (type 7 ())assign_local_to_stack 1 ()set_imm_field ()assigning 3 ()local 3 ()saving_stack 2 ()local 2 ()saving_stack 1 ()class_reference 3 ()saving_stack ()argument ()direct_call_op 3587 (type 3 ())"; constexpr auto Build_S_ByRefHandlerTest_Class = "class 4 (method 5891 (tape ( open_frame () assigning 1 () local -2 () saving_stack () int_literal 2 (value 1 ())saving_stack 1 ()intop -8 (operator_id 4 ())local_address -8 ()saving_stack ()local -3 ()copying_to_acc -3 (size 4 ()) going_to_eop ()close_frame ()exit ())reserved 4 ()reserved_n 16 ())method 4098 (tape (open_frame ()assigning 1 ()local_address -8 ()saving_stack 2 ()local -2 ()saving_stack 1 ()local 1 ()saving_stack ()argument ()semi_direct_call_op 5891 (type 4 ()index_table_mode ())local_address -8 ()saving_stack ()create_struct 4 (type 2 ())copying_to_acc 2 (size 4 ())assigning 2 ()local 2 ()close_frame ()exit ())reserved 6 ()reserved_n 16 ()))"; +constexpr auto Build_RetoverloadHandlerInvoker_Scenario1 = "local 2 () assigning 3 () local_reference 3 () saving_stack 1 () class_reference 3 () saving_stack () argument () direct_call_op 3586 (type 3 ()) local 3 () assigning 2 () local 2 () assigning 1 ()"; + +constexpr auto Build_RetOverloadInRetExprTest_Scenario1 = "tape(open_frame ()assigning 1 ()local 2 ()assigning 3 ()local_reference 3 ()saving_stack 1 ()local -2 ()saving_stack ()argument ()call_op 1538 (type 3 ())local 3 ()assigning 2 ()local 2 () going_to_eop() close_frame ()exit ())reserved 6 ())"; + #endif // --- CompileScenarioTest --- @@ -156,7 +219,6 @@ TEST_F(AccessPrivateField, AccessParentPrivateFieldTest) runTest(4, 106); } - // --- CallingIndexedethodFromSealed --- void CallingIndexedMethodFromSealed::SetUp() @@ -174,6 +236,40 @@ TEST_F(CallingIndexedMethodFromSealed, CallingIndexedMethodTest) runBuildTest(true, false); } +// --- CallingIndexedethod --- + +void CallingIndexedMethod::SetUp() +{ + ExprTest::SetUp(); + + LoadDeclarationScenario(S_DefaultNamespace_2, S_IntNumber, S_IntRefeference, IndexedClass_Scenario2); + SyntaxTreeSerializer::load(CallingIndexedethod_Scenario1, exprNode); + + BuildTreeSerializer::load(Build_CallingIndexedethod_Scenario1, buildNode); +} + +TEST_F(CallingIndexedMethod, CallingIndexedMethodTest) +{ + runBuildTest(true, false); +} + +// --- CallingSealedByRefDeclaredInParent --- + +void CallingSealedByRefDeclaredInParent::SetUp() +{ + ExprTest::SetUp(); + + LoadDeclarationScenario(S_DefaultNamespace_2, S_IntNumber, S_IntRefeference, SealedByRefDeclaredInParent_Scenario1); + SyntaxTreeSerializer::load(CallingSealedByRefDeclaredInParent_Scenario1, exprNode); + + BuildTreeSerializer::load(Build_CallingSealedByRefDeclaredInParent_Scenario1, buildNode); +} + +TEST_F(CallingSealedByRefDeclaredInParent, CallingSealedByRefDeclaredInParentTest) +{ + runBuildTest(true, false); +} + // --- DuplicateBoxingTest --- void DuplicateBoxingTest :: SetUp() @@ -257,3 +353,38 @@ TEST_F(ByRefHandlerTest, GeneratingByRefHandlerInvoker) { runTest(true, false, 1, 2); } + +// --- RetoverloadHandlerInvoker --- + +void RetoverloadHandlerTest :: SetUp() +{ + ExprTest::SetUp(); + + LoadDeclarationScenario(S_DefaultNamespace_2, RetoverloadHandler_Scenario1); + SyntaxTreeSerializer::load(RetoverloadHandlerInvoker_Scenario1, exprNode); + + BuildTreeSerializer::load(Build_RetoverloadHandlerInvoker_Scenario1, buildNode); +} + +TEST_F(RetoverloadHandlerTest, RetoverloadHandlerInvoker) +{ + runBuildTest(true, false); +} + +// --- RetOverloadInRetExpr --- + +void RetOverloadInRetExprTest::SetUp() +{ + MethodScenarioTest::SetUp(); + + LoadDeclarationScenario(S_DefaultNamespace_5, RetOverloadInRetExprTest_Scenario1); + + BuildTreeSerializer::load(Build_RetOverloadInRetExprTest_Scenario1, controlOutputNode); + + targetRef = 4; +} + +TEST_F(RetOverloadInRetExprTest, RetOverloadInRetExpr) +{ + runTest(); +} diff --git a/elenasrc3/elena-tests/tests_declaration.cpp b/elenasrc3/elena-tests/tests_declaration.cpp index 4fcb6cca9..b12652f0c 100644 --- a/elenasrc3/elena-tests/tests_declaration.cpp +++ b/elenasrc3/elena-tests/tests_declaration.cpp @@ -2,7 +2,7 @@ // E L E N A P r o j e c t: ELENA Compiler // // This header contains ELENA Test Optimization Fixture implementation -// (C)2024, by Aleksey Rakov +// (C)2024-2025, by Aleksey Rakov //--------------------------------------------------------------------------- #include "declaration.h" @@ -16,7 +16,7 @@ using namespace elena_lang; constexpr auto Field_TemplateBasedArray = "namespace (class (nameattr (identifier \"A\" ())field (array_type (template_type (identifier \"VarTuple\" () template_arg (type(identifier \"object\" ())) template_arg (type(identifier \"object\" ()))))nameattr (identifier \"_array\" ())))"; -constexpr auto New_TemplateBasedArray = "namespace (class (attribute -2147467263 (identifier \"public\" ())nameattr (identifier \"program\" ())attribute -2147479546 ()method (attribute -2147479540 ()code (expression (assign_operation (object (attribute -2147479539 (identifier \"var\" ())identifier \"array\" ())expression (message_operation (object (array_type (template_type (attribute -2147479534 (identifier \"new\" ())identifier \"VarTuple\" ()template_arg (type (identifier \"object\" ()))template_arg (type (identifier \"object\" ())))))expression (object (integer \"10\" ()))))))EOP (eop \"}\" ())))))"; +constexpr auto New_TemplateBasedArray = "namespace (class (attribute -2147467263 (identifier \"public\" ())nameattr (identifier \"program\" ())attribute -2147479546 ()method (attribute -2147479540 ()code (expression (assign_operation (object (attribute -2147479539 (identifier \"var\" ())identifier \"array\" ())expression (message_operation (object (array_type (template_type (attribute -2147471342 (identifier \"new\" ())identifier \"VarTuple\" ()template_arg (type (identifier \"object\" ()))template_arg (type (identifier \"object\" ())))))expression (object (integer \"10\" ()))))))EOP (eop \"}\" ())))))"; constexpr auto Src_Field_TemplateBasedArray = "A { VarTuple[] _array; }"; constexpr auto Src_New_TemplateBasedArray = "public program() { var array := new VarTuple[](10); }"; diff --git a/elenasrc3/elenavm/elenavmmachine.cpp b/elenasrc3/elenavm/elenavmmachine.cpp index 0245745d1..0b6637169 100644 --- a/elenasrc3/elenavm/elenavmmachine.cpp +++ b/elenasrc3/elenavm/elenavmmachine.cpp @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------- // E L E N A P r o j e c t: ELENA VM declaration // -// (C)2021-2025, by Aleksey Rakov +// (C)2021-2026, by Aleksey Rakov // (C)2021-2024, by ELENA-LANG Org //--------------------------------------------------------------------------- @@ -294,7 +294,8 @@ inline ref_t getCmdMask(int command) } } -bool ELENAVMMachine :: compileVMTape(MemoryReader& reader, MemoryDump& tapeSymbol, ModuleBase* dummyModule, bool withSystemStartUp) +bool ELENAVMMachine :: compileVMTape(MemoryReader& reader, MemoryDump& tapeSymbol, ModuleBase* dummyModule, + bool withSystemStartUp, bool returnAcc) { CachedList, 5> symbols; @@ -416,6 +417,11 @@ bool ELENAVMMachine :: compileVMTape(MemoryReader& reader, MemoryDump& tapeSymbo } } + if (returnAcc) { + ByteCodeUtil::write(writer, ByteCode::StoreSI, 0); + ByteCodeUtil::write(writer, ByteCode::LoadSI, 0); + } + ByteCodeUtil::write(writer, ByteCode::ExtCloseN); ByteCodeUtil::write(writer, ByteCode::XQuit); @@ -450,7 +456,7 @@ void ELENAVMMachine :: resumeVM(SystemEnv* env, void* criricalHandler) } addr_t ELENAVMMachine :: interprete(SystemEnv* env, void* tape, pos_t size, - const char* criricalHandlerReference, bool withConfiguration, bool withSystemStartUp) + const char* criricalHandlerReference, bool withConfiguration, bool withSystemStartUp, bool returnAcc) { ByteArray tapeArray(tape, size); MemoryReader reader(&tapeArray); @@ -474,7 +480,7 @@ addr_t ELENAVMMachine :: interprete(SystemEnv* env, void* tape, pos_t size, void* address = nullptr; if (_initialized) { - if (compileVMTape(reader, tapeSymbol, dummyModule, withSystemStartUp)) + if (compileVMTape(reader, tapeSymbol, dummyModule, withSystemStartUp, returnAcc)) address = (void*)_jitLinker->resolveTemporalByteCode(tapeSymbol, dummyModule); resumeVM(env, (void*)criricalHandler); @@ -503,14 +509,14 @@ void ELENAVMMachine :: startSTA(SystemEnv* env, void* tape, const char* crirical } } -addr_t ELENAVMMachine :: evaluate(void* tape) +addr_t ELENAVMMachine :: evaluate(void* tape, bool returnAcc) { - return interprete(_env, tape, INVALID_POS, nullptr, false, true); + return interprete(_env, tape, INVALID_POS, nullptr, false, true, returnAcc); } bool ELENAVMMachine :: evaluateAndReturn(void* tape, char* output, size_t maxLength, size_t& copied) { - auto result = evaluate(tape); + auto result = evaluate(tape, true); if (result) { return SystemRoutineProvider::CopyResult(result, output, maxLength, copied); } diff --git a/elenasrc3/elenavm/elenavmmachine.h b/elenasrc3/elenavm/elenavmmachine.h index dc91ec753..66a6a1f88 100644 --- a/elenasrc3/elenavm/elenavmmachine.h +++ b/elenasrc3/elenavm/elenavmmachine.h @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------- // E L E N A P r o j e c t: ELENA VM declaration // -// (C)2022-2024, by Aleksey Rakov +// (C)2022-2026, by Aleksey Rakov //--------------------------------------------------------------------------- #ifndef ELENAVMMACHINE_H @@ -70,15 +70,16 @@ namespace elena_lang void addForward(ustr_t forwardLine); void addPackage(ustr_t packageLine); - addr_t interprete(SystemEnv* env, void* tape, pos_t size, - const char* criricalHandlerReference, bool withConfiguration, bool withSystemStartUp); + addr_t interprete(SystemEnv* env, void* tape, pos_t size, const char* criricalHandlerReference, + bool withConfiguration, bool withSystemStartUp, bool returnAcc = false); void onNewCode(); virtual void stopVM(); bool configurateVM(MemoryReader& reader, SystemEnv* env); - bool compileVMTape(MemoryReader& reader, MemoryDump& tapeSymbol, ModuleBase* dummyModule, bool withSystemStartUp); + bool compileVMTape(MemoryReader& reader, MemoryDump& tapeSymbol, ModuleBase* dummyModule, + bool withSystemStartUp, bool returnAcc); virtual void resumeVM(SystemEnv* env, void* criricalHandler); @@ -111,7 +112,7 @@ namespace elena_lang void startSTA(SystemEnv* env, void* tape, const char* criricalHandlerReference); - addr_t evaluate(void* tape); + addr_t evaluate(void* tape, bool returnAcc); bool evaluateAndReturn(void* tape, char* output, size_t maxLength, size_t& copied); diff --git a/elenasrc3/elenavm/vmcommon.h b/elenasrc3/elenavm/vmcommon.h index eb44590e2..751a78bd1 100644 --- a/elenasrc3/elenavm/vmcommon.h +++ b/elenasrc3/elenavm/vmcommon.h @@ -9,11 +9,11 @@ #ifndef VMCOMMON_H #define VMCOMMON_H -#define ELENAVM_REVISION_NUMBER 0x000E +#define ELENAVM_REVISION_NUMBER 0x000F namespace elena_lang { - constexpr auto ELENAVM_GREETING = "ELENA VM %d.%d.%d (%s) (C)2022-2025 by Aleksey Rakov, ELENA-LANG Org"; + constexpr auto ELENAVM_GREETING = "ELENA VM %d.%d.%d (%s) (C)2022-2026 by Aleksey Rakov, ELENA-LANG Org"; constexpr auto ELENAVM_INITIALIZING = "Initializing..."; } diff --git a/elenasrc3/elenavm/windows/dllmain.cpp b/elenasrc3/elenavm/windows/dllmain.cpp index ee253794c..f96d8c8b6 100644 --- a/elenasrc3/elenavm/windows/dllmain.cpp +++ b/elenasrc3/elenavm/windows/dllmain.cpp @@ -185,7 +185,7 @@ EXTERN_DLL_EXPORT int EvaluateVMLA(void* tape) int retVal = 0; try { - machine->evaluate(tape); + machine->evaluate(tape, false); } catch (InternalError err) { @@ -272,7 +272,7 @@ EXTERN_DLL_EXPORT int ExecuteVMLA(const char* target, const char* arg, char* out retVal = (int)copied; } else { - machine->evaluate(tape.get(0)); + machine->evaluate(tape.get(0), false); retVal = 0; } } diff --git a/elenasrc3/engine/buildtree.h b/elenasrc3/engine/buildtree.h index 5198e9f76..8823a9b23 100644 --- a/elenasrc3/engine/buildtree.h +++ b/elenasrc3/engine/buildtree.h @@ -387,6 +387,7 @@ namespace elena_lang map.add("copying_to_acc", BuildKey::CopyingToAcc); map.add("copying_to_acc_exact", BuildKey::CopyingToAccExact); map.add("copying_to_acc_field", BuildKey::CopyingToAccField); + map.add("copying_acc_field", BuildKey::CopyingAccField); map.add("create_class", BuildKey::CreatingClass); map.add("local", BuildKey::Local); map.add("intcondop", BuildKey::IntCondOp); @@ -468,6 +469,9 @@ namespace elena_lang map.add("const_param", BuildKey::Const); map.add("stack_index", BuildKey::StackIndex); map.add("long_int_op", BuildKey::LongIntOp); + map.add("idle", BuildKey::Idle); + map.add("true_const", BuildKey::TrueConst); + map.add("false_const", BuildKey::FalseConst); } }; diff --git a/elenasrc3/engine/bytecode.cpp b/elenasrc3/engine/bytecode.cpp index ddb6d568d..0ca683b4f 100644 --- a/elenasrc3/engine/bytecode.cpp +++ b/elenasrc3/engine/bytecode.cpp @@ -77,7 +77,8 @@ const ByteCode opNotUsingAcc[] = { const ByteCode opSetAcc[] = { ByteCode::SetR, ByteCode::SetDP, ByteCode::PeekR, ByteCode::SetFP, ByteCode::CreateR, ByteCode::XSetFP, ByteCode::PeekFI, ByteCode::PeekSI, ByteCode::SetSP, - ByteCode::PeekTLS, ByteCode::XCreateR, ByteCode::SelGrRR, ByteCode::NewIR, ByteCode::NewNR, ByteCode::CreateNR, + ByteCode::PeekTLS, ByteCode::XCreateR, ByteCode::SelGrRR, ByteCode::SelEqRR, ByteCode::SelLtRR, ByteCode::NewIR, ByteCode::NewNR, ByteCode::CreateNR, + ByteCode::XNewNR }; // --- Auxiliary --- @@ -977,7 +978,7 @@ inline bool contains(const ByteCode* list, size_t len, ByteCode bc) // NOTE : the copy of an iterator must be passed inline bool isAccFree(ByteCodeIterator bc_it) { - while (bc_it.eof()) { + while (!bc_it.eof()) { ByteCode bc = (*bc_it).code; if (contains(opSetAcc, sizeof(opSetAcc) / sizeof(ByteCode), bc)) return true; diff --git a/elenasrc3/engine/elena.h b/elenasrc3/engine/elena.h index 3075eecc6..f1ca13cc6 100644 --- a/elenasrc3/engine/elena.h +++ b/elenasrc3/engine/elena.h @@ -3,7 +3,7 @@ // // This file contains the common ELENA Compiler Engine templates, // classes, structures, functions and constants -// (C)2021-2025, by Aleksey Rakov +// (C)2021-2026, by Aleksey Rakov //--------------------------------------------------------------------------- #ifndef ELENA_H @@ -857,6 +857,7 @@ namespace elena_lang { ref_t typeRef; bool nillable; + bool constant; ref_t elementRef; bool nillableElement; @@ -879,6 +880,7 @@ namespace elena_lang { typeRef = elementRef = 0; nillableElement = nillable = false; + constant = false; } TypeInfo(ref_t typeRef) { @@ -886,6 +888,7 @@ namespace elena_lang this->elementRef = 0; this->nillable = false; this->nillableElement = false; + this->constant = false; } TypeInfo(ref_t typeRef, ref_t elemantRef) { @@ -893,6 +896,7 @@ namespace elena_lang this->elementRef = elemantRef; this->nillable = false; this->nillableElement = false; + this->constant = false; } TypeInfo(ref_t typeRef, ref_t elemantRef, bool nillable) { @@ -900,6 +904,7 @@ namespace elena_lang this->elementRef = elemantRef; this->nillable = nillable; this->nillableElement = false; + this->constant = false; } TypeInfo(ref_t typeRef, ref_t elemantRef, bool nillable, bool nillableElement) { @@ -907,6 +912,15 @@ namespace elena_lang this->elementRef = elemantRef; this->nillable = nillable; this->nillableElement = nillableElement; + this->constant = false; + } + TypeInfo(ref_t typeRef, ref_t elemantRef, bool nillable, bool nillableElement, bool constant) + { + this->typeRef = typeRef; + this->elementRef = elemantRef; + this->nillable = nillable; + this->nillableElement = nillableElement; + this->constant = constant; } }; diff --git a/elenasrc3/engine/elenaconst.h b/elenasrc3/engine/elenaconst.h index 7f8395735..22df4e1c1 100644 --- a/elenasrc3/engine/elenaconst.h +++ b/elenasrc3/engine/elenaconst.h @@ -12,12 +12,12 @@ namespace elena_lang { // --- Common ELENA Engine constants --- -#define ENGINE_MAJOR_VERSION 6 // ELENA Engine version -#define ENGINE_MINOR_VERSION 8 +#define ENGINE_MAJOR_VERSION 6 // ELENA Engine version +#define ENGINE_MINOR_VERSION 9 - constexpr auto LINE_LEN = 0x1000; // the maximal source line length - constexpr auto IDENTIFIER_LEN = 0x0300; // the maximal identifier length - constexpr auto MESSAGE_LEN = 0x500; // the maximal message length + constexpr auto LINE_LEN = 0x1000; // the maximal source line length + constexpr auto IDENTIFIER_LEN = 0x0300; // the maximal identifier length + constexpr auto MESSAGE_LEN = 0x500; // the maximal message length // --- ELENA Standart message constants --- constexpr auto ACTION_ORDER = 9; @@ -30,19 +30,19 @@ namespace elena_lang constexpr auto VARIADIC_MESSAGE = 0x040u; constexpr auto PROPERTY_MESSAGE = 0x080u; constexpr auto CONVERSION_MESSAGE = 0x0C0u; - constexpr auto PREFIX_MESSAGE_MASK = 0x0C0u; // HOTFIX : is used to correctly identify VARIADIC_MESSAGE / PROPERTY_MESSAGE / CONVERSION_MESSAGE + constexpr auto PREFIX_MESSAGE_MASK = 0x0C0u; // HOTFIX : is used to correctly identify VARIADIC_MESSAGE / PROPERTY_MESSAGE / CONVERSION_MESSAGE constexpr auto ARG_COUNT = 0x01Eu; constexpr auto ARG_MASK = 0x01Fu; // --- ELENA Module structure constants --- - constexpr auto ELENA_SIGNITURE = "ELENA."; // the stand alone image - constexpr auto ELENA_VM_SIGNITURE = "VM.ELENA."; // the stand alone image - constexpr auto MODULE_SIGNATURE = "ELENA.0606"; // the module version + constexpr auto ELENA_SIGNITURE = "ELENA."; // the stand alone image + constexpr auto ELENA_VM_SIGNITURE = "VM.ELENA."; // the stand alone image + constexpr auto MODULE_SIGNATURE = "ELENA.0608"; // the module version constexpr auto DEBUG_MODULE_SIGNATURE = "ED.06"; // --- ELENA core module names --- - constexpr auto CORE_ALIAS = "core"; // Core functionality + constexpr auto CORE_ALIAS = "core"; // Core functionality // --- ELENA predefined module names --- constexpr auto BINARY_MODULE = "$binary"; diff --git a/elenasrc3/engine/jitcompiler.cpp b/elenasrc3/engine/jitcompiler.cpp index 57e0252a2..d47af2055 100644 --- a/elenasrc3/engine/jitcompiler.cpp +++ b/elenasrc3/engine/jitcompiler.cpp @@ -2039,6 +2039,8 @@ void elena_lang :: loadMROp(JITCompilerScope* scope) pos_t length = *(pos_t*)((char*)code - sizeof(pos_t)); ref_t arg2 = scope->command.arg2 & ~mskAnyRef; + int argMask = scope->getAltMode() ? mskHMTMethodOffset : mskVMTMethodAddress; + // simply copy correspondent inline code writer->write(code, length); @@ -2050,38 +2052,38 @@ void elena_lang :: loadMROp(JITCompilerScope* scope) writer->seek(position + entries->offset); switch (entries->reference) { case PTR32_2: - scope->compiler->writeVMTMethodArg(scope, arg2 | mskVMTMethodAddress, + scope->compiler->writeVMTMethodArg(scope, arg2 | argMask, 0, scope->helper->importMessage(scope->command.arg1), mskRef32); break; case RELPTR32_2: - scope->compiler->writeVMTMethodArg(scope, arg2 | mskVMTMethodAddress, + scope->compiler->writeVMTMethodArg(scope, arg2 | argMask, 0, scope->helper->importMessage(scope->command.arg1), mskRelRef32); break; case DISP32HI_2: - scope->compiler->writeVMTMethodArg(scope, arg2 | mskVMTMethodAddress, + scope->compiler->writeVMTMethodArg(scope, arg2 | argMask, 0, scope->helper->importMessage(scope->command.arg1), mskDisp32Hi); break; case DISP32LO_2: - scope->compiler->writeVMTMethodArg(scope, arg2 | mskVMTMethodAddress, + scope->compiler->writeVMTMethodArg(scope, arg2 | argMask, 0, scope->helper->importMessage(scope->command.arg1), mskDisp32Lo); break; case XDISP32HI_2: - scope->compiler->writeVMTMethodArg(scope, arg2 | mskVMTMethodAddress, + scope->compiler->writeVMTMethodArg(scope, arg2 | argMask, 0, scope->helper->importMessage(scope->command.arg1), mskXDisp32Hi); break; case XDISP32LO_2: - scope->compiler->writeVMTMethodArg(scope, arg2 | mskVMTMethodAddress, + scope->compiler->writeVMTMethodArg(scope, arg2 | argMask, 0, scope->helper->importMessage(scope->command.arg1), mskXDisp32Lo); break; case PTR32HI_2: { - scope->compiler->writeVMTMethodArg(scope, arg2 | mskVMTMethodAddress, + scope->compiler->writeVMTMethodArg(scope, arg2 | argMask, 0, scope->helper->importMessage(scope->command.arg1), mskRef32Hi); break; } case PTR32LO_2: { - scope->compiler->writeVMTMethodArg(scope, arg2 | mskVMTMethodAddress, + scope->compiler->writeVMTMethodArg(scope, arg2 | argMask, 0, scope->helper->importMessage(scope->command.arg1), mskRef32Lo); break; } diff --git a/elenasrc3/engine/langcommon.h b/elenasrc3/engine/langcommon.h index bfb8f3563..d557df944 100644 --- a/elenasrc3/engine/langcommon.h +++ b/elenasrc3/engine/langcommon.h @@ -3,7 +3,7 @@ // // This file contains the language common constants // -// (C)2021-2025, by Aleksey Rakov +// (C)2021-2026, by Aleksey Rakov //--------------------------------------------------------------------------- #ifndef LANGCOMMON_H @@ -19,10 +19,11 @@ namespace elena_lang enum MetaHint : int { - mhNone = 0, - mhStandart = 1, - mhNoValidation = 2, - mhNoPrologEpilog = 4, + mhNone = 0, + mhStandart = 1, + mhNoValidation = 2, + mhNoPrologEpilog = 4, + mhNoTemplateCache = 8, }; enum class MethodHint : ref_t @@ -70,6 +71,8 @@ namespace elena_lang }; // --- MethodInfo --- + constexpr int EnforcedNillableArgs = 0x80000000; + struct MethodInfo { bool inherited; @@ -417,6 +420,7 @@ namespace elena_lang constexpr auto wrnUnassignedVariable = 428; constexpr auto wrnLessAccessible = 429; constexpr auto wrnUnknownModule = 430; + constexpr auto wrnNonNillableArgument = 431; constexpr auto wrnSyntaxFileNotFound = 500; constexpr auto wrnInvalidConfig = 501; @@ -443,6 +447,7 @@ namespace elena_lang constexpr auto infoInternalDefConstructor = 710; constexpr auto infoMessageInfo = 711; constexpr auto infoSourceClass = 712; + constexpr auto infoMissingTemplate = 713; constexpr auto errVMBroken = 800; constexpr auto errVMNotInitialized = 801; @@ -499,11 +504,13 @@ namespace elena_lang constexpr auto V_SEALED = 0x80003001u; constexpr auto V_ABSTRACT = 0x80003002u; constexpr auto V_CLOSED = 0x80003003u; + constexpr auto V_EMBEDDABLE = 0x80003004u; constexpr auto V_PREDEFINED = 0x80003005u; + constexpr auto V_CONVERSION = 0x80003011u; + constexpr auto V_NEWOP = 0x80003012u; /// scope_prefix: constexpr auto V_CONST = 0x80002001u; - constexpr auto V_EMBEDDABLE = 0x80002002u; constexpr auto V_WRAPPER = 0x80002003u; constexpr auto V_READONLY = 0x80002004u; constexpr auto V_OUTWRAPPER = 0x80002005u; @@ -526,8 +533,6 @@ namespace elena_lang constexpr auto V_VARIABLE = 0x8000100Du; constexpr auto V_MEMBER = 0x8000100Eu; constexpr auto V_STATIC = 0x8000100Fu; - constexpr auto V_CONVERSION = 0x80001011u; - constexpr auto V_NEWOP = 0x80001012u; constexpr auto V_DISPATCHER = 0x80001013u; constexpr auto V_TEXTBLOCK = 0x80001014u; constexpr auto V_EXTERN = 0x80001015u; @@ -712,7 +717,7 @@ namespace elena_lang constexpr auto VM_TAPE = "$elena'meta$startUpTape"; - constexpr auto PROGRAM_ENTRY = "$forwards'program"; // used by the linker to define the debug entry + constexpr auto PROGRAM_ENTRY = "$forwards'Program"; // used by the linker to define the debug entry constexpr auto SYSTEM_FORWARD = "$system_entry"; // the system entry constexpr auto SUPER_FORWARD = "$super"; // the common class predecessor @@ -732,7 +737,8 @@ namespace elena_lang constexpr auto FALSE_FORWARD = "$false"; // the false boolean value constexpr auto WRAPPER_FORWARD = "$ref"; // the wrapper template constexpr auto ARRAY_FORWARD = "$array"; // the array template - constexpr auto VARIADIC_ARRAY_FORWARD = "$varray"; // the array template + constexpr auto CONST_ARRAY_FORWARD = "$const_array"; // the constant array template + constexpr auto VARIADIC_ARRAY_FORWARD = "$varray"; // the variadic array template constexpr auto MESSAGE_FORWARD = "$message"; // the message name class constexpr auto PROPERTY_NAME_FORWARD = "$prop_subject"; // the property message name class constexpr auto MESSAGE_NAME_FORWARD = "$subject"; // the message class @@ -787,6 +793,7 @@ namespace elena_lang constexpr auto PROFILE_ATTR = "profile"; constexpr auto BASE_PATH_ATTR = "base_path"; constexpr auto PLATFORM_ATTR = "platform"; + constexpr auto NAME_ATTR = "name"; constexpr auto TEMPLATE_CATEGORY = "templates/*"; constexpr auto PRIMITIVE_CATEGORY = "primitives/*"; diff --git a/elenasrc3/engine/libman.cpp b/elenasrc3/engine/libman.cpp index 216745e03..b6e4123c3 100644 --- a/elenasrc3/engine/libman.cpp +++ b/elenasrc3/engine/libman.cpp @@ -206,6 +206,23 @@ ModuleBase* LibraryProvider :: resolveModule(ustr_t referenceName, ref_t& refere return nullptr; if (NamespaceString::compareNs(referenceName, ROOT_MODULE)) { + if (referenceName.find('|') != NOTFOUND_POS) { + // HOTFIX : support both program & Program + size_t index = referenceName.find('|'); + + IdentifierString copy(referenceName, index); + auto result = resolveModule(*copy, reference, true, debugModule); + if (result == nullptr) { + size_t nsIndex = referenceName.findLast('\''); + copy.truncate(nsIndex + 1); + copy.append(referenceName.str() + index + 1); + + result = resolveModule(*copy, reference, true, debugModule); + } + + return result; + } + ReferenceName name; ReferenceName::copyProperName(name, referenceName); @@ -450,6 +467,29 @@ ReferenceInfo LibraryProvider :: retrieveReferenceInfo(ModuleBase* module, ref_t } if (NamespaceString::compareNs(referenceName, ROOT_MODULE)) { + if (referenceName.find('|') != NOTFOUND_POS) { + // HOTFIX : support both program & Program + size_t index = referenceName.find('|'); + size_t nsIndex = referenceName.findLast('\''); + + IdentifierString copy(*_namespace); + copy.append(referenceName.str() + nsIndex, index - nsIndex); + + auto result = retrieveReferenceInfo(*copy, forwardResolver); + if (result.module == nullptr) { + copy.copy(*_namespace); + copy.append('\''); + copy.append(referenceName.str() + index + 1); + + result = retrieveReferenceInfo(*copy, forwardResolver); + } + + if (!result.module) + throw JITUnresolvedException(ReferenceInfo(referenceName)); + + return result; + } + ReferenceName name; ReferenceName::copyProperName(name, referenceName); diff --git a/elenasrc3/engine/syntaxtree.cpp b/elenasrc3/engine/syntaxtree.cpp index b2a55df0f..74d8aff8c 100644 --- a/elenasrc3/engine/syntaxtree.cpp +++ b/elenasrc3/engine/syntaxtree.cpp @@ -108,6 +108,7 @@ void SyntaxTree :: loadTokens(TokenMap& map) map.add("shr_op", SyntaxKey::ShrOperation); map.add("band_op", SyntaxKey::BAndOperation); map.add("final_block", SyntaxKey::FinallyBlock); + map.add("inline_prop_template", SyntaxKey::InlinePropertyTemplate); } bool SyntaxTree :: save(MemoryBase* section) diff --git a/elenasrc3/gui/text.cpp b/elenasrc3/gui/text.cpp index c8af16680..4f5a688fe 100644 --- a/elenasrc3/gui/text.cpp +++ b/elenasrc3/gui/text.cpp @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------- // E L E N A P r o j e c t: ELENA IDE // Text class body -// (C)2021-2023, by Aleksey Rakov +// (C)2021-2026, by Aleksey Rakov //--------------------------------------------------------------------------- #include "guicommon.h" @@ -560,7 +560,7 @@ void Text :: copyLineTo(TextBookmark& bookmark, TextWriter& writer, pos_ else { size_t chLen = TextBookmark::charLength(line, i); if (chLen > 1) { - if (i + chLen < count) { + if (i + chLen <= count) { writer.write(&line[i], (pos_t)chLen); i += (chLen - 1); } @@ -619,7 +619,7 @@ void Text :: copyLineToX(TextBookmark& bookmark, TextWriter& writer, pos else { size_t chLen = TextBookmark::charLength(line, i); if (chLen > 1) { - if (i + chLen < count) { + if (i + chLen <= count) { writer.write(&line[i], chLen); i += ((pos_t)chLen - 1); } diff --git a/elenasrc3/ide/eng/messages.h b/elenasrc3/ide/eng/messages.h index 458a84950..70985d5dd 100644 --- a/elenasrc3/ide/eng/messages.h +++ b/elenasrc3/ide/eng/messages.h @@ -9,7 +9,7 @@ namespace elena_lang { - constexpr auto APP_NAME = _T("ELENA IDE 6.6"); + constexpr auto APP_NAME = _T("ELENA IDE 6.9"); constexpr auto OPEN_FILE_CAPTION = _T("Open File"); constexpr auto OPEN_PROJECT_CAPTION = _T("Open Project"); @@ -49,7 +49,7 @@ namespace elena_lang constexpr auto HINT_GOTOSOURCE = _T("Go to Source"); // --- About dialog --- - constexpr auto MIT_LICENSE = _T("The MIT License (MIT)\r\n\r\nCopyright (c) 2006-2024: Aleksey Rakov and other contributors:\r\n\r\nhttps://github.com/ELENA-LANG/elena-lang/blob/master/doc/contributors\r\n\r\nPermission is hereby granted, free of charge, to any person obtaining a copy\r\nof this software and associated documentation files (the \"Software\"), to deal\r\nin the Software without restriction, including without limitation the rights\r\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\ncopies of the Software, and to permit persons to whom the Software is\r\nfurnished to do so, subject to the following conditions:\r\n\r\nThe above copyright notice and this permission notice shall be included in all\r\ncopies or substantial portions of the Software.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r\nSOFTWARE."); + constexpr auto MIT_LICENSE = _T("The MIT License (MIT)\r\n\r\nCopyright (c) 2006-2026: Aleksey Rakov and other contributors:\r\n\r\nhttps://github.com/ELENA-LANG/elena-lang/blob/master/doc/contributors\r\n\r\nPermission is hereby granted, free of charge, to any person obtaining a copy\r\nof this software and associated documentation files (the \"Software\"), to deal\r\nin the Software without restriction, including without limitation the rights\r\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\ncopies of the Software, and to permit persons to whom the Software is\r\nfurnished to do so, subject to the following conditions:\r\n\r\nThe above copyright notice and this permission notice shall be included in all\r\ncopies or substantial portions of the Software.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r\nSOFTWARE."); constexpr auto ELENA_HOMEPAGE = _T("https://elena-lang.github.io/"); } diff --git a/elenasrc3/ide/idecontroller.cpp b/elenasrc3/ide/idecontroller.cpp index c3043c596..3be7f9c0c 100644 --- a/elenasrc3/ide/idecontroller.cpp +++ b/elenasrc3/ide/idecontroller.cpp @@ -1195,9 +1195,8 @@ void IDEController :: init(IDEModel* model, int& status) PathString path(model->projectModel.lastOpenProjects.get(1)); if (PathUtil::checkExtension(*path, "l")) { - if (openFile(model, *path, status)) { - model->changeStatus(IDEStatus::Ready); - } + status |= projectController.openSingleFileProject(model->projectModel, *path); + model->changeStatus(IDEStatus::Ready); } else { int retVal = openProject(model, *path); @@ -1274,7 +1273,7 @@ inline void removeDuplicate(ProjectPaths& lastOpenFiles, path_t value) } } -inline void addToRecentProjects(IDEModel* model, path_t path) +void IDEController :: addToRecentProjects(IDEModel* model, path_t path) { removeDuplicate(model->projectModel.lastOpenProjects, path); @@ -1413,7 +1412,7 @@ bool IDEController::ifProjectNotSaved(IDEModel* model) bool IDEController :: ifProjectUnnamed(IDEModel* model) { - return model->projectModel.projectPath.empty(); + return !model->projectModel.singleSourceProject && model->projectModel.projectPath.empty(); } bool IDEController :: doSaveFile(IDEModel* model, int index, bool forcedSave, path_t filePath) diff --git a/elenasrc3/ide/idecontroller.h b/elenasrc3/ide/idecontroller.h index 2fb6961ac..373f1752a 100644 --- a/elenasrc3/ide/idecontroller.h +++ b/elenasrc3/ide/idecontroller.h @@ -185,6 +185,8 @@ namespace elena_lang SourceViewController sourceController; ProjectController projectController; + void addToRecentProjects(IDEModel* model, path_t path); + void loadSystemConfig(IDEModel* model, path_t configPath, ustr_t typeXPath, ustr_t platformXPath); bool loadConfig(IDEModel* model, path_t configPath, GUISettinngs& guiSettings); diff --git a/elenasrc3/ide/ideversion.h b/elenasrc3/ide/ideversion.h index b7a22907e..f837bfeaf 100644 --- a/elenasrc3/ide/ideversion.h +++ b/elenasrc3/ide/ideversion.h @@ -1,2 +1,2 @@ -#define IDE_REVISION_NUMBER 58 +#define IDE_REVISION_NUMBER 61 diff --git a/elenasrc3/ide/windows/main.cpp b/elenasrc3/ide/windows/main.cpp index ccf7efbb6..e7b5e5f76 100644 --- a/elenasrc3/ide/windows/main.cpp +++ b/elenasrc3/ide/windows/main.cpp @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------- // E L E N A P r o j e c t: ELENA IDE // WinAPI32 program entry -// (C)2021-2024, by Aleksey Rakov +// (C)2021-2026, by Aleksey Rakov //--------------------------------------------------------------------------- #include "factory.h" @@ -58,12 +58,61 @@ bool compareFileModifiedTime(path_t sour, path_t dest) return sourceDT > moduleDT; } +// --- loadCommandLine --- + +inline void setOption(IDEController* ideController, IDEModel* model, path_t parameter, path_t currentPath) +{ + if (parameter[0] != '-') { + PathString path; + if (PathUtil::isRelative(parameter, parameter.length())) { + path.copy(currentPath); + path.combine(parameter); + } + else path.copy(parameter); + + if (PathUtil::checkExtension(parameter, _T("l"))) { + ideController->addToRecentProjects(model, *path); + } + else if (PathUtil::checkExtension(parameter, _T("prj"))) { + ideController->addToRecentProjects(model, *path); + } + } + else if (text_str(parameter).compare(_T("-sclassic"))) { + model->sourceViewModel.schemeIndex = 1; + } + else if (text_str(parameter).compare(_T("-sdark"))) { + model->sourceViewModel.schemeIndex = 2; + } +} + +void loadCommandLine(IDEController* ideController, IDEModel* model, LPWSTR cmdWLine) +{ + TCHAR currentPath[MAX_PATH + 1]; + size_t len = GetCurrentDirectory(MAX_PATH, currentPath); + if (len <= 0) + return; + + size_t start = 0; + for (size_t i = 1; i <= wcslen(cmdWLine); i++) { + if (cmdWLine[i] == ' ' || cmdWLine[i] == 0) { + PathString parameter(cmdWLine + start, i - start); + + /*// check if a custom config file should be loaded + if (text_str(parameter).compare(CMD_CONFIG_PATH, _ELENA_::getlength(CMD_CONFIG_PATH))) { + configPath.copy(model->paths.appPath.c_str()); + configPath.combine(parameter + _ELENA_::getlength(CMD_CONFIG_PATH)); + } + else*/ setOption(ideController, model, *parameter, path_t(currentPath)); + + start = i + 1; + } + } +} + typedef Win32DebugAdapter DebugProcess; -// Forward declarations of functions included in this code module: -ATOM MyRegisterClass(HINSTANCE hInstance); -BOOL InitInstance(HINSTANCE, int); -INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM); +Win32Process vmConsoleProcess(50); +Win32Process outputProcess(50); int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, @@ -80,8 +129,6 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance, TextViewSettings textViewSettings = { EOLMode::CRLF, false, 3 }; IDEModel ideModel(textViewSettings); - Win32Process vmConsoleProcess(50); - Win32Process outputProcess(50); DebugProcess debugProcess; IDEController ideController(&outputProcess, &vmConsoleProcess, &debugProcess, &ideModel, CURRENT_PLATFORM, &pathHelper, compareFileModifiedTime); @@ -106,6 +153,8 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance, ideController.setNotifier(app); + loadCommandLine(&ideController, &ideModel, lpCmdLine); + StartUpEvent startUpEvent(STATUS_NONE); int retVal = app->run(ideWindow, ideModel.appMaximized, &startUpEvent); @@ -115,26 +164,3 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance, return retVal; } - -// Message handler for about box. -INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) -{ - UNREFERENCED_PARAMETER(lParam); - switch (message) - { - case WM_INITDIALOG: - return (INT_PTR)TRUE; - - case WM_COMMAND: - if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) - { - EndDialog(hDlg, LOWORD(wParam)); - return (INT_PTR)TRUE; - } - break; - default: - // to make compiler happy - break; - } - return (INT_PTR)FALSE; -} diff --git a/elenasrc3/ide/windows/winide.cpp b/elenasrc3/ide/windows/winide.cpp index b27839294..9d582ec7c 100644 --- a/elenasrc3/ide/windows/winide.cpp +++ b/elenasrc3/ide/windows/winide.cpp @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------- // E L E N A P r o j e c t: ELENA IDE // WinAPI IDE Window Implementation File -// (C)2021-2025, by Aleksey Rakov +// (C)2021-2026, by Aleksey Rakov //--------------------------------------------------------------------------- #include @@ -276,7 +276,8 @@ IDEWindow :: IDEWindow(wstr_t title, IDEController* controller, IDEModel* model, fontSettingsDialog(instance, this), ideSettingsDialog(instance, this, model), debuggerSettingsDialog(instance, this, &model->projectModel), - _docViewListener(nullptr) + _docViewListener(nullptr), + _tabTTHandle(0) { this->_viewFactory = viewFactory; diff --git a/elenasrc3/tools/asmc/asmconst.h b/elenasrc3/tools/asmc/asmconst.h index 874d53246..5cccffbe2 100644 --- a/elenasrc3/tools/asmc/asmconst.h +++ b/elenasrc3/tools/asmc/asmconst.h @@ -12,7 +12,7 @@ namespace elena_lang { - #define ASM_REVISION_NUMBER 0x0015 + #define ASM_REVISION_NUMBER 0x0017 constexpr auto N_ARGUMENT1 = "__n_1"; constexpr auto N_ARGUMENT2 = "__n_2"; diff --git a/elenasrc3/tools/ecv/ecvconst.h b/elenasrc3/tools/ecv/ecvconst.h index a90bf95ad..3eca338bf 100644 --- a/elenasrc3/tools/ecv/ecvconst.h +++ b/elenasrc3/tools/ecv/ecvconst.h @@ -3,7 +3,7 @@ // // This file contains the ecv common interfaces & types // -// (C)2021-2025, by Aleksey Rakov +// (C)2021-2026, by Aleksey Rakov //--------------------------------------------------------------------------- #ifndef ECVCONST_H @@ -11,9 +11,9 @@ namespace elena_lang { - #define ECV_REVISION_NUMBER 0x000A + #define ECV_REVISION_NUMBER 0x000C - constexpr auto ECV_GREETING = "ELENA command line ByteCode Viewer %d.%d.%d (C)2021-25 by Aleksey Rakov\n"; + constexpr auto ECV_GREETING = "ELENA command line ByteCode Viewer %d.%d.%d (C)2021-26 by Aleksey Rakov\n"; constexpr auto ECV_MODULE_NOTLOADED = "cannot load a module: %s"; constexpr auto ECV_MODULE_LOADED = "module %s loaded\n"; diff --git a/elenasrc3/tools/ecv/ecviewer.cpp b/elenasrc3/tools/ecv/ecviewer.cpp index 481288b35..3b4e9959f 100644 --- a/elenasrc3/tools/ecv/ecviewer.cpp +++ b/elenasrc3/tools/ecv/ecviewer.cpp @@ -3,7 +3,7 @@ // // This is a main file containing ecode viewer code // -// (C)2021-2025, by Aleksey Rakov +// (C)2021-2026, by Aleksey Rakov //--------------------------------------------------------------------------- #include "ecviewer.h" @@ -153,6 +153,7 @@ void ByteCodeViewer :: printHelp() _presenter->print("-a - toggle displaying class attributes mode\n"); _presenter->print("-b - toggle bytecode mode\n"); _presenter->print("-h - toggle displaying method hints mode\n"); + _presenter->print("-i - toggle ignore-internal classes mode\n"); _presenter->print("-p - toggle pagination mode\n"); _presenter->print("-q - quit\n"); _presenter->print("-t - toggle ignore-breakpoint mode\n"); @@ -1087,11 +1088,12 @@ struct BCVSessionInfo int row; int pageSize; ustr_t filter; + bool ignoreInternalClasses; }; void ByteCodeViewer :: listMembers(ustr_t filter) { - BCVSessionInfo info = { this, 1, _pageSize, filter }; + BCVSessionInfo info = { this, 1, _pageSize, filter, _ignoreInternalClasses }; _module->forEachReference(&info, [](ModuleBase* module, ref_t reference, void* arg) { @@ -1100,6 +1102,9 @@ void ByteCodeViewer :: listMembers(ustr_t filter) BCVSessionInfo* info = (BCVSessionInfo*)arg; if (isWeakReference(referenceName)) { + if (info->ignoreInternalClasses && referenceName.findStr(INLINE_CLASSNAME) != NOTFOUND_POS) + return; + if (!info->filter.empty() && referenceName.findStr(info->filter) == NOTFOUND_POS) return; @@ -1162,6 +1167,10 @@ void ByteCodeViewer :: runSession() _showMethodInfo = !_showMethodInfo; _presenter->print("Method hint mode is %s", _showMethodInfo ? "true" : "false"); break; + case 'i': + _ignoreInternalClasses = !_ignoreInternalClasses; + _presenter->print("Ignore internal classes mode is %s", _ignoreInternalClasses ? "true" : "false"); + break; case 'a': _showClassAttributes = !_showClassAttributes; _presenter->print("Displaying class attributes mode is %s", _showClassAttributes ? "true" : "false"); diff --git a/elenasrc3/tools/ecv/ecviewer.h b/elenasrc3/tools/ecv/ecviewer.h index d07e789d9..c4bba32c6 100644 --- a/elenasrc3/tools/ecv/ecviewer.h +++ b/elenasrc3/tools/ecv/ecviewer.h @@ -3,7 +3,7 @@ // // This is a main file containing ecode viewer code // -// (C)2021-2024, by Aleksey Rakov +// (C)2021-2026, by Aleksey Rakov //--------------------------------------------------------------------------- #ifndef ECVIEWER_H @@ -43,6 +43,7 @@ namespace elena_lang bool _showBytecodes; bool _showMethodInfo; bool _ignoreBreakpoints; + bool _ignoreInternalClasses; bool _showClassAttributes; MemoryBase* findProcedureCode(ustr_t referenceName); @@ -120,6 +121,7 @@ namespace elena_lang _showBytecodes = false; _showMethodInfo = false; _ignoreBreakpoints = true; + _ignoreInternalClasses = true; _showClassAttributes = false; } virtual ~ByteCodeViewer() diff --git a/elenasrc3/tools/ecv/windows/ecv.cpp b/elenasrc3/tools/ecv/windows/ecv.cpp index 2e7706ae4..331a47a62 100644 --- a/elenasrc3/tools/ecv/windows/ecv.cpp +++ b/elenasrc3/tools/ecv/windows/ecv.cpp @@ -3,7 +3,7 @@ // // This is a main file containing ecode viewer code // -// (C)2021-2025, by Aleksey Rakov +// (C)2021-2026, by Aleksey Rakov //--------------------------------------------------------------------------- #include diff --git a/examples60/console/binary/binary.l b/examples60/console/binary/binary.l index eacc614eb..ada106bdd 100644 --- a/examples60/console/binary/binary.l +++ b/examples60/console/binary/binary.l @@ -2,7 +2,7 @@ import extensions; // --- Program --- -public program() +public Program() { // reading var number := Console.write("Enter the number you want to convert: ").loadLineTo(Integer.new()); diff --git a/examples60/console/bsort/bsort.l b/examples60/console/bsort/bsort.l index ceacf963b..19888251f 100644 --- a/examples60/console/bsort/bsort.l +++ b/examples60/console/bsort/bsort.l @@ -62,7 +62,7 @@ extension bsortOp // === Program === -public program() +public Program() { // 1. Create the array var size := Console.write("Enter the array size:").loadLineTo(Integer.new()).Value; diff --git a/examples60/console/collatz/collatz.l b/examples60/console/collatz/collatz.l index ebd9f4e91..1a2106d51 100644 --- a/examples60/console/collatz/collatz.l +++ b/examples60/console/collatz/collatz.l @@ -148,7 +148,7 @@ altcolsingle(x) } //end -public program() +public Program() { altcol(7); altcol(44); diff --git a/examples60/console/datetime/control.l b/examples60/console/datetime/control.l index 5671898b6..cf5674360 100644 --- a/examples60/console/datetime/control.l +++ b/examples60/console/datetime/control.l @@ -23,7 +23,7 @@ public singleton Control 2 : { ^UtcNow.toString() } 3 : { ^Now.Year.toString() } 4 : { ^Now.toShortTimeString() } - 7 : { forward program.stop(); ^ EmptyString } + 7 : { forward Program.stop(); ^ EmptyString } ! : { ^"Invalid choice" } } } \ No newline at end of file diff --git a/examples60/console/datetime/datetime.linux.prj b/examples60/console/datetime/datetime.linux.prj index 431ce7a1e..b5c7fe8ef 100644 --- a/examples60/console/datetime/datetime.linux.prj +++ b/examples60/console/datetime/datetime.linux.prj @@ -29,7 +29,7 @@ - extensions'ProgramLoop - datetime'Control + extensions'ProgramLoop + datetime'Control \ No newline at end of file diff --git a/examples60/console/datetime/datetime.prj b/examples60/console/datetime/datetime.prj index 086dc4b15..1610f3bf2 100644 --- a/examples60/console/datetime/datetime.prj +++ b/examples60/console/datetime/datetime.prj @@ -19,7 +19,7 @@ - extensions'ProgramLoop - datetime'Control + extensions'ProgramLoop + datetime'Control \ No newline at end of file diff --git a/examples60/console/goods/goods.l b/examples60/console/goods/goods.l index 08501a004..db218a0fd 100644 --- a/examples60/console/goods/goods.l +++ b/examples60/console/goods/goods.l @@ -65,7 +65,7 @@ class Adapter // --- Program --- -public program() +public Program() { if(Program_arguments.Length == 1) { Console.printLine("Please provide the path to the file to view"); AbortException.raise() }; diff --git a/examples60/console/helloworld/helloworld.l b/examples60/console/helloworld/helloworld.l index 623216df4..e5ab66d61 100644 --- a/examples60/console/helloworld/helloworld.l +++ b/examples60/console/helloworld/helloworld.l @@ -1,6 +1,6 @@ // --- Program --- -public program() +public Program() { Console.writeLine("Hello World"); diff --git a/examples60/console/matrix/matrix.l b/examples60/console/matrix/matrix.l index a7101acd9..95ff04793 100644 --- a/examples60/console/matrix/matrix.l +++ b/examples60/console/matrix/matrix.l @@ -124,7 +124,7 @@ Your choice:"; ^ identity.toString() } "6" : { - forward program.stop() + forward Program.stop() } } } diff --git a/examples60/console/matrix/matrix.prj b/examples60/console/matrix/matrix.prj index af8e9f237..fd526152c 100644 --- a/examples60/console/matrix/matrix.prj +++ b/examples60/console/matrix/matrix.prj @@ -20,7 +20,7 @@ - extensions'ProgramLoop - matrix'Control + extensions'ProgramLoop + matrix'Control \ No newline at end of file diff --git a/examples60/console/pi/pi.l b/examples60/console/pi/pi.l index 3c3de4100..63a775edd 100644 --- a/examples60/console/pi/pi.l +++ b/examples60/console/pi/pi.l @@ -3,7 +3,7 @@ import extensions; const int MAX = 50000000; -public program() +public Program() { var started := Now; diff --git a/examples60/console/pi2/pi2.l b/examples60/console/pi2/pi2.l index 0398a9a43..d124dd852 100644 --- a/examples60/console/pi2/pi2.l +++ b/examples60/console/pi2/pi2.l @@ -4,7 +4,7 @@ import extensions; const int ARRAY_SIZE = 32768; -public program() +public Program() { int casas := 50; if(Program_arguments.Length > 1) diff --git a/examples60/console/random/random.l b/examples60/console/random/random.l index be5ba9538..215c8da62 100644 --- a/examples60/console/random/random.l +++ b/examples60/console/random/random.l @@ -2,7 +2,7 @@ import extensions; -// --- program --- +// --- Program --- const int rows = 4; const int cols = 6; @@ -10,7 +10,7 @@ const int cols = 6; const int runCount = 1000000; const int distGroupCount = 20; -public program() +public Program() { auto intGroupSize := (1.0 + IntNumber.MaxValue) / distGroupCount; @@ -22,7 +22,7 @@ public program() { for(int j := 0; j <= cols; j += 1) { - Console.printPaddingRight(12, randomGenerator.nextReal()); + Console.printPaddingRight(12, Random.nextReal()); }; Console.writeLine() @@ -34,7 +34,7 @@ public program() { for(int j := 0; j <= cols; j += 1) { - Console.printPaddingRight(12, randomGenerator.nextInt()); + Console.printPaddingRight(12, Random.nextInt()); }; Console.writeLine() @@ -45,11 +45,11 @@ public program() for(int i := 0; i < runCount; i += 1) { - int index := (randomGenerator.nextInt(0, IntNumber.MaxValue) / intGroupSize).toInt(); + int index := (Random.nextInt(0, IntNumber.MaxValue) / intGroupSize).toInt(); if(index < distGroupCount) { intCounts[index] := intCounts[index] + 1 }; - index := (randomGenerator.nextReal() * distGroupCount).toInt(); + index := (Random.nextReal() * distGroupCount).toInt(); if(index < distGroupCount) { realCounts[index] := realCounts[index] + 1 } }; diff --git a/examples60/console/regex/regex.l b/examples60/console/regex/regex.l index f5fadad58..67d01fb9a 100644 --- a/examples60/console/regex/regex.l +++ b/examples60/console/regex/regex.l @@ -21,7 +21,7 @@ public singleton Control proceed(line) { if (line == String.MinValue) - forward program.stop(); + forward Program.stop(); ^ _regEx.match(line) ? "matched" : "not matched"; } diff --git a/examples60/console/regex/regex.prj b/examples60/console/regex/regex.prj index ac809e0b5..74a748f3c 100644 --- a/examples60/console/regex/regex.prj +++ b/examples60/console/regex/regex.prj @@ -11,7 +11,7 @@ - extensions'ProgramLoop - regex'Control + extensions'ProgramLoop + regex'Control \ No newline at end of file diff --git a/examples60/console/replace/replace.l b/examples60/console/replace/replace.l index 9210a5c1a..7fb0ea443 100644 --- a/examples60/console/replace/replace.l +++ b/examples60/console/replace/replace.l @@ -3,7 +3,7 @@ import extensions'text; // --- Program --- -public program() +public Program() { var text := Console.print("Enter the text:").loadLineTo(new StringWriter()); var searchText := Console.print("Enter the phrase to be found:").readLine(); diff --git a/examples60/console/sum/sum.l b/examples60/console/sum/sum.l index 8ec69ce84..ee90b4ce7 100644 --- a/examples60/console/sum/sum.l +++ b/examples60/console/sum/sum.l @@ -29,7 +29,7 @@ EnteredNumber = forward number.new().loadFrom(Console); // --- Program --- -public program() +public Program() { Console .printLine(forward prompt) diff --git a/examples60/console/trans/control.l b/examples60/console/trans/control.l index 1f367ef77..cb7cf0dfa 100644 --- a/examples60/console/trans/control.l +++ b/examples60/console/trans/control.l @@ -1,11 +1,11 @@ import extensions; import extensions'text; -public program() +public Program() { while(true) { - var source := Console.writeLine("Enter the cyrillic text for transliteration or prese enter to exit:").loadLineTo(new StringWriter()); + var source := Console.writeLine("Enter the cyrillic text for transliteration or prese enter to exit:").loadLineTo(new StringWriter()).Value; if (0 == source.Length) { AbortException.raise() }; diff --git a/examples60/console/trans/translit.linux.prj b/examples60/console/trans/translit.linux.prj new file mode 100644 index 000000000..e2fe7c1c3 --- /dev/null +++ b/examples60/console/trans/translit.linux.prj @@ -0,0 +1,32 @@ + + + + translit + + + + + translit64 + + + + + translit64 + + + + + translit64 + + + + translit + + + + + translit.l + control.l + + + \ No newline at end of file diff --git a/examples60/console/words/words.l b/examples60/console/words/words.l index 4b3248be5..43bc0d3e5 100644 --- a/examples60/console/words/words.l +++ b/examples60/console/words/words.l @@ -34,7 +34,7 @@ class WordList // --- Program --- -public program() +public Program() { Console.writeLine("Enter the text(to stop press enter two times):"); diff --git a/examples60/db/sqlite/main.l b/examples60/db/sqlite/main.l index 3043671a7..f09a912a8 100644 --- a/examples60/db/sqlite/main.l +++ b/examples60/db/sqlite/main.l @@ -36,9 +36,9 @@ extension dbTestOp } } -// --- program --- +// --- Program --- -public program() +public Program() { auto dbFile := File.assign(DBFileName); diff --git a/examples60/files/textdb/textdb.l b/examples60/files/textdb/textdb.l index 8304716bf..d2a11c486 100644 --- a/examples60/files/textdb/textdb.l +++ b/examples60/files/textdb/textdb.l @@ -81,7 +81,7 @@ class Record // --- Program --- -public program() +public Program() { if (Program_arguments.Length == 1) { Console.write("Please provide the path to the file to view"); AbortException.raise() }; diff --git a/examples60/files/textfile/textfile.l b/examples60/files/textfile/textfile.l index 9abc9c10f..4cf3333fa 100644 --- a/examples60/files/textfile/textfile.l +++ b/examples60/files/textfile/textfile.l @@ -2,7 +2,7 @@ import system'io; import extensions; import extensions'routines; -public program() +public Program() { if (Program_arguments.Length == 1) { Console.writeLine("Please provide the path to the file to view"); AbortException.raise() }; diff --git a/examples60/gui/agenda/form.l b/examples60/gui/agenda/form.l index 4d0ee4da5..17ca128a2 100644 --- a/examples60/gui/agenda/form.l +++ b/examples60/gui/agenda/form.l @@ -194,7 +194,7 @@ public class MainWindow : SDIDialog // Exit BtmExit.onClick := (args) { - forward program.stop() + forward Program.stop() }; // About diff --git a/examples60/gui/c_a_g/calc_area_gui.l b/examples60/gui/c_a_g/calc_area_gui.l index 5a6f57f14..d042508e4 100644 --- a/examples60/gui/c_a_g/calc_area_gui.l +++ b/examples60/gui/c_a_g/calc_area_gui.l @@ -233,7 +233,7 @@ public class MainWindow : SDIDialog { self.onButtonClickSave() }; BtmSair.onClick := (args) - { forward program.stop() } + { forward Program.stop() } } private TipoDoCalculo(int index) diff --git a/examples60/gui/helloworld/helloworld.l b/examples60/gui/helloworld/helloworld.l index 6a13c919a..4c4be7318 100644 --- a/examples60/gui/helloworld/helloworld.l +++ b/examples60/gui/helloworld/helloworld.l @@ -10,6 +10,6 @@ public class MainWindow : XForm, using(MainWindow) private onExit(sender) { - forward program.stop() + forward Program.stop() } } diff --git a/examples60/gui/helloworld/helloworld.xs b/examples60/gui/helloworld/helloworld.xs index ddd4a8d5d..2a8c9a4a6 100644 --- a/examples60/gui/helloworld/helloworld.xs +++ b/examples60/gui/helloworld/helloworld.xs @@ -1,6 +1,6 @@ -
-