From 3902dc482e9ff592d5a8611b60a13ced4807fc0b Mon Sep 17 00:00:00 2001 From: Aleksey Rakov Date: Thu, 21 Mar 2024 10:56:44 +0100 Subject: [PATCH] Iteration20 (#639) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * preparing new version * [FIXED] calling a variadic method without arguments directly * [ADDED] an opcode LNEG * [ADDED] native negate operation for long integers * [FIXED] declaring a template based type with T is an array as a method result * [ADDED] sqlite module * [FIXED] string.toUpper() : returns a string with an incorrect length * [FIXED] Rosetta Code : Vigenère cipher * [FIXING]c_a_g sample * [FIXED] GC : perm generation is not included as roots for the partial collect * [FIXED] windproc * [ADDED] support for stdcall for win32 * IDE - refactoring notification routines * [FIXED] IDE notification refactoring * [FIXED] displaying stack-allocated structures * [Samples] c_a_g sample * [ADDED] c_a_g sample * [ADDED] agenda sample * [ADDED] graph sample * [FIXED] it has to be possible to convert int literal directly to v_int8 / v_int16 / v_int64, depending on the value size * [FIXED] warn if the source code is not compiled after the change before run / debug * [FIXED] warn if the source code is changed and not save before run / debug * [FIXED] the document is in read-only mode during the debugging * [FIXED] #636 - IDE bugs * [ADDED]x86 mt * [FIXED] x86 MTA : starting the new thread / program * [FIXED] x86 MTA : GC routine * [FIXED] byrefHandler : if it is not contain the explicit return, assign self to byref retVal * [FIXED] no need for typecasting operation after if-else operation with both branches containging returning operation * [FIXED] #634 - debugger step over some expressions * [FIXED] optimizing operation with int constants * [ADDED] xforms module * [ADDED] multi-profiles per a single project file; new option -l * [ADDED] project settings - select the project profile * [ADDED] #638 - Accessing a variable declared in the upper scope * fixing script samples --- CHANGELOG.md | 65 ++ LICENSE | 2 +- VERSION | 2 +- asm/aarch64/core60.asm | 8 + asm/amd64/core60.asm | 21 + asm/ppc64le/core60.asm | 7 + asm/x32/core60.asm | 63 +- asm/x32/corex60.asm | 33 +- bin/elc60.cfg | 3 + bin/scripts/xforms.es | 155 ---- bin/scripts/xforms60.es | 131 ++++ bin/templates/mt_win_console60.cfg | 1 + dat/api2html/api2html.bat | 2 + dat/og/bc_rules60.txt | 13 +- dat/og/bt_rules60.txt | 8 +- dat/sg/syntax60.txt | 28 +- doc/LICENSE | 2 +- doc/api/extensions.html | 31 +- doc/api/forms-summary.html | 39 +- doc/api/forms.html | 369 +++++++++- doc/api/index.html | 8 +- doc/api/sqlite-summary.html | 20 +- doc/api/sqlite.html | 619 ++++++---------- doc/api/system-collections.html | 54 ++ doc/api/system-culture-summary.html | 9 + doc/api/system-culture.html | 66 ++ doc/api/system-winforms-summary.html | 133 ++-- doc/api/system-winforms.html | 172 ++++- doc/readme.txt | 2 +- doc/todo.txt | 42 +- elenasrc3/common/config.h | 15 +- elenasrc3/common/tree.h | 1 - elenasrc3/elc/clicommon.h | 5 + elenasrc3/elc/cliconst.h | 7 +- elenasrc3/elc/codeimage.cpp | 5 +- elenasrc3/elc/compiler.cpp | 475 ++++++++---- elenasrc3/elc/compiler.h | 25 +- elenasrc3/elc/compilerlogic.cpp | 49 +- elenasrc3/elc/compilerlogic.h | 2 + elenasrc3/elc/compiling.cpp | 6 +- elenasrc3/elc/compiling.h | 3 +- elenasrc3/elc/derivation.cpp | 4 +- elenasrc3/elc/errors.h | 1 + elenasrc3/elc/linux/elc.cpp | 44 +- elenasrc3/elc/messages.h | 7 +- elenasrc3/elc/parser.h | 1 + elenasrc3/elc/project.cpp | 62 +- elenasrc3/elc/project.h | 15 +- elenasrc3/elc/windows/elc.cpp | 49 +- elenasrc3/elenart/rtcommon.h | 2 +- elenasrc3/elenasm/cfparser.cpp | 31 +- elenasrc3/elenasm/smcommon.h | 2 +- elenasrc3/elenavm/elenavmmachine.cpp | 11 +- elenasrc3/elenavm/elenavmmachine.h | 6 +- elenasrc3/elenavm/vmcommon.h | 4 +- elenasrc3/elenavm/windows/dllmain.cpp | 5 + elenasrc3/engine/bcwriter.cpp | 123 ++-- elenasrc3/engine/bcwriter.h | 2 +- elenasrc3/engine/buildtree.h | 6 +- elenasrc3/engine/bytecode.cpp | 6 +- elenasrc3/engine/bytecode.h | 3 +- elenasrc3/engine/elena.h | 1 + elenasrc3/engine/elenaconst.h | 1 + elenasrc3/engine/elenamachine.cpp | 2 + elenasrc3/engine/jitcompiler.cpp | 12 +- elenasrc3/engine/jitcompiler.h | 2 +- elenasrc3/engine/jitlinker.cpp | 4 +- elenasrc3/engine/jitlinker.h | 2 +- elenasrc3/engine/langcommon.h | 9 +- elenasrc3/engine/syntaxtree.cpp | 4 +- elenasrc3/engine/windows/winroutines.cpp | 3 + elenasrc3/engine/xmlprojectbase.cpp | 12 +- elenasrc3/engine/xmlprojectbase.h | 3 +- elenasrc3/gui/controller.cpp | 100 +-- elenasrc3/gui/controller.h | 16 +- elenasrc3/gui/document.cpp | 10 +- elenasrc3/gui/document.h | 19 +- elenasrc3/gui/guicommon.h | 25 +- elenasrc3/gui/guieditor.h | 19 +- elenasrc3/gui/view.cpp | 22 - elenasrc3/gui/view.h | 29 +- elenasrc3/gui/windows/wincommon.cpp | 88 +-- elenasrc3/gui/windows/wincommon.h | 122 ++-- elenasrc3/gui/windows/winsdi.cpp | 14 +- elenasrc3/gui/windows/winsplitter.cpp | 9 +- elenasrc3/gui/windows/winsplitter.h | 9 +- elenasrc3/gui/windows/wintabbar.cpp | 8 +- elenasrc3/gui/windows/wintabbar.h | 13 +- elenasrc3/gui/windows/wintextframe.cpp | 11 +- elenasrc3/gui/windows/wintextframe.h | 8 +- elenasrc3/gui/windows/wintextview.cpp | 18 +- elenasrc3/gui/windows/wintextview.h | 12 +- elenasrc3/gui/windows/wintreeview.cpp | 12 +- elenasrc3/gui/windows/wintreeview.h | 19 +- elenasrc3/ide/debugcontroller.cpp | 74 +- elenasrc3/ide/debugcontroller.h | 15 +- elenasrc3/ide/editframe.cpp | 34 +- elenasrc3/ide/editframe.h | 12 +- elenasrc3/ide/eng/messages.h | 7 +- elenasrc3/ide/idecommon.cpp | 88 +++ elenasrc3/ide/idecommon.h | 169 ++++- elenasrc3/ide/idecontroller.cpp | 546 ++++++++------ elenasrc3/ide/idecontroller.h | 104 ++- elenasrc3/ide/ideproject.cpp | 4 +- elenasrc3/ide/ideproject.h | 2 + elenasrc3/ide/ideversion.h | 2 +- elenasrc3/ide/ideview.cpp | 2 - elenasrc3/ide/ideview.h | 4 + elenasrc3/ide/ideworkspace.h | 20 - elenasrc3/ide/vs/elide.vcxproj | 1 - elenasrc3/ide/windows/Resource.h | 1 + elenasrc3/ide/windows/elide.rc | Bin 40116 -> 40560 bytes elenasrc3/ide/windows/factory.cpp | 88 ++- elenasrc3/ide/windows/factory.h | 9 +- elenasrc3/ide/windows/main.cpp | 15 +- elenasrc3/ide/windows/win32debugprocess.cpp | 25 +- elenasrc3/ide/windows/win32debugprocess.h | 7 +- elenasrc3/ide/windows/wincontextbrowser.cpp | 12 +- elenasrc3/ide/windows/wincontextbrowser.h | 12 +- elenasrc3/ide/windows/windialogs.cpp | 28 +- elenasrc3/ide/windows/windialogs.h | 3 +- elenasrc3/ide/windows/winide.cpp | 686 ++++++++++-------- elenasrc3/ide/windows/winide.h | 107 ++- elenasrc3/ide/windows/winidestatusbar.cpp | 20 +- elenasrc3/ide/windows/winidestatusbar.h | 4 +- elenasrc3/ide/windows/winmessagelog.cpp | 8 +- elenasrc3/ide/windows/winmessagelog.h | 16 +- elenasrc3/ide/windows/winoutput.cpp | 6 +- elenasrc3/ide/windows/winoutput.h | 8 +- elenasrc3/tools/asmc/asmc.cpp | 14 +- elenasrc3/tools/asmc/asmconst.h | 6 +- elenasrc3/tools/asmc/bcassembler.cpp | 20 +- elenasrc3/tools/asmc/bcassembler.h | 7 +- elenasrc3/tools/asmc/x86assembler.cpp | 18 +- elenasrc3/tools/elt/eltconst.h | 6 +- elenasrc3/tools/elt/windows/elt.cpp | 18 +- elenasrc3/tools/og/ogconst.h | 6 +- examples/gui/agenda/agenda.prj | 16 - examples/gui/agenda/form.l | 206 ------ examples/gui/graphs/graphs.l | 96 --- examples/gui/graphs/graphs.prj | 16 - examples60/console/sum/intsum.prj | 25 - examples60/console/sum/realsum.prj | 25 - examples60/console/sum/sum.prj | 47 ++ examples60/db/sqlite/main.l | 93 +++ examples60/db/sqlite/sqlite_test.prj | 15 + examples60/gui/agenda/form.l | 42 +- examples60/gui/c_a_g/anot_wind.l | 180 +++-- examples60/gui/c_a_g/c_area_gui.prj | 1 + examples60/gui/c_a_g/calc_area_gui.l | 376 +++++----- .../gui/c_a_g/formulas/Triangulos/bitmap1.bmp | Bin 158514 -> 210778 bytes .../gui/c_a_g/formulas/Triangulos/bitmap2.bmp | Bin 158514 -> 158514 bytes examples60/gui/graphs/graphs.l | 97 +++ examples60/gui/graphs/graphs.prj | 17 + examples60/gui/helloworld/helloworld.l | 18 + examples60/gui/helloworld/helloworld.xs | 4 + .../gui/helloworld/xforms_hellowindow.prj | 29 + install/aarch64/control | 2 +- install/amd64/control | 2 +- install/build_package_x64.bat | 27 + install/build_package_x86.bat | 106 +++ install/elena_inno.iss | 21 +- install/i386/control | 2 +- install/ppc64le/control | 2 +- rebuild_lib60.bat | 27 + src60/core/system.core_routines.esm | 10 +- src60/core/system.win_core_routines.esm | 51 +- src60/extensions/console.l | 35 + src60/extensions/convertors.l | 2 +- src60/extensions/extensions.prj | 3 + src60/extensions/scripting/interpreter.l | 2 +- src60/extensions/threading/threading.l | 20 + src60/forms/controls.l | 33 + src60/forms/forms.prj | 56 +- src60/forms/win32_controls.l | 118 +-- src60/forms/win_dialogs.l | 4 +- src60/forms/win_forms.l | 98 ++- src60/sqlite/common.l | 267 +++++++ src60/sqlite/data_table.l | 59 ++ src60/sqlite/reader.l | 80 ++ src60/sqlite/sqlite.prj | 28 + src60/system/collections/tuples.l | 91 ++- src60/system/convertors.l | 2 +- src60/system/culture/common.l | 16 +- src60/system/drawing/win_graphics.l | 2 +- src60/system/drawing/win_handles.l | 60 +- src60/system/io/win_console.l | 2 - src60/system/winforms/win_app.l | 29 + src60/system/winforms/win_common.l | 3 + src60/system/winforms/win_controls.l | 20 +- src60/system/winforms/win_dialogs.l | 108 +-- src60/system/winforms/win_windows.l | 20 +- src60/xforms/xforms.l | 12 + src60/xforms/xforms.prj | 26 + tests60/sandbox/sandbox.l | 56 +- tests60/system_tests/basic.l | 5 + 196 files changed, 5697 insertions(+), 3070 deletions(-) delete mode 100644 bin/scripts/xforms.es create mode 100644 bin/scripts/xforms60.es delete mode 100644 elenasrc3/ide/ideworkspace.h delete mode 100644 examples/gui/agenda/agenda.prj delete mode 100644 examples/gui/agenda/form.l delete mode 100644 examples/gui/graphs/graphs.l delete mode 100644 examples/gui/graphs/graphs.prj delete mode 100644 examples60/console/sum/intsum.prj delete mode 100644 examples60/console/sum/realsum.prj create mode 100644 examples60/console/sum/sum.prj create mode 100644 examples60/db/sqlite/main.l create mode 100644 examples60/db/sqlite/sqlite_test.prj create mode 100644 examples60/gui/graphs/graphs.l create mode 100644 examples60/gui/graphs/graphs.prj create mode 100644 examples60/gui/helloworld/helloworld.l create mode 100644 examples60/gui/helloworld/helloworld.xs create mode 100644 examples60/gui/helloworld/xforms_hellowindow.prj create mode 100644 src60/extensions/threading/threading.l create mode 100644 src60/sqlite/common.l create mode 100644 src60/sqlite/data_table.l create mode 100644 src60/sqlite/reader.l create mode 100644 src60/sqlite/sqlite.prj create mode 100644 src60/xforms/xforms.l create mode 100644 src60/xforms/xforms.prj diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e5a42ec6d..29bf9c8a2b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,68 @@ +## ELENA 6.0.8 +*21.03.2024* + +- ELENA + - [ADDED] an opcode LNEG + +- ELC + - [ADDED] native negate operation for long integers + - [ADDED] #588 - Operation with int constant + - [ADDED] multi-profiles per a single project file; new option -l + - [ADDED] #638 - Accessing a variable declared in the upper scope + - [FIXED] calling a variadic method without arguments directly + - [FIXED] declaring a template based type with T is an array as a method result + - [FIXED] GC : perm generation is not included as roots for the partial collect + - [FIXED] generating a proper debug info for local structure / structure self + - [FIXED] it has to be possible to convert int literal directly to v_int8 / v_int16 / v_int64, depending on the value size + - [FIXED] x86 MTA : starting the new thread / program + - [FIXED] x86 MTA : GC routine + - [FIXED] byrefHandler : if it is not contain the explicit return, assign self to byref retVal + - [FIXED] no need for typecasting operation after if-else operation with both branches containging returning operation + - [FIXED] optimizing operation with int constants + +- API + - [ADDED] sqlite module + - [FIXED] string.toUpper() : returns a string with an incorrect length + - [FIXED] windproc + - [ADDED] xforms + +- SAMPLES + - [ADDED] sqlite_test + - [FIXED] Rosetta Code : Interactive programming (repl), Vigenère cipher + - [ADDED] c_a_g sample + - [ADDED] agenda sample + - [ADDED] graph sample + +- Tools + - [ADDED] support for stdcall for win32 + +- IDE + - [ADDED] project settings - select the project profile + - [FIXED] #634 - IDE debugger: the debugger must hide trace line on wait + - [FIXED] #634 - debugger step over some expressions + - [FIXED] #636 - IDE bugs + - [FIXED] displaying stack-allocated structures + - [FIXED] warn if the source code is not compiled after the change before run / debug + - [FIXED] warn if the source code is changed and not save before run / debug + - [FIXED] the document is in read-only mode during the debugging + +## ELENA 6.0.7 +*11.02.2024* + +- ELENA + - [ADDED]meta command #load, #clear + - [ADDED]#563:Extended statement templates + - [FIXED]#508 - working on multi-value assigning + - [FIXED]#86 - primitive operations : int + long + - [FIXED]"this self" for an extension + - [ADDED]system : Int8Number, UShortNumber + - [ADDED]#629 - Read-only fields + - [FIXED]#613 - bytecode optimization + - [FIXED]#623 - Overriding property set accessor + - [FIXED]#601 - bytecode optimization + - [ADDED]evaluate an expression in compile-time if possible + - [ADDED]#562 - Nullable support + ## ELENA 6.0.6 *19.10.2023* diff --git a/LICENSE b/LICENSE index ca09288314..e3d67137a9 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2017 ELENA Language Project +Copyright (c) 2017-2024 ELENA Language Project Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/VERSION b/VERSION index 41bd15e2ea..a0c2cf5cd7 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -6.0.7 \ No newline at end of file +6.0.8 \ No newline at end of file diff --git a/asm/aarch64/core60.asm b/asm/aarch64/core60.asm index 6b2ab6bbc5..9c24094687 100644 --- a/asm/aarch64/core60.asm +++ b/asm/aarch64/core60.asm @@ -763,6 +763,14 @@ inline %1Eh end +// ; lneg +inline % 1Fh + + mov x17, 0 + sub x9, x17, x9 + +end + // ; coalesce inline % 20h diff --git a/asm/amd64/core60.asm b/asm/amd64/core60.asm index 02c1c0b236..8ea49150db 100644 --- a/asm/amd64/core60.asm +++ b/asm/amd64/core60.asm @@ -631,6 +631,13 @@ inline %1Eh end +// ; lneg +inline % 1Fh + + neg rdx + +end + // ; coalesce inline % 20h @@ -2909,6 +2916,20 @@ inline %7F1h end +// ; xstoresir :0, -1 +inline %9F1h + + mov r10, -1 + +end + +// ; xstoresir :1, -1 +inline %0AF1h + + mov r11, -1 + +end + // ; extopenin inline %0F2h diff --git a/asm/ppc64le/core60.asm b/asm/ppc64le/core60.asm index 6bff8320d2..5fd733f812 100644 --- a/asm/ppc64le/core60.asm +++ b/asm/ppc64le/core60.asm @@ -824,6 +824,13 @@ inline %1Eh end +// ; lneg +inline % 1Fh + + neg r14, r14 + +end + // ; coalesce inline % 20h diff --git a/asm/x32/core60.asm b/asm/x32/core60.asm index 74ad07e0fe..1553fae111 100644 --- a/asm/x32/core60.asm +++ b/asm/x32/core60.asm @@ -182,6 +182,13 @@ labYGCollect: push esi push ecx + // ; save perm roots + mov esi, [data : %CORE_GC_TABLE + gc_perm_start] + mov ecx, [data : %CORE_GC_TABLE + gc_perm_current] + sub ecx, esi + push esi + push ecx + // ; collect frames mov eax, [data : %CORE_SINGLE_CONTENT + tt_stack_frame] mov ecx, eax @@ -485,7 +492,7 @@ end // ; exclude inline % 10h - + push ebp mov [data : %CORE_SINGLE_CONTENT + tt_stack_frame], esp @@ -494,7 +501,7 @@ end // ; include inline % 11h - add esp, 4 + add esp, 4 end @@ -635,6 +642,16 @@ inline %1Eh end +// ; lneg +inline % 1Fh + + not edx + not eax + add eax, 1 + adc edx, 0 + +end + // ; coalesce inline % 20h @@ -2034,6 +2051,9 @@ inline %0CAh pop ebp add esp, 8 + pop eax + mov [data : %CORE_SINGLE_CONTENT + tt_stack_frame], eax + pop ebp end @@ -2045,6 +2065,10 @@ inline %1CAh pop ebp add esp, 8 + + pop eax + mov [data : %CORE_SINGLE_CONTENT + tt_stack_frame], eax + pop ebp end @@ -3210,13 +3234,22 @@ inline %6F1h end +// ; xstoresir :0, -1 +inline %9F1h + + mov esi, __ptr32_2 + +end + // ; extopenin inline %0F2h push ebp + mov eax, [data : %CORE_SINGLE_CONTENT + tt_stack_frame] + push eax + mov ebp, eax xor eax, eax - mov ebp, [data : %CORE_SINGLE_CONTENT + tt_stack_frame] push ebp push eax mov ebp, esp @@ -3239,9 +3272,11 @@ end inline %1F2h push ebp + mov eax, [data : %CORE_SINGLE_CONTENT + tt_stack_frame] + push eax + mov ebp, eax xor eax, eax - mov ebp, [data : %CORE_SINGLE_CONTENT + tt_stack_frame] push ebp push eax mov ebp, esp @@ -3255,9 +3290,11 @@ end inline %2F2h push ebp + mov eax, [data : %CORE_SINGLE_CONTENT + tt_stack_frame] + push eax + mov ebp, eax xor eax, eax - mov ebp, [data : %CORE_SINGLE_CONTENT + tt_stack_frame] push ebp push eax mov ebp, esp @@ -3272,9 +3309,11 @@ end inline %3F2h push ebp + mov eax, [data : %CORE_SINGLE_CONTENT + tt_stack_frame] + push eax + mov ebp, eax xor eax, eax - mov ebp, [data : %CORE_SINGLE_CONTENT + tt_stack_frame] push ebp push eax mov ebp, esp @@ -3291,9 +3330,11 @@ end inline %4F2h push ebp + mov eax, [data : %CORE_SINGLE_CONTENT + tt_stack_frame] + push eax + mov ebp, eax xor eax, eax - mov ebp, [data : %CORE_SINGLE_CONTENT + tt_stack_frame] push ebp push eax mov ebp, esp @@ -3311,9 +3352,11 @@ end inline %5F2h push ebp + mov eax, [data : %CORE_SINGLE_CONTENT + tt_stack_frame] + push eax + mov ebp, eax xor eax, eax - mov ebp, [data : %CORE_SINGLE_CONTENT + tt_stack_frame] push ebp push eax mov ebp, esp @@ -3332,9 +3375,11 @@ end inline %6F2h push ebp + mov eax, [data : %CORE_SINGLE_CONTENT + tt_stack_frame] + push eax + mov ebp, eax xor eax, eax - mov ebp, [data : %CORE_SINGLE_CONTENT + tt_stack_frame] push ebp push eax mov ebp, esp diff --git a/asm/x32/corex60.asm b/asm/x32/corex60.asm index d74037932b..faa8f5ca7d 100644 --- a/asm/x32/corex60.asm +++ b/asm/x32/corex60.asm @@ -105,7 +105,7 @@ labWait: // ; GCXT: free lock // ; could we use mov [esi], 0 instead? - lock xadd [esi], edx + lock xadd [edi], edx ret @@ -171,6 +171,7 @@ labConinue: mov eax, esi // ; get tls entry address mov esi, data : %CORE_THREAD_TABLE + tt_slots + xor ecx, ecx mov edi, [esi - 4] labNext: mov edx, [esi] @@ -234,6 +235,13 @@ labSkipWait: push esi push ecx + // ; save perm roots + mov esi, [data : %CORE_GC_TABLE + gc_perm_start] + mov ecx, [data : %CORE_GC_TABLE + gc_perm_current] + sub ecx, esi + push esi + push ecx + // ; == GCXT: save frames == mov eax, data : %CORE_THREAD_TABLE mov ebx, [eax] @@ -243,7 +251,7 @@ labYGNextThread: mov eax, data : %CORE_THREAD_TABLE + tt_slots // ; get tls entry address - mov esi, [eax+ebx*4] + mov esi, [eax+ebx*8] test esi, esi jz short labYGNextThreadSkip @@ -344,7 +352,6 @@ labWait: push ecx - // ; === GCXT: safe point === mov edx, [data : %CORE_GC_TABLE + gc_signal] // ; if it is a collecting thread, starts the GC @@ -533,7 +540,7 @@ labWait: // ; GCXT: free lock // ; could we use mov [esi], 0 instead? - lock xadd [esi], edx + lock xadd [edi], edx ret @@ -662,8 +669,9 @@ labSkipWait: call extern "$rt.SignalStopGCLA" mov ebx, edi - add esp, 4 + add esp, 8 + pop ebp pop esi ret @@ -769,7 +777,7 @@ end // ; exclude inline % 10h - + mov ecx, fs:[2Ch] mov eax, [data : %CORE_TLS_INDEX] mov edi, [ecx+eax*4] @@ -782,7 +790,7 @@ end // ; include inline % 11h - add esp, 4 + add esp, 4 mov ecx, fs:[2Ch] mov eax, [data : %CORE_TLS_INDEX] mov edi, [ecx+eax*4] @@ -793,14 +801,13 @@ end // ; tststck inline %17h - xor ecx, ecx - // ; COREX mov ecx, fs:[2Ch] mov eax, [data : %CORE_TLS_INDEX] mov edi, [ecx+eax*4] mov eax, [edi + tt_stack_root] + xor ecx, ecx cmp ebx, esp setl cl cmp ebx, eax @@ -839,8 +846,7 @@ inline %3CFh mov edi, data : %CORE_THREAD_TABLE + tt_slots mov [edi + edx * 8], eax - mov edi, [ecx+eax*4] - mov [edi + tt_stack_root], esp + mov [eax + tt_stack_root], esp end @@ -849,11 +855,6 @@ inline %4CFh finit - mov ecx, fs:[2Ch] - mov eax, [data : %CORE_TLS_INDEX] - mov edi, [ecx+eax*4] - mov [edi + tt_stack_root], esp - mov eax, esp call %PREPARE diff --git a/bin/elc60.cfg b/bin/elc60.cfg index 1faac1c354..5d6b72813d 100644 --- a/bin/elc60.cfg +++ b/bin/elc60.cfg @@ -14,6 +14,9 @@ KERNEL32 USER32 + GDI32 + WS2_32 + Comdlg32 diff --git a/bin/scripts/xforms.es b/bin/scripts/xforms.es deleted file mode 100644 index eb4d034dad..0000000000 --- a/bin/scripts/xforms.es +++ /dev/null @@ -1,155 +0,0 @@ -[[ - #grammar cf - - #define start ::= form; - #define start ::= $eof; - - #define form ::= -<= - root ( public_namespace ( - singleton ( - nameattr ( identifier = program ) - script_function ( - parameter ( nameattr ( identifier = owner ) ) - code ( - expression ( - variable_identifier = current - assign = 0 - expression ( - reference = forms'SDIDialog - message = new - ) - ) -=> - "<" "Form" property* form_closing_tag -<= - returning ( - expression ( - identifier = current - ) - ) - ) - ) - ) - ) ) -=>; - - #define property ::= -<= - expression ( - expression ( - identifier = current - - message ( - identifier = $current - ) - property_parameter = 0 - ) - assign = 0 - expression ( - new_reference = xforms'PropVariant - message = 0 - expression ( identifier = owner ) - expression ( -=> - $identifier "=" value -<= - ) - ) - ) -=>; - - #define member ::= -<= - code ( - expression ( - variable_identifier = current - assign = 0 - expression ( - reference = forms'Label - message = new - ) - ) -=> - "<" "Label" property* label_closing_tag -<= - expression ( - expression ( - prev_identifier = current - ) - message ( identifier = appendControl ) - expression ( - identifier = current - ) - ) - ) -=>; - - #define member ::= -<= - code ( - expression ( - variable_identifier = current - assign = 0 - expression ( - reference = forms'Button - message = new - ) - ) -=> - "<" "Button" property* button_closing_tag -<= - expression ( - expression ( - prev_identifier = current - ) - message ( identifier = appendControl ) - expression ( - identifier = current - ) - ) - ) -=>; - - #define member ::= -<= - code ( - expression ( - variable_identifier = current - assign = 0 - expression ( - reference = forms'Edit - message = new - ) - ) -=> - "<" "Edit" property* edit_closing_tag -<= - expression ( - expression ( - prev_identifier = current - ) - message ( identifier = appendControl ) - expression ( - identifier = current - ) - ) - ) -=>; - - #define form_closing_tag ::= - ">" member* "<" "/" "Form" ">"; - - #define label_closing_tag ::= - ">" "<" "/" "Label" ">"; - - #define button_closing_tag ::= - ">" "<" "/" "Button" ">"; - - #define edit_closing_tag ::= - ">" "<" "/" "Edit" ">"; - - #define value ::= <= literal = "$literal" =>; - -]] - \ No newline at end of file diff --git a/bin/scripts/xforms60.es b/bin/scripts/xforms60.es new file mode 100644 index 0000000000..5881cc4b75 --- /dev/null +++ b/bin/scripts/xforms60.es @@ -0,0 +1,131 @@ +[[ + #grammar cf + + #define start ::= form; + #define start ::= $eof; + + #define form ::= +<= + root ( public_namespace ( + public_singleton ( + nameattr ( identifier = loader ) + script_function ( + parameter ( nameattr ( identifier = owner ) ) + code ( + expression ( + assign_operation ( + new_variable ( identifier = current ) + message_operation ( + object ( reference = forms'SDIDialog ) + message ( identifier = new ) + ) + ) + ) +=> + "<" "Form" { val_property | property }* ">" member* form_closing_tag +<= + returning ( + expression ( + object ( identifier = current ) + ) + ) + ) + ) + ) + )) +=>; + + #define val_property ::= +<= + expression ( + property_operation ( + object ( identifier = current ) +=> + ":" prop_name "=" prop_value +<= + ) + ) +=>; + + #define property ::= +<= + expression ( + property_operation ( + object ( identifier = current ) +=> + prop_name "=" prop_str_value +<= + ) + ) +=>; + + #define member ::= +<= + code ( + expression ( + assign_operation ( + new_variable ( identifier = current ) + message_operation ( + object ( reference = forms'Label ) + message ( identifier = new ) + ) + ) + ) +=> + "<" "Label" { val_property | property }* ">" label_closing_tag +<= + expression ( + message_operation ( + object ( super_identifier = current ) + message ( identifier = appendControl ) + expression ( + object ( identifier = current ) + ) + ) + ) + ) +=>; + + #define form_closing_tag ::= + "<" "/" "Form" ">"; + + #define label_closing_tag ::= + "<" "/" "Label" ">"; + + #define prop_name ::= +<= + message ( +=> + identifier +<= + ) +=>; + + #define prop_value ::= +<= + expression ( + object ( + integer = +=> + int_quote +<= + ) + ) +=>; + + #define prop_str_value ::= +<= + expression ( + object ( + literal = +=> + quote +<= + ) + ) +=>; + + #define identifier ::= <= identifier = $identifier =>; + #define int_quote ::= <= $intliteral =>; + #define quote ::= <= "$literal" =>; +]] diff --git a/bin/templates/mt_win_console60.cfg b/bin/templates/mt_win_console60.cfg index aaafaabbda..f9b0c99c54 100644 --- a/bin/templates/mt_win_console60.cfg +++ b/bin/templates/mt_win_console60.cfg @@ -23,6 +23,7 @@ system'core_routines'mta_start + system'$private'entrySymbol $rootnamespace'program \ No newline at end of file diff --git a/dat/api2html/api2html.bat b/dat/api2html/api2html.bat index f8f75d8af4..4e83da357a 100644 --- a/dat/api2html/api2html.bat +++ b/dat/api2html/api2html.bat @@ -10,6 +10,8 @@ ..\..\bin\ldoc extensions'scripting ..\..\bin\ldoc extensions'dynamic ..\..\bin\ldoc cellular +..\..\bin\ldoc algorithms +..\..\bin\ldoc sqlite ..\..\bin\ldoc forms copy *.html ..\..\doc\api diff --git a/dat/og/bc_rules60.txt b/dat/og/bc_rules60.txt index c1d6637569..802d6496d3 100644 --- a/dat/og/bc_rules60.txt +++ b/dat/og/bc_rules60.txt @@ -1,12 +1,13 @@ -store sp:$1, peek sp:#1 => store sp, idle; -store fp:$1, peek fp:#1 => store fp, idle; -store fp:$1, load dp, save, peek fp:#1 => store fp, load dp, save, idle; cmp, jne =3, set :$1, jump =2, set :$2 => cmp, set :$1, store sp=0, set :$2, xpeekeq; cmp, jne =3, set dp:$1, jump =2, set dp:$2 => cmp, set dp:$1, store sp=0, set dp:$2, xpeekeq; cmp, jne =3, peek fp:$1, jump =2, peek fp:$2 => cmp, peek fp:$1, store sp=0, peek fp:$2, xpeekeq; -peek fp:$1, copy, peek fp:#1 => peek fp, copy, idle; -peek fp:$1, save, peek fp:#1 => peek fp, save, idle; 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; \ No newline at end of file +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; +store fp:$1, load dp, save, peek fp:#1 => store fp, load dp, save, idle; diff --git a/dat/og/bt_rules60.txt b/dat/og/bt_rules60.txt index 06a594bd08..f7a3fde8cc 100644 --- a/dat/og/bt_rules60.txt +++ b/dat/og/bt_rules60.txt @@ -1,11 +1,13 @@ breakpoint, breakpoint => 1; byrefmark => 2; int_literal, copying => 3; -local_address, saving_stack, int_literal, saving_stack = 1, intop, local_address, copying => 4; -local_address, saving_stack, int_literal, saving_stack, intop, create_struct, assigning, local_address, saving_stack, local, copying_to_acc => 11; +local_address, saving_stack, int_literal, saving_stack =1, intop => 4; +int_literal, saving_stack =0, intop => 5; +copying, addingint, local_address, copying => 15; +saving_index, addingint, local_address, copying => 15; +saving_index, local_address, copying => 11; local_address, saving_stack, int_literal, saving_stack, intbranchop => 8; local_address, saving_stack, local_address, conversion_op, local_address, copying => 9; -int_literal, saving_stack =0, intop => 5; create_struct =4, assigning, local_address, saving_stack =0, local, copying_to_acc => 6; intcondop, assigning, local, branchop => 7; realcondop, assigning, local, branchop => 7; diff --git a/dat/sg/syntax60.txt b/dat/sg/syntax60.txt index 5e80b53144..103a1df6d5 100644 --- a/dat/sg/syntax60.txt +++ b/dat/sg/syntax60.txt @@ -189,7 +189,8 @@ STATEMENT ::= ROOT_EXPRESSION | "#include" INCLUDE_STATEMENT | "#let" META_STATEMENT - | "#new" DICTIONARY; + | "#new" DICTIONARY + | "{" BLOCK; NEXT_STATEMENT ::= DECLARATION_END { @@ -308,12 +309,13 @@ ROOT_EXPRESSION ::= | T_EXPRESSION T_EXPRESSION_F ^ TEMPLATE_BLOCK | eps ^OBJECT } - | reference ^OBJECT L2_OP* L3_OP* L4_OP* L5_OP* L6_OP? L7_OP* L8_OP? L9_OP? + | { reference | global } ^OBJECT L2_OP* L3_OP* L4_OP* L5_OP* L6_OP? L7_OP* L8_OP? L9_OP? | { string | integer | hexinteger | long | real | constant | character | wide } ^OBJECT L_F | "*" SINGLE_EXPRESSION ^VALUE_OPERATION L2_OP* L3_OP* L4_OP* L5_OP* L6_OP? L7_OP* L8_OP? L9_OP? | "$rep" EXPRESSION ^LOOP_OPERATION | "$ext" EXPRESSION ^EXTERN_OPERATION | "$break" ^BREAK_OPERATION + | "$continue" ^CONTINUE_OPERATION | "$yield" EXPRESSION ^YIELD_OPERATION | BRACKET SUB_EXPRESSION { "=>" { SWITCH_OPTION+ SWITCH_LAST_OPTION? } ^SWITCH_OPERATION @@ -411,11 +413,12 @@ NESTED_ROOT_EXPRESSION ::= | T_EXPRESSION T_EXPRESSION_F ^ TEMPLATE_BLOCK | eps ^OBJECT } - | reference ^OBJECT L2_OP* L3_OP* L4_OP* L5_OP* L6_OP? L7_OP* L8_OP? L9_OP? + | { reference | global } ^OBJECT L2_OP* L3_OP* L4_OP* L5_OP* L6_OP? L7_OP* L8_OP? L9_OP? | { string | integer | hexinteger | long | real | constant | character | wide } ^OBJECT L_F | "$rep" EXPRESSION ^LOOP_OPERATION | "$ext" EXPRESSION ^EXTERN_OPERATION | "$break" ^BREAK_OPERATION + | "$continue" ^CONTINUE_OPERATION | "$yield" EXPRESSION ^YIELD_OPERATION; EXPRESSION ::= @@ -501,7 +504,7 @@ EXPRESSION ::= } | "{" NESTED_EXPRESSION ^NESTED L_F } - | reference ^OBJECT L2_OP* L3_OP* L4_OP* L5_OP* L6_OP? L7_OP* L8_OP? L9_OP? + | { reference | global } ^OBJECT L2_OP* L3_OP* L4_OP* L5_OP* L6_OP? L7_OP* L8_OP? L9_OP? | { string | integer | hexinteger | long | real | constant | character | wide } ^OBJECT L_F | "!" EXPRESSION ^NOT_OPERATION | "*" SINGLE_EXPRESSION ^VALUE_OPERATION L2_OP* L3_OP* L4_OP* L5_OP* L6_OP? L7_OP* L8_OP? L9_OP? @@ -604,7 +607,7 @@ SUB_EXPRESSION ::= | eps ^OBJECT } } - | reference ^OBJECT SUB_L_F ")" + | { reference | global } ^OBJECT SUB_L_F ")" | { string | integer | hexinteger | long | real | constant | character | wide } ^OBJECT SUB_L_F ")" | "!" EXPRESSION ^NOT_OPERATION ")" | "*" SINGLE_EXPRESSION ^VALUE_OPERATION SUB_L_F ")" @@ -686,7 +689,7 @@ L4_EXPRESSION ::= | "{" NESTED_EXPRESSION ^NESTED L2_OP* L3_OP* | eps ^OBJECT } - | reference ^OBJECT L2_OP* L3_OP* + | { reference | global } ^OBJECT L2_OP* L3_OP* | { string | integer | hexinteger | long | real | constant | character | wide } ^OBJECT L3_OP* | "$name" SINGLE_EXPRESSION ^NAME_OPERATION | "$reference" SINGLE_EXPRESSION ^REFER_OPERATION @@ -750,7 +753,7 @@ L6_EXPRESSION ::= | "{" NESTED_EXPRESSION ^NESTED L2_OP* L3_OP* L4_OP* L5_OP* | eps ^OBJECT } - | reference ^OBJECT L2_OP* L3_OP* L4_OP* L5_OP* + | { reference | global } ^OBJECT L2_OP* L3_OP* L4_OP* L5_OP* | { string | integer | hexinteger | long | real | constant | character | wide } ^OBJECT L3_OP* L4_OP* L5_OP* | "$name" SINGLE_EXPRESSION ^NAME_OPERATION | "$reference" SINGLE_EXPRESSION ^REFER_OPERATION @@ -918,8 +921,8 @@ L3_F ::= | eps } | "::" L3_SINGLE_EXPRESSION ^ MESSAGE_OPERATION L3_OP* L4_OP* L5_OP* L6_OP? L7_OP* L8_OP? L9_OP? - | STAR ^PROPERTY_OPERATION L4_EXPRESSION ^MUL_OPERATION - | DIV ^PROPERTY_OPERATION L4_EXPRESSION ^DIV_OPERATION + | STAR ^PROPERTY_OPERATION L4_EXPRESSION ^MUL_OPERATION L5_OP* L6_OP? L7_OP* L8_OP? L9_OP? + | DIV ^PROPERTY_OPERATION L4_EXPRESSION ^DIV_OPERATION L5_OP* L6_OP? L7_OP* L8_OP? L9_OP? | BAND ^PROPERTY_OPERATION L4_EXPRESSION ^BAND_OPERATION | BOR ^PROPERTY_OPERATION L4_EXPRESSION ^BOR_OPERATION | BXOR ^PROPERTY_OPERATION L4_EXPRESSION ^BXOR_OPERATION @@ -1121,8 +1124,9 @@ PARAMETER ::= DYNAMIC_DIMENSION ^ARRAY_TYPE identifier | TEMPLATE_BRACKETS identifier | "?" ^NULLABLE_TYPE identifier - | eps - }; + | eps + } + | reference identifier; SUB_VARIABLE ::= identifier+ { @@ -1134,7 +1138,7 @@ TEMPLATE_BRACKETS ::= "<" TEMPLATE_ARG { "," TEMPLATE_ARG }* ">"; TEMPLATE_ARG ::= - identifier { TEMPLATE_BRACKETS ^ TEMPLATE_TYPE }? + identifier { TEMPLATE_BRACKETS ^ TEMPLATE_TYPE | DYNAMIC_DIMENSION ^ARRAY_TYPE }? | reference | global; diff --git a/doc/LICENSE b/doc/LICENSE index bb73730fc3..b5940e8ee6 100644 --- a/doc/LICENSE +++ b/doc/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2006-2019: Aleksey Rakov and other contributors: +Copyright (c) 2006-2024: Aleksey Rakov and other contributors: https://github.com/ELENA-LANG/elena-lang/blob/master/doc/contributors diff --git a/doc/api/extensions.html b/doc/api/extensions.html index 11c61ed1cc..c47087cbce 100644 --- a/doc/api/extensions.html +++ b/doc/api/extensions.html @@ -1465,7 +1465,7 @@

Extension Summary

-assertTrue() +dispatch() @@ -1474,7 +1474,7 @@

Extension Summary

-assertFalse() +printPaddingRightChar(IntNumber width, CharValue ch, params Object[] list) @@ -1483,6 +1483,33 @@

Extension Summary

+printPaddingLeftChar(IntNumber width, CharValue ch, params Object[] list) + + + + + + + + +assertTrue() + + + + + + + + +assertFalse() + + + + + + + + randomize(IntNumber count) diff --git a/doc/api/forms-summary.html b/doc/api/forms-summary.html index de4151ef01..0e663a5b69 100644 --- a/doc/api/forms-summary.html +++ b/doc/api/forms-summary.html @@ -107,6 +107,15 @@

+ChildForm + + +
+public class ChildForm
+ + + + Edit @@ -114,7 +123,7 @@

public class Edit - + Frame @@ -123,7 +132,7 @@

public class Frame - + IControl @@ -132,7 +141,7 @@

abstract public class IControl - + Imagebox @@ -141,7 +150,7 @@

public class Imagebox - + ImageList @@ -150,7 +159,7 @@

public class ImageList - + Label @@ -159,7 +168,7 @@

public class Label - + messageDialog @@ -168,7 +177,7 @@

public singleton messageDialog - + OpenFileDialog @@ -177,7 +186,7 @@

public class OpenFileDialog - + Paintbox @@ -186,7 +195,7 @@

public class Paintbox - + Panel @@ -195,7 +204,7 @@

public class Panel - + RadioButton @@ -204,7 +213,7 @@

public class RadioButton - + RadioButtonGroup @@ -213,7 +222,7 @@

public class RadioButtonGroup - + SaveFileDialog @@ -222,7 +231,7 @@

public class SaveFileDialog - + SDIDialog @@ -231,7 +240,7 @@

public class SDIDialog - + SDIForm @@ -240,7 +249,7 @@

public class SDIForm - + StaticLabel diff --git a/doc/api/forms.html b/doc/api/forms.html index 375a20df41..25cd9a0f62 100644 --- a/doc/api/forms.html +++ b/doc/api/forms.html @@ -408,6 +408,48 @@

Property Summary

+ + + +get  IntNumber + +X() + + + + + +set   + +X(IntNumber n) + + + + + + +get  IntNumber + +Y() + + + + + +set   + +Y(IntNumber n) + + + + + + +get  Region + +Region() + + @@ -554,6 +596,14 @@

Field Summary

+EventHandler<system'Func1> + +onResize + + + + + Frame _frame @@ -597,7 +647,7 @@

Property Summary

set   -Caption(String s) +Caption(String caption) @@ -606,7 +656,25 @@

Property Summary

set   -Caption(WideString s) +Width(IntNumber v) + + + + + + +set   + +Height(IntNumber h) + + + + + + +set   + +Caption(WideString caption) @@ -774,6 +842,14 @@

Field Summary

_controls + + + +EventHandler<system'Func1> + +onResize + + @@ -819,12 +895,30 @@

Method Summary

+ + +close() + + + + + + IControl retrieve(Handle handle) + + + +internal   + +resize(WindowHandle hwnd, IntNumber width, IntNumber height) + + + @@ -1092,13 +1186,22 @@

Method Summary

+ + +close() + + + + + + IControl retrieve(Handle handle) - + internal   @@ -1107,7 +1210,7 @@

Method Summary

- + @@ -1238,6 +1341,14 @@

Field Summary

_controls + + + +EventHandler<system'Func1> + +onResize + + @@ -1276,6 +1387,15 @@

Method Summary

+close() + + + + + + + + appendControl(BaseControl control) @@ -1449,6 +1569,202 @@

Method Summary


+ + + +
+
+forms'
+

ChildForm

+
+
+
+
+
+
+public class ChildForm
+
+
+ + + + +
    +
  • +

    Constructor / Static Method Summary

    + + + + + + + + + +
    Modifier and TypeConstructor / Static Method
    + +ChildForm +new(parent) + +
    +
  • +
+ +
    +
  • +

    Method Summary

    + + + + + + + + + + + + + + + + + +
    Modifier and TypeMethod
    + +internal   +createHandle() + +
    + + +close() + +
    + + +run() + +
    +
  • +
+
+
@@ -1842,6 +2158,15 @@

Method Summary

abstract   +close() + + + + + + +abstract   + click() @@ -2979,6 +3304,14 @@

Field Summary

+EventHandler<system'Func1> + +onResize + + + + + Frame _frame @@ -3385,12 +3718,20 @@

Field Summary

+EventHandler<system'Func1> + +onResize + + + + + Frame _frame - + IntNumber @@ -3398,7 +3739,7 @@

Field Summary

_selected - + EventHandler<system'Func1> @@ -3776,6 +4117,14 @@

Field Summary

_controls + + + +EventHandler<system'Func1> + +onResize + + @@ -3946,6 +4295,14 @@

Field Summary

_controls + + + +EventHandler<system'Func1> + +onResize + + diff --git a/doc/api/index.html b/doc/api/index.html index b0c3b799f9..1af5b1e733 100644 --- a/doc/api/index.html +++ b/doc/api/index.html @@ -408,7 +408,7 @@

-extensions'threading(not yet migrated) +extensions'threading
@@ -450,7 +450,7 @@

-algorithms(not yet migrated) +algorithms
@@ -513,7 +513,7 @@

-sqlite(not yet migrated) +sqlite
@@ -534,7 +534,7 @@

-xforms(not yet migrated) +xforms
diff --git a/doc/api/sqlite-summary.html b/doc/api/sqlite-summary.html index 673a49b568..e8c97e3e31 100644 --- a/doc/api/sqlite-summary.html +++ b/doc/api/sqlite-summary.html @@ -2,7 +2,7 @@ -ELENA Standard Library 5.8: Module sqlite +ELENA Standard Library 6.0: Module sqlite @@ -19,7 +19,7 @@
-ELENA Standard Library
5.8 +ELENA Standard Library
6.0
@@ -48,7 +48,7 @@

-sealed Class DBCommand
+public class DBCommand

@@ -57,7 +57,7 @@

-sealed Class DBConnection
+public class DBConnection

@@ -66,7 +66,7 @@

-sealed Class DBEnumerator
+public class DBEnumerator

@@ -75,7 +75,7 @@

-Class DBException
+public class DBException @@ -84,7 +84,7 @@

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

-sealed Class DBRow
+public class DBRow @@ -102,7 +102,7 @@

-sealed Class DBTable
+public class DBTable @@ -120,7 +120,7 @@

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

DBCommand



-sealed Class DBCommand
+public class DBCommand
-
-
    -
  • - + +
    • Field Summary

      @@ -53,18 +60,18 @@

      Field Summary

      -DBConnection - + +DBConnection -theConnection +_connection -Handle - + +Handle -theCommandHandle +_commandHandle @@ -73,11 +80,11 @@

      Field Summary

      • -

        Constructor Summary

        +

        Constructor / Static Method Summary

        - + - - - -
        Modifier and TypeConstructorConstructor / Static Method
        @@ -88,25 +95,16 @@

        Constructor Summary

        - -protected  DBCommand -constructor() - -
      - +
      • Conversion Summary

        - + @@ -114,17 +112,7 @@

        Conversion Summary

        Handle - - - -
        TypeModifier and Type Conversion Method
        -cast() - -
        - -DBCommand -cast() - +cast()
        @@ -142,22 +130,13 @@

        Method Summary

        -private  Object - -prepare(String text) - - - - - - -Object +
        eval() - + BoolValue @@ -166,16 +145,16 @@

        Method Summary

        - + -Object + evalScalar() - + DBReader @@ -184,7 +163,7 @@

        Method Summary

        - + Enumerator @@ -193,16 +172,16 @@

        Method Summary

        - + -Object + at(IntNumber index) - + IntNumber @@ -211,19 +190,19 @@

        Method Summary

        - + -Array<system'String> +String[] sql_field_names() - + -Object + close() @@ -232,9 +211,6 @@

        Method Summary

      -
    • -
    -

@@ -250,13 +226,20 @@

DBConnection



-sealed Class DBConnection
+public class DBConnection
-
-
    -
  • - + +
    • Field Summary

      @@ -267,26 +250,26 @@

      Field Summary

      -IntNumber - + +Handle -theDBHandle +_DBHandle -String - + +String -thePath +_path -BoolValue - + +BoolValue -theOpen +_open @@ -295,11 +278,11 @@

      Field Summary

      • -

        Constructor Summary

        +

        Constructor / Static Method Summary

        - + - - - -
        Modifier and TypeConstructorConstructor / Static Method
        @@ -319,43 +302,24 @@

        Constructor Summary

        - -protected  DBConnection -constructor() - -
      - +
      • Conversion Summary

        - + - - - - +Handle
        TypeModifier and Type Conversion Method
        -IntNumber -cast() - -
        - -DBConnection -cast() - +cast()
        @@ -382,7 +346,7 @@

        Method Summary

        -Object + open() @@ -400,16 +364,16 @@

        Method Summary

        -Object + -doSql(Object query) +doSql(query) -Object + executeNonQuery(String sqlText) @@ -418,7 +382,7 @@

        Method Summary

        -Object + executeQuery(String sqlText) @@ -427,7 +391,7 @@

        Method Summary

        -Object + numberOfTable() @@ -436,7 +400,7 @@

        Method Summary

        -Object + tables() @@ -445,7 +409,7 @@

        Method Summary

        -Object + close() @@ -454,9 +418,6 @@

        Method Summary

      -
    • -
    -

@@ -468,9 +429,20 @@

Method Summary

DBEnumerator

+
+
+
+
+public class DBEnumerator
+
+
@@ -625,13 +587,20 @@

DBException



-Class DBException
+public class DBException
-
-
    -
  • - + +
    • Field Summary

      @@ -642,18 +611,18 @@

      Field Summary

      -String - + +String -theMessage +message -CallStack - + +CallStack -theCallstack +callStack @@ -662,87 +631,33 @@

      Field Summary

      • -

        Constructor Summary

        +

        Constructor / Static Method Summary

        - + - - - - - - - - - - -
        Modifier and TypeConstructorConstructor / Static Method
        -Object -raise() - -
        - DBException new()
        - -DBException -new(String message) - -
        -protected  DBException -constructor() - -
        -
      • -
      - -
        -
      • -

        Conversion Summary

        - - - - - - -
        TypeConversion Method
        - DBException -cast() +new(String message)
      - -
        -
      • -

        Method Summary

        - - - - - -
        Modifier and TypeMethod
        -
      • -
      -
    • -
    -

@@ -754,9 +669,20 @@

Method Summary

DBReader

+
+
+
+
+public class DBReader
+
+
-

@@ -954,13 +839,20 @@

DBRow



-sealed Class DBRow
+public class DBRow
-
-
    -
  • - + +
    • Field Summary

      @@ -971,18 +863,18 @@

      Field Summary

      -Array<system'Object> - + +Object[] -theRow +_row -DBTable - + +DBTable -theTable +_table @@ -991,39 +883,18 @@

      Field Summary

      • -

        Constructor Summary

        +

        Constructor / Static Method Summary

        - + +internal  DBRow - -
        Modifier and TypeConstructorConstructor / Static Method
        -protected  DBRow -constructor() - -
        -
      • -
      - -
        -
      • -

        Conversion Summary

        - - - - - - - - @@ -1042,7 +913,7 @@

        Method Summary

        + +
        TypeConversion Method
        - -DBRow -cast() +newTableRow(Object[] row, DBTable table)
        -Object at(IntNumber n) @@ -1051,7 +922,7 @@

        Method Summary

        -Object at(String fieldName) @@ -1060,9 +931,6 @@

        Method Summary

      -
    • -
    -

@@ -1078,13 +946,20 @@

DBTable



-sealed Class DBTable
+public class DBTable
-
-

@@ -1227,7 +1078,7 @@

Method Summary

-ELENA Standard Library
5.8 +ELENA Standard Library
6.0
diff --git a/doc/api/system-collections.html b/doc/api/system-collections.html index a1b1f91cc4..2decb760dd 100644 --- a/doc/api/system-collections.html +++ b/doc/api/system-collections.html @@ -2583,6 +2583,15 @@

Method Summary

+ + + +Indexer + +indexer() + + + @@ -2719,6 +2728,15 @@

Method Summary

+ + + +Indexer + +indexer() + + + @@ -2843,6 +2861,15 @@

Method Summary

+ + + +Indexer + +indexer() + + + @@ -2975,6 +3002,15 @@

Method Summary

+ + + +Indexer + +indexer() + + + @@ -3115,6 +3151,15 @@

Method Summary

+ + + +Indexer + +indexer() + + + @@ -3263,6 +3308,15 @@

Method Summary

+ + + +Indexer + +indexer() + + + diff --git a/doc/api/system-culture-summary.html b/doc/api/system-culture-summary.html index 91fd8c0021..145dfc2622 100644 --- a/doc/api/system-culture-summary.html +++ b/doc/api/system-culture-summary.html @@ -101,6 +101,15 @@

A UTF-8 literal value + + +WideString + + +
+public class WideString
+ + diff --git a/doc/api/system-culture.html b/doc/api/system-culture.html index a80c820351..cc8e79fb1a 100644 --- a/doc/api/system-culture.html +++ b/doc/api/system-culture.html @@ -324,6 +324,72 @@

Extension Summary


+ + + +
+
+system'
+

WideString

+
+
+
+
+
+
+public class WideString
+
+
+ + +
+
- + HInstance @@ -60,7 +69,7 @@

public class HInstance - + messageBox @@ -69,7 +78,7 @@

public singleton messageBox - + MSG @@ -78,7 +87,7 @@

public class MSG - + OpenFileDialog @@ -87,7 +96,7 @@

public class OpenFileDialog - + PAINTSTRUCT @@ -96,7 +105,7 @@

public class PAINTSTRUCT - + SaveFileDialog @@ -105,7 +114,7 @@

public class SaveFileDialog - + SDIApplication @@ -114,7 +123,7 @@

public class SDIApplication - + SDIWindowCallback @@ -123,7 +132,7 @@

public class SDIWindowCallback - + WindowCallback @@ -132,7 +141,7 @@

public class WindowCallback - + WindowHandle @@ -141,7 +150,7 @@

public class WindowHandle - + WinFormsException @@ -150,7 +159,7 @@

public class WinFormsException - + WNDCLASS @@ -307,6 +316,15 @@

+CW_USEDEFAULT + + +
+CW_USEDEFAULT
+ + + + DS_CENTER @@ -314,7 +332,7 @@

DS_CENTER - + EditClass @@ -323,7 +341,7 @@

EditClass - + EN_CHANGE @@ -332,7 +350,7 @@

EN_CHANGE - + EX_SDI_OVERLAPPEDWINDOW @@ -341,7 +359,7 @@

EX_SDI_OVERLAPPEDWINDOW - + GWL_USERDATA @@ -350,7 +368,7 @@

GWL_USERDATA - + HTCLIENT @@ -359,7 +377,7 @@

HTCLIENT - + IDC_ARROW @@ -368,7 +386,7 @@

IDC_ARROW - + IDNO @@ -377,7 +395,7 @@

IDNO - + IDOK @@ -386,7 +404,7 @@

IDOK - + IDRETRY @@ -395,7 +413,7 @@

IDRETRY - + IDTRYAGAIN @@ -404,7 +422,7 @@

IDTRYAGAIN - + IDYES @@ -413,7 +431,7 @@

IDYES - + MB_ABORTRETRYIGNORE @@ -422,7 +440,7 @@

MB_ABORTRETRYIGNORE - + MB_CANCELTRYCONTINUE @@ -431,7 +449,7 @@

MB_CANCELTRYCONTINUE - + MB_HELP @@ -440,7 +458,7 @@

MB_HELP - + MB_ICONASTERISK @@ -449,7 +467,7 @@

MB_ICONASTERISK - + MB_ICONERROR @@ -458,7 +476,7 @@

MB_ICONERROR - + MB_ICONEXCLAMATION @@ -467,7 +485,7 @@

MB_ICONEXCLAMATION - + MB_ICONHAND @@ -476,7 +494,7 @@

MB_ICONHAND - + MB_ICONINFORMATION @@ -485,7 +503,7 @@

MB_ICONINFORMATION - + MB_ICONQUESTION @@ -494,7 +512,7 @@

MB_ICONQUESTION - + MB_ICONSTOP @@ -503,7 +521,7 @@

MB_ICONSTOP - + MB_ICONWARNING @@ -512,7 +530,7 @@

MB_ICONWARNING - + MB_OK @@ -521,7 +539,7 @@

MB_OK - + MB_OKCANCEL @@ -530,7 +548,7 @@

MB_OKCANCEL - + MB_RETRYCANCEL @@ -539,7 +557,7 @@

MB_RETRYCANCEL - + MB_YESNO @@ -548,7 +566,7 @@

MB_YESNO - + MB_YESNOCANCEL @@ -557,7 +575,7 @@

MB_YESNOCANCEL - + MF_POPUP @@ -566,7 +584,7 @@

MF_POPUP - + MF_STRING @@ -575,7 +593,7 @@

MF_STRING - + OFN_EXPLORER @@ -584,7 +602,7 @@

OFN_EXPLORER - + OFN_HIDEREADONLY @@ -593,7 +611,7 @@

OFN_HIDEREADONLY - + OFN_LONGNAMES @@ -602,7 +620,7 @@

OFN_LONGNAMES - + OFN_PATHMUSTEXIST @@ -611,7 +629,7 @@

OFN_PATHMUSTEXIST - + PaintboxClass @@ -620,7 +638,7 @@

PaintboxClass - + PanelClass @@ -629,7 +647,7 @@

PanelClass - + program @@ -638,7 +656,7 @@

program - + SDIWindowClass @@ -647,7 +665,7 @@

SDIWindowClass - + SS_SIMPLE @@ -656,7 +674,7 @@

SS_SIMPLE - + StaticClass @@ -665,7 +683,7 @@

StaticClass - + SWP_NOMOVE @@ -674,7 +692,7 @@

SWP_NOMOVE - + SWP_NOSIZE @@ -683,6 +701,15 @@

SWP_NOSIZE + + +WM_CLOSE + + +
+WM_CLOSE
+ + WM_DESTROY diff --git a/doc/api/system-winforms.html b/doc/api/system-winforms.html index 7feadb3c21..a3261449dc 100644 --- a/doc/api/system-winforms.html +++ b/doc/api/system-winforms.html @@ -23,6 +23,40 @@ + + + +
+
+system'winforms'
+

ChildWindowCallback

+
+
+
+
+
+
+public class ChildWindowCallback
+
+
+ +
+
@@ -474,7 +508,7 @@

Field Summary

-ShortNumber[] +WideString[] _filters @@ -482,27 +516,11 @@

Field Summary

-ShortNumber[] - -_fileName - - - - - IntNumber _filterIndex - - - -IntNumber - -_maxFile - - @@ -536,7 +554,7 @@

Constructor / Static Method Summary

OpenFileDialog -constructor(WindowHandle parent, WideString[] filters, IntNumber filterIndex, IntNumber maxFile, WideString caption) +constructor(WindowHandle parent, WideString[] filters, IntNumber filterIndex, WideString caption) @@ -763,7 +781,7 @@

Method Summary

-begin(WindowHandle handle) +begin(WindowHandle hwnd) @@ -772,7 +790,7 @@

Method Summary

-end(WindowHandle handle) +end(WindowHandle hwnd) @@ -833,7 +851,7 @@

Field Summary

-ShortNumber[] +WideString[]
_filters @@ -841,27 +859,11 @@

Field Summary

-ShortNumber[] - -_fileName - - - - - IntNumber _filterIndex - - - -IntNumber - -_maxFile - - @@ -895,7 +897,7 @@

Constructor / Static Method Summary

SaveFileDialog -constructor(WindowHandle parent, WideString[] filters, IntNumber filterIndex, IntNumber maxFile, WideString caption) +constructor(WindowHandle parent, WideString[] filters, IntNumber filterIndex, WideString caption) @@ -1015,7 +1017,7 @@

Method Summary

-error(String caption, Exception e) +run(window) @@ -1024,6 +1026,15 @@

Method Summary

+error(String caption, Exception e) + + + + + + + + stop() @@ -1186,6 +1197,15 @@

Method Summary

+ + + + + +onWMClose(Handle hwnd) + + + @@ -2189,6 +2209,43 @@

Symbol Summary


+ + + +
+
+system'winforms'
+

CW_USEDEFAULT

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

    Symbol Summary

    + + + + + + + +
    Modifier and TypeName
    + +public  IntNumber +CW_USEDEFAULT +
    +
  • +
+
+
+
@@ -3743,6 +3800,43 @@

Symbol Summary


+ + + +
+
+system'winforms'
+

WM_CLOSE

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

    Symbol Summary

    + + + + + + + +
    Modifier and TypeName
    + +public  IntNumber +WM_CLOSE +
    +
  • +
+
+
+
diff --git a/doc/readme.txt b/doc/readme.txt index a19fad1113..461412c61a 100644 --- a/doc/readme.txt +++ b/doc/readme.txt @@ -1,5 +1,5 @@ ELENA Language Project V. 6.0 - (C)2005-2023 By Alex Rakov + (C)2005-2024 By Alex Rakov The project includes ELENA documentation, standard library source code, samples, command-line compiler, IDE. diff --git a/doc/todo.txt b/doc/todo.txt index 5973553f73..05c2f5febb 100644 --- a/doc/todo.txt +++ b/doc/todo.txt @@ -4,39 +4,39 @@ In development: [development] ### EPIC: elena 6.0 - redux ### - === Iteration 19 === - -------------------------------------- - * build all platforms - === Iteration 20 === + === Iteration 21 === -------------------------------------- - dev: async programming (instant messagange sample (chat) ), #608 - op:github actions : x86 - opt: pi - under 8 sec, #601,#602 - maint:#620, tools:backlog,#616, system module warnings, #622 - exp:snake game : text / gui version, using expression trees in real-life apps (see c#) - ide:backlog (#617), vm debugger, debugger watch - struct - tools: - prom: - port:db samples, gui samples, xforms, x86 mt, x86-64 vm,elenavm / elt for linux + dev: #637, windows executable - support manifest + op: + opt:pi under 7 sec, #602 + maint:#620,#622,#618 + exp: + ide:vm debugger,backlog (#617) + tools:work with elt in ide + prom:#635,elena in nutshell every 1 week + port:win64 gui,helloworld gui sample (button) -------------------------------------- - === Iteration 21 === -------------------------------------- - dev: - op: - opt: + + === Iteration 22 === + -------------------------------------- + dev: async programming (instant messagange sample (chat) ), #608 + op:github actions : x86 + opt:pi under 6 sec, #601 maint: exp: ide: tools: prom: - port: - -------------------------------------- + port:x86-64 vm === Iteration 22 === -------------------------------------- - dev: + dev: redesign switch statement : it should be possible to use as an expression as well + (so we cannot use => anymore : e.g. console.printLine(x => 1 { "first" } 2 { "second" } 3 { "third" }) ) + console.printLine(x $sel 1 => "first", 2 => "second", 3 => "third"); op: opt: maint: @@ -44,4 +44,4 @@ In development: ide: tools: prom: - port: + port:elenavm / elt for linux diff --git a/elenasrc3/common/config.h b/elenasrc3/common/config.h index ea15d8fd22..fb7f29947b 100644 --- a/elenasrc3/common/config.h +++ b/elenasrc3/common/config.h @@ -2,7 +2,7 @@ // E L E N A P r o j e c t: ELENA Common Library // // This file contains Config File class header -// (C)2021-2022, by Aleksey Rakov +// (C)2021-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #ifndef CONFIG_H @@ -112,6 +112,19 @@ namespace elena_lang return Node(); } + template Node selectNode(Node& node, ustr_t xpath, ArgT arg, bool(*filter)(ArgT arg, Node& node)) + { + XmlNodeList list(XmlNode::Default()); + _tree.selectNodes(node.xmlNode, xpath, list); + for (auto it = list.start(); !it.eof(); ++it) { + Node node(*it); + if (filter(arg, node)) + return node; + } + + return Node(); + } + void appendSetting(ustr_t xpath, ustr_t value); void create(); diff --git a/elenasrc3/common/tree.h b/elenasrc3/common/tree.h index 02f7422ffc..a7b55e3254 100644 --- a/elenasrc3/common/tree.h +++ b/elenasrc3/common/tree.h @@ -385,7 +385,6 @@ namespace elena_lang else return Node(); } - Node findChild(Key key) const { Node current = firstChild(); diff --git a/elenasrc3/elc/clicommon.h b/elenasrc3/elc/clicommon.h index f98b172f65..ccfcf78d02 100644 --- a/elenasrc3/elc/clicommon.h +++ b/elenasrc3/elc/clicommon.h @@ -600,6 +600,11 @@ class ErrorProcessor : public ErrorProcessorBase _presenter->print(_presenter->getMessage(code), arg); } + void info(int code, ustr_t arg, ustr_t arg2) override + { + _presenter->print(_presenter->getMessage(code), arg, arg2); + } + void raiseError(int code, ustr_t arg) override { _presenter->print(_presenter->getMessage(code), arg); diff --git a/elenasrc3/elc/cliconst.h b/elenasrc3/elc/cliconst.h index 24f1f9d848..f7881c7bac 100644 --- a/elenasrc3/elc/cliconst.h +++ b/elenasrc3/elc/cliconst.h @@ -13,7 +13,7 @@ namespace elena_lang { - #define ELC_REVISION_NUMBER 0x0235 + #define ELC_REVISION_NUMBER 0x0244 #if defined _M_IX86 || _M_X64 @@ -30,6 +30,7 @@ namespace elena_lang // --- Information messages --- constexpr auto ELC_GREETING = "ELENA Command-line compiler %d.%d.%d (C)2005-2024 by Aleksey Rakov\n"; constexpr auto ELC_STARTING = "Project: %s, Platform: %s, Target type: %s"; + constexpr auto ELC_PROFILE_INFO = "Project profile: %s"; constexpr auto ELC_CLEANING = "Cleaning up"; constexpr auto ELC_LINKING = "Linking..\n"; @@ -43,7 +44,9 @@ namespace elena_lang constexpr auto ELC_SAVING_MODULE = "\nsaving %s\n"; - constexpr auto ELC_HELP_INFO = "elena-cli {-key} {source-file+ | project-file}\nkeys: m - turning on address mapping output\n r - clean the compilation output\n t{template name} - loading the project template\n p - set the base path\n wX- turns off warnings with level X=1,2,4\n xp[-] - turning on/off a generation the parameter meta info\n xb[-] - turning on/off a conditional boxing"; + constexpr auto ELC_PROFILE_WARNING = "\nWARNING - Please select one of available profiles:%s\n"; + + constexpr auto ELC_HELP_INFO = "elena-cli {-key} {source-file+ | project-file}\nkeys:\n -f{fwd=reference} - add a forward\n -l{profile name} - selecct a profile\n -m - turning on address mapping output\n -o{0 | 1 | 2} - set the optimization level\n -p - set the base path\n -r - clean the compilation output\n -s{ stackReserv:n } - set the linker option - stack reserved\n -t{ template name } - load the project template\n -v - turn on a verbose output mode\n - w{ 0 | 1 | 2 | 3 } - set the minimal warnings level to X = { 0 | 1 | 2 | 3 }\n -xb[-] - turn on / off a conditional boxing\n -xe[-] - turn on / off a compile-time expression evaluation\n -xp[-] - turn on / off generation of the parameter meta info"; constexpr auto SYNTAX_FILE = "syntax60.dat"; constexpr auto BC_RULES_FILE = "bc_rules60.dat"; diff --git a/elenasrc3/elc/codeimage.cpp b/elenasrc3/elc/codeimage.cpp index 3091939b7b..fd8f144c40 100644 --- a/elenasrc3/elc/codeimage.cpp +++ b/elenasrc3/elc/codeimage.cpp @@ -50,12 +50,15 @@ TargetImage :: TargetImage(PlatformType systemTarget, ForwardResolverBase* resol // add predefined values prepareImage(imageInfo.ns); - linker.prepare(compiler); + linker.setCompiler(compiler); if (imageInfo.withTLS) { + // NOTE : TLS variable must be declared first, before loading system routines _tlsVariable = linker.resolveTLSSection(compiler); } + linker.prepare(); + // resolve the debug entry _debugEntryPoint = INVALID_POS; diff --git a/elenasrc3/elc/compiler.cpp b/elenasrc3/elc/compiler.cpp index 095d660927..7d9e80efd6 100644 --- a/elenasrc3/elc/compiler.cpp +++ b/elenasrc3/elc/compiler.cpp @@ -41,7 +41,7 @@ MethodHint operator | (const ref_t& l, const MethodHint& r) { return (MethodHint)(l | (unsigned int)r); } - +// //inline void testNodes(SyntaxNode node) //{ // SyntaxNode current = node.firstChild(); @@ -162,6 +162,36 @@ inline bool areConstants(ArgumentsInfo& args) return true; } +inline ref_t mapLongConstant(Compiler::Scope& scope, long long integer) +{ + String s; + + // convert back to string as a decimal integer + s.appendLong(integer, 16); + + return scope.moduleScope->module->mapConstant(s.str()); +} + +inline ref_t mapUIntConstant(Compiler::Scope& scope, int integer) +{ + String s; + + // convert back to string as a decimal integer + s.appendUInt(integer, 16); + + return scope.moduleScope->module->mapConstant(s.str()); +} + +inline ref_t mapFloat64Const(ModuleBase* module, double val) +{ + String s; + + // convert back to string as a decimal integer + s.appendDouble(val); + + return module->mapConstant(s.str()); +} + // --- Interpreter --- Interpreter :: Interpreter(ModuleScopeBase* scope, CompilerLogic* logic) @@ -508,6 +538,46 @@ bool Interpreter :: evalIntOp(ref_t operator_id, ArgumentsInfo& args, ObjectInfo return false; } +bool Interpreter :: evalRealOp(ref_t operator_id, ArgumentsInfo& args, ObjectInfo& retVal) +{ + ObjectInfo loperand = args[0]; + ObjectInfo roperand = args[1]; + + double lvalue = 0; + double rvalue = 0; + + if (loperand.kind == ObjectKind::Float64Literal && roperand.kind == ObjectKind::Float64Literal) { + ustr_t valueStr = _scope->module->resolveConstant(loperand.reference); + lvalue = StrConvertor::toDouble(valueStr); + + valueStr = _scope->module->resolveConstant(roperand.reference); + rvalue = StrConvertor::toDouble(valueStr); + } + else return false; + + double result = 0; + switch (operator_id) { + case ADD_OPERATOR_ID: + result = lvalue + rvalue; + break; + case SUB_OPERATOR_ID: + result = lvalue - rvalue; + break; + case MUL_OPERATOR_ID: + result = lvalue * rvalue; + break; + case DIV_OPERATOR_ID: + result = lvalue / rvalue; + break; + default: + return false; + } + + retVal = { ObjectKind::Float64Literal, { V_FLOAT64 }, ::mapFloat64Const(_scope->module, result) }; + + return true; +} + bool Interpreter :: evalDeclOp(ref_t operator_id, ArgumentsInfo& args, ObjectInfo& retVal) { ObjectInfo loperand = args[0]; @@ -557,6 +627,8 @@ bool Interpreter :: eval(BuildKey key, ref_t operator_id, ArgumentsInfo& argumen return evalDeclOp(operator_id, arguments, retVal); case BuildKey::IntOp: return evalIntOp(operator_id, arguments, retVal); + case BuildKey::RealOp: + return evalRealOp(operator_id, arguments, retVal); default: return false; } @@ -1220,6 +1292,7 @@ Compiler::CodeScope :: CodeScope(MethodScope* parent) { allocated1 = reserved1 = 0; allocated2 = reserved2 = 0; + withRetStatement = false; } Compiler::CodeScope :: CodeScope(CodeScope* parent) @@ -1227,6 +1300,7 @@ Compiler::CodeScope :: CodeScope(CodeScope* parent) { reserved1 = allocated1 = parent->allocated1; reserved2 = allocated2 = parent->allocated2; + withRetStatement = false; } ObjectInfo Compiler::CodeScope :: mapLocal(ustr_t identifier) @@ -1243,6 +1317,10 @@ ObjectInfo Compiler::CodeScope :: mapLocal(ustr_t identifier) ObjectInfo Compiler::CodeScope :: mapIdentifier(ustr_t identifier, bool referenceOne, ExpressionAttribute attr) { + if (EAttrs::testAndExclude(attr, EAttr::Superior)) { + return parent->mapIdentifier(identifier, referenceOne, attr); + } + ObjectInfo info = mapLocal(identifier); if (info.kind != ObjectKind::Unknown || EAttrs::test(attr, ExpressionAttribute::Local)) { return info; @@ -1280,6 +1358,8 @@ void Compiler::CodeScope :: syncStack(CodeScope* parentScope) if (parentScope->reserved2 < reserved2) parentScope->reserved2 = reserved2; + + parentScope->withRetStatement |= withRetStatement; } void Compiler::CodeScope :: markAsAssigned(ObjectInfo object) @@ -2157,6 +2237,13 @@ void Compiler :: generateMethodAttributes(ClassScope& scope, SyntaxNode node, } else { if (methodInfo.outputRef && methodInfo.outputRef != outputRef) { + if (_verbose) { + ustr_t expectedReference = scope.module->resolveReference(methodInfo.outputRef); + ustr_t actualReference = scope.module->resolveReference(outputRef); + + _errorProcessor->info(infoExptectedType, expectedReference, actualReference); + } + scope.raiseError(errTypeAlreadyDeclared, node); } methodInfo.outputRef = outputRef; @@ -6738,9 +6825,75 @@ inline bool isPrimitiveArray(ref_t typeRef) } } +inline bool DoesOperationSupportConvertableIntLiteral(int operatorId) +{ + switch (operatorId) { + case ADD_OPERATOR_ID: + case SUB_OPERATOR_ID: + case LESS_OPERATOR_ID: + case EQUAL_OPERATOR_ID: + case NOTEQUAL_OPERATOR_ID: + case ELSE_OPERATOR_ID: + case MUL_OPERATOR_ID: + case DIV_OPERATOR_ID: + case NOTLESS_OPERATOR_ID: + case GREATER_OPERATOR_ID: + case NOTGREATER_OPERATOR_ID: + case BAND_OPERATOR_ID: + case BOR_OPERATOR_ID: + case BXOR_OPERATOR_ID: + case BNOT_OPERATOR_ID: + case AND_OPERATOR_ID: + case OR_OPERATOR_ID: + case XOR_OPERATOR_ID: + 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; + } +} + +void Compiler :: convertIntLiteralForOperation(ExprScope& scope, SyntaxNode node, int operatorId, ArgumentsInfo& messageArguments) +{ + if (!DoesOperationSupportConvertableIntLiteral(operatorId)) + return; + + ObjectInfo literal = {}; + ref_t loperandRef = messageArguments[0].typeInfo.typeRef; + switch (loperandRef) { + case V_INT16ARRAY: + literal = convertIntLiteral(scope, node, messageArguments[1], V_INT16, true); + break; + case V_INT8ARRAY: + literal = convertIntLiteral(scope, node, messageArguments[1], V_INT8, true); + break; + case V_BINARYARRAY: + literal = convertIntLiteral(scope, node, messageArguments[1], _logic->retrievePrimitiveType(*scope.moduleScope, messageArguments[0].typeInfo.elementRef), true); + break; + default: + { + literal = convertIntLiteral(scope, node, messageArguments[1], _logic->retrievePrimitiveType(*scope.moduleScope, loperandRef), true); + + break; + } + } + + if (literal.kind != ObjectKind::Unknown) + messageArguments[1] = literal; +} + ObjectInfo Compiler :: compileOperation(BuildTreeWriter& writer, ExprScope& scope, SyntaxNode node, ArgumentsInfo& messageArguments, int operatorId, ref_t expectedRef, ArgumentsInfo* updatedOuterArgs) { + if (messageArguments.count() > 1 && messageArguments[1].kind == ObjectKind::IntLiteral) { + // try to typecast int literal if possible + convertIntLiteralForOperation(scope, node, operatorId, messageArguments); + } + WriterContext context = { &writer, &scope, node }; ObjectInfo loperand = messageArguments[0]; @@ -6755,8 +6908,8 @@ ObjectInfo Compiler :: compileOperation(BuildTreeWriter& writer, ExprScope& scop arguments[argLen++] = retrieveType(scope, messageArguments[2]); } - if (operatorId == SET_INDEXER_OPERATOR_ID && isPrimitiveArray(arguments[0])) { - if (_logic->isCompatible(*scope.moduleScope, { arguments[1] }, { loperand.typeInfo.elementRef }, false)) + if (operatorId == SET_INDEXER_OPERATOR_ID) { + if (isPrimitiveArray(arguments[0]) && _logic->isCompatible(*scope.moduleScope, { arguments[1] }, { loperand.typeInfo.elementRef }, false)) // HOTFIX : for the generic binary array, recognize the element type arguments[1] = V_ELEMENT; } @@ -8655,6 +8808,7 @@ ObjectInfo Compiler :: compileSubCode(BuildTreeWriter& writer, ExprScope& scope, ExpressionAttribute mode, bool withoutNewScope) { bool retValExpected = EAttrs::testAndExclude(mode, EAttr::RetValExpected); + bool withoutDebugInfo = EAttrs::testAndExclude(mode, EAttr::NoDebugInfo); scope.syncStack(); @@ -8662,7 +8816,7 @@ ObjectInfo Compiler :: compileSubCode(BuildTreeWriter& writer, ExprScope& scope, ObjectInfo retVal = {}; if (!withoutNewScope) { CodeScope codeScope(parentCodeScope); - retVal = compileCode(writer, codeScope, node, retValExpected); + retVal = compileCode(writer, codeScope, node, retValExpected, withoutDebugInfo); codeScope.syncStack(parentCodeScope); } @@ -8676,13 +8830,22 @@ ObjectInfo Compiler :: compileSubCode(BuildTreeWriter& writer, ExprScope& scope, } ObjectInfo Compiler :: compileBranchingOperands(BuildTreeWriter& writer, ExprScope& scope, SyntaxNode rnode, - SyntaxNode r2node, bool retValExpected) + SyntaxNode r2node, bool retValExpected, bool withoutDebugInfo) { + CodeScope* codeScope = Scope::getScope(scope, Scope::ScopeLevel::Code); + writer.newNode(BuildKey::Tape); ObjectInfo subRetCode = {}; + bool oldWithRet = codeScope->withRetStatement; if (rnode == SyntaxKey::ClosureBlock || rnode == SyntaxKey::SwitchCode) { - subRetCode = compileSubCode(writer, scope, rnode.firstChild(), retValExpected ? EAttr::RetValExpected : EAttr::None); + EAttr mode = retValExpected ? EAttr::RetValExpected : EAttr::None; + if (withoutDebugInfo) + mode = mode | EAttr::NoDebugInfo; + + codeScope->withRetStatement = false; + + subRetCode = compileSubCode(writer, scope, rnode.firstChild(), mode); } else subRetCode = compileExpression(writer, scope, rnode, 0, EAttr::None, nullptr); @@ -8698,7 +8861,18 @@ ObjectInfo Compiler :: compileBranchingOperands(BuildTreeWriter& writer, ExprSco writer.newNode(BuildKey::Tape); ObjectInfo elseSubRetCode = {}; if (r2node == SyntaxKey::ClosureBlock) { - elseSubRetCode = compileSubCode(writer, scope, r2node.firstChild(), retValExpected ? EAttr::RetValExpected : EAttr::None); + bool withRet = codeScope->withRetStatement; + codeScope->withRetStatement = false; + + EAttr mode = retValExpected ? EAttr::RetValExpected : EAttr::None; + if (withoutDebugInfo) + mode = mode | EAttr::NoDebugInfo; + + elseSubRetCode = compileSubCode(writer, scope, r2node.firstChild(), mode); + + if (!withRet || !codeScope->withRetStatement) { + codeScope->withRetStatement = oldWithRet; + } } else elseSubRetCode = compileExpression(writer, scope, r2node, 0, EAttr::None, nullptr); @@ -8712,18 +8886,20 @@ ObjectInfo Compiler :: compileBranchingOperands(BuildTreeWriter& writer, ExprSco } writer.closeNode(); } + else codeScope->withRetStatement = oldWithRet; writer.closeNode(); ObjectInfo retVal = {}; - if (retValExpected) + if (retValExpected) { retVal = { ObjectKind::Object, retType, 0 }; + } return retVal; } ObjectInfo Compiler :: compileBranchingOperation(WriterContext& context, ObjectInfo loperand, SyntaxNode rnode, - SyntaxNode r2node, int operatorId, ArgumentsInfo* updatedOuterArgs, bool retValExpected) + SyntaxNode r2node, int operatorId, ArgumentsInfo* updatedOuterArgs, bool retValExpected, bool withoutDebugInfo) { ObjectInfo retVal = {}; BuildKey op = BuildKey::None; @@ -8767,7 +8943,7 @@ ObjectInfo Compiler :: compileBranchingOperation(WriterContext& context, ObjectI context.writer->newNode(op, operatorId); context.writer->appendNode(BuildKey::Const, context.scope->moduleScope->branchingInfo.trueRef); - retVal = compileBranchingOperands(*context.writer, *context.scope, rnode, r2node, retValExpected); + retVal = compileBranchingOperands(*context.writer, *context.scope, rnode, r2node, retValExpected, withoutDebugInfo); } else { mssg_t message = 0; @@ -8804,7 +8980,7 @@ ObjectInfo Compiler :: compileBranchingOperation(WriterContext& context, ObjectI } ObjectInfo Compiler :: compileBranchingOperation(BuildTreeWriter& writer, ExprScope& scope, SyntaxNode node, - int operatorId, bool retValExpected) + int operatorId, bool retValExpected, bool withoutDebugInfo) { SyntaxNode lnode = node.firstChild(); SyntaxNode rnode = /*skipNestedExpression(*/lnode.nextNode()/*)*/; @@ -8816,14 +8992,17 @@ ObjectInfo Compiler :: compileBranchingOperation(BuildTreeWriter& writer, ExprSc ObjectInfo loperand = compileExpression(writer, scope, lnode, 0, EAttr::Parameter, &updatedOuterArgs); - // HOTFIX : to allow correct step over the branching statement - writer.appendNode(BuildKey::EndStatement); - writer.appendNode(BuildKey::VirtualBreakoint); + if (!withoutDebugInfo) { + // HOTFIX : to allow correct step over the branching statement + writer.appendNode(BuildKey::EndStatement); + writer.appendNode(BuildKey::VirtualBreakoint); + } WriterContext context = { &writer, &scope, node }; - auto retVal = compileBranchingOperation(context, loperand, rnode, r2node, operatorId, &updatedOuterArgs, retValExpected); + auto retVal = compileBranchingOperation(context, loperand, rnode, r2node, operatorId, &updatedOuterArgs, retValExpected, withoutDebugInfo); - writer.appendNode(BuildKey::OpenStatement); // HOTFIX : to match the closing statement + if (!withoutDebugInfo) + writer.appendNode(BuildKey::OpenStatement); // HOTFIX : to match the closing statement return retVal; } @@ -9052,36 +9231,6 @@ ObjectInfo Compiler :: mapConstant(Scope& scope, SyntaxNode node) return { ObjectKind::ConstantLiteral, { V_WORD32 }, scope.module->mapConstant(node.identifier()) }; } -inline ref_t mapLongConstant(Compiler::Scope& scope, long long integer) -{ - String s; - - // convert back to string as a decimal integer - s.appendLong(integer, 16); - - return scope.moduleScope->module->mapConstant(s.str()); -} - -inline ref_t mapUIntConstant(Compiler::Scope& scope, int integer) -{ - String s; - - // convert back to string as a decimal integer - s.appendUInt(integer, 16); - - return scope.moduleScope->module->mapConstant(s.str()); -} - -inline ref_t mapFloat64Const(Compiler::Scope& scope, double val) -{ - String s; - - // convert back to string as a decimal integer - s.appendDouble(val); - - return scope.moduleScope->module->mapConstant(s.str()); -} - ObjectInfo Compiler :: mapIntConstant(Scope& scope, SyntaxNode node, int radix) { int integer = StrConvertor::toInt(node.identifier(), radix); @@ -9119,22 +9268,34 @@ ObjectInfo Compiler :: mapLongConstant(Scope& scope, SyntaxNode node, int radix) return { ObjectKind::LongLiteral, { V_INT64 }, ::mapLongConstant(scope, integer)}; } -ObjectInfo Compiler :: mapFloat64Constant(Scope& scope, SyntaxNode node) +inline bool defineFloat64Constant(ustr_t val, ModuleBase* module, ObjectInfo& retVal) { double real = 0; - ustr_t val = node.identifier(); if (val.endsWith("r")) { String tmp(val); tmp.truncate(tmp.length() - 1); real = StrConvertor::toDouble(tmp.str()); } - else real = StrConvertor::toDouble(node.identifier()); + else real = StrConvertor::toDouble(val); if (errno == ERANGE) + return false; + + retVal = { ObjectKind::Float64Literal, { V_FLOAT64 }, ::mapFloat64Const(module, real) }; + + return true; +} + +ObjectInfo Compiler :: mapFloat64Constant(Scope& scope, SyntaxNode node) +{ + ObjectInfo retVal = {}; + + if (!defineFloat64Constant(node.identifier(), scope.module, retVal)) { scope.raiseError(errInvalidIntNumber, node); + } - return { ObjectKind::Float64Literal, { V_FLOAT64 }, ::mapFloat64Const(scope, real) }; + return retVal; } ObjectInfo Compiler :: mapMessageConstant(Scope& scope, SyntaxNode node, ref_t actionRef) @@ -9579,37 +9740,41 @@ inline bool isNormalConstant(ObjectInfo info) } } -ObjectInfo Compiler :: convertIntLiteral(ExprScope& scope, SyntaxNode node, ObjectInfo source, ref_t targetRef) +ObjectInfo Compiler :: convertIntLiteral(ExprScope& scope, SyntaxNode node, ObjectInfo source, ref_t targetRef, bool ignoreError) { + bool invalid = false; switch (targetRef) { case V_UINT8: - if (source.extra < 0 || source.extra > 255) - scope.raiseError(errInvalidOperation, node); + invalid = source.extra < 0 || source.extra > 255; break; case V_INT8: - if (source.extra < INT8_MIN || source.extra > INT8_MAX) - scope.raiseError(errInvalidOperation, node); + invalid = source.extra < INT8_MIN || source.extra > INT8_MAX; break; case V_INT16: - if (source.extra < INT16_MIN || source.extra > INT16_MAX) - scope.raiseError(errInvalidOperation, node); + invalid = source.extra < INT16_MIN || source.extra > INT16_MAX; break; case V_UINT16: - if (source.extra < 0 || source.extra > 65535) - scope.raiseError(errInvalidOperation, node); + invalid = source.extra < 0 || source.extra > 65535; break; case V_INT64: source.kind = ObjectKind::LongLiteral; break; case V_FLOAT64: source.kind = ObjectKind::Float64Literal; - source.reference = mapFloat64Const(scope, source.extra); + source.reference = mapFloat64Const(scope.module, source.extra); break; default: - scope.raiseError(errInvalidOperation, node); + invalid = true; break; } + if (invalid) { + if (!ignoreError) + scope.raiseError(errInvalidOperation, node); + + return {}; + } + source.typeInfo = { targetRef }; return source; @@ -9995,7 +10160,7 @@ void Compiler :: compileSwitchOperation(BuildTreeWriter& writer, ExprScope& scop arguments.add(loperand); arguments.add(value); ObjectInfo retVal = compileOperation(writer, scope, node, arguments, operator_id, 0, nullptr); - compileBranchingOperation(context, retVal, optionNode.nextNode(), {}, IF_OPERATOR_ID, nullptr, false); + compileBranchingOperation(context, retVal, optionNode.nextNode(), {}, IF_OPERATOR_ID, nullptr, false, false); writer.closeNode(); break; @@ -10352,13 +10517,13 @@ ObjectInfo Compiler :: compileExpression(BuildTreeWriter& writer, ExprScope& sco case SyntaxKey::IfNotOperation: case SyntaxKey::IfElseOperation: retVal = compileBranchingOperation(writer, scope, current, (int)current.key - OPERATOR_MAKS, - EAttrs::test(mode, EAttr::RetValExpected)); + EAttrs::test(mode, EAttr::RetValExpected), EAttrs::test(mode, EAttr::NoDebugInfo)); break; case SyntaxKey::BranchOperation: // HOTFIX : used for script based code retVal = compileBranchingOperation(writer, scope, current, (current.firstChild().nextNode().nextNode() != SyntaxKey::None ? IF_ELSE_OPERATOR_ID : IF_OPERATOR_ID), - EAttrs::test(mode, EAttr::RetValExpected)); + EAttrs::test(mode, EAttr::RetValExpected), false); break; case SyntaxKey::LoopOperation: retVal = compileLoopExpression(writer, scope, current.firstChild(), mode); @@ -10517,7 +10682,7 @@ ObjectInfo Compiler :: compileRetExpression(BuildTreeWriter& writer, CodeScope& compileAssigningOp(context, byRefTarget, retVal); - retVal = {}; + retVal = scope.mapSelf(); } else { retVal = boxArgument(context, retVal, @@ -10546,15 +10711,21 @@ ObjectInfo Compiler :: compileRetExpression(BuildTreeWriter& writer, CodeScope& scope.syncStack(); + codeScope.withRetStatement = true; + return retVal; } ObjectInfo Compiler :: compileRootExpression(BuildTreeWriter& writer, CodeScope& codeScope, SyntaxNode node, EAttr mode) { + bool noDebugInfo = EAttrs::test(mode, EAttr::NoDebugInfo); + ExprScope scope(&codeScope); - writer.appendNode(BuildKey::OpenStatement); - addBreakpoint(writer, findObjectNode(node), BuildKey::Breakpoint); + if (!noDebugInfo) { + writer.appendNode(BuildKey::OpenStatement); + addBreakpoint(writer, findObjectNode(node), BuildKey::Breakpoint); + } auto retVal = compileExpression(writer, scope, node, 0, mode, nullptr); @@ -10562,7 +10733,8 @@ ObjectInfo Compiler :: compileRootExpression(BuildTreeWriter& writer, CodeScope& // retVal = boxArgumentInPlace(writer, scope, retVal); //} - writer.appendNode(BuildKey::EndStatement); + if (!noDebugInfo) + writer.appendNode(BuildKey::EndStatement); scope.syncStack(); @@ -10722,7 +10894,7 @@ void Compiler :: beginMethod(BuildTreeWriter& writer, MethodScope& scope, Syntax writer.newNode(BuildKey::Tape); - writeParameterDebugInfo(writer, scope); + writeMethodDebugInfo(writer, scope); writeMessageInfo(writer, scope); } @@ -10819,9 +10991,17 @@ void Compiler :: injectVariableInfo(BuildNode node, CodeScope& codeScope) varNode.appendChild(BuildKey::Index, localInfo.offset); } else { - // !! temporal stub - BuildNode varNode = node.appendChild(BuildKey::Variable, it.key()); + BuildNode varNode = node.appendChild(BuildKey::VariableAddress, it.key()); varNode.appendChild(BuildKey::Index, localInfo.offset); + + ustr_t className = codeScope.moduleScope->module->resolveReference(localInfo.typeInfo.typeRef); + if (isWeakReference(className)) { + IdentifierString fullName(codeScope.module->name()); + fullName.append(className); + + varNode.appendChild(BuildKey::ClassName, *fullName); + } + else varNode.appendChild(BuildKey::ClassName, className); } } else { @@ -10831,7 +11011,7 @@ void Compiler :: injectVariableInfo(BuildNode node, CodeScope& codeScope) } } -ObjectInfo Compiler :: compileCode(BuildTreeWriter& writer, CodeScope& codeScope, SyntaxNode node, bool closureMode) +ObjectInfo Compiler :: compileCode(BuildTreeWriter& writer, CodeScope& codeScope, SyntaxNode node, bool closureMode, bool noDebugInfoMode) { ObjectInfo retVal = {}; ObjectInfo exprRetVal = {}; @@ -10842,6 +11022,8 @@ ObjectInfo Compiler :: compileCode(BuildTreeWriter& writer, CodeScope& codeScope writer.closeNode(); EAttr mode = closureMode ? EAttr::RetValExpected : EAttr::None; + if (noDebugInfoMode) + mode = mode | EAttr::NoDebugInfo; SyntaxNode current = node.firstChild(); while (current != SyntaxKey::None) { @@ -10854,9 +11036,19 @@ ObjectInfo Compiler :: compileCode(BuildTreeWriter& writer, CodeScope& codeScope break; case SyntaxKey::CodeBlock: { + bool autoGenerated = current.existChild(SyntaxKey::Autogenerated); + + if (!noDebugInfoMode && autoGenerated) { + writer.appendNode(BuildKey::OpenStatement); + addBreakpoint(writer, findObjectNode(current.firstChild()), BuildKey::Breakpoint); + } + CodeScope subScope(&codeScope); - exprRetVal = compileCode(writer, subScope, current, false); + exprRetVal = compileCode(writer, subScope, current, false, autoGenerated); subScope.syncStack(&codeScope); + + if (!noDebugInfoMode && autoGenerated) + writer.appendNode(BuildKey::EndStatement); break; } case SyntaxKey::EOP: @@ -10968,7 +11160,28 @@ void Compiler :: compileMethodCode(BuildTreeWriter& writer, ClassScope* classSco if (codeScope.isByRefHandler() && retVal.kind != ObjectKind::Unknown) { ExprScope exprScope(&codeScope); WriterContext context = { &writer, &exprScope, node }; - compileAssigningOp(context, codeScope.mapByRefReturnArg(), retVal); + + ObjectInfo byRefVar = codeScope.mapByRefReturnArg(); + + retVal = convertObject(writer, exprScope, node, retVal, + retrieveStrongType(scope, byRefVar), false, false); + + compileAssigningOp(context, byRefVar, retVal); + } + else if (scope.info.outputRef != 0 && !scope.constructorMode){ + ExprScope exprScope(&codeScope); + WriterContext context = { &writer, &exprScope, node }; + + ref_t outputRef = scope.info.outputRef; + if (outputRef && outputRef != V_AUTO) { + convertObject(writer, exprScope, node, retVal, outputRef, false, false); + + exprScope.syncStack(); + } + + writeObjectInfo(context, + boxArgument(context, retVal, + scope.checkHint(MethodHint::Stacksafe), true, false)); } break; case SyntaxKey::Redirect: @@ -10979,14 +11192,19 @@ void Compiler :: compileMethodCode(BuildTreeWriter& writer, ClassScope* classSco } // if the method returns itself - if (retVal.kind == ObjectKind::Unknown) { + if (retVal.kind == ObjectKind::Unknown && !codeScope.withRetStatement) { ExprScope exprScope(&codeScope); WriterContext context = { &writer, &exprScope, node }; // NOTE : extension should re retVal = scope.mapSelf(!scope.isExtension); if (codeScope.isByRefHandler()) { - compileAssigningOp(context, codeScope.mapByRefReturnArg(), retVal); + ObjectInfo byRefVar = codeScope.mapByRefReturnArg(); + + retVal = convertObject(writer, exprScope, node, retVal, + retrieveStrongType(scope, byRefVar), false, false); + + compileAssigningOp(context, byRefVar, retVal); } else { ref_t outputRef = scope.info.outputRef; @@ -11600,63 +11818,72 @@ void Compiler :: writeMessageInfo(BuildTreeWriter& writer, MethodScope& scope) writer.appendNode(BuildKey::MethodName, *methodName); } -void Compiler :: writeParameterDebugInfo(BuildTreeWriter& writer, MethodScope& scope) +void Compiler :: writeParameterDebugInfo(BuildTreeWriter& writer, Scope& scope, int size, TypeInfo typeInfo, + ustr_t name, int index) { - writer.newNode(BuildKey::ParameterInfo); + if (size > 0) { + if (typeInfo.typeRef == scope.moduleScope->buildins.intReference) { + writer.newNode(BuildKey::IntParameterAddress, name); + } + else if (typeInfo.typeRef == scope.moduleScope->buildins.longReference) { + writer.newNode(BuildKey::LongParameterAddress, name); + } + else if (typeInfo.typeRef == scope.moduleScope->buildins.realReference) { + writer.newNode(BuildKey::RealParameterAddress, name); + } + else { + writer.newNode(BuildKey::ParameterAddress, name); - if (!scope.functionMode) { - writer.newNode(BuildKey::Parameter, "self"); - writer.appendNode(BuildKey::Index, -1); - writer.closeNode(); - } + ref_t classRef = typeInfo.typeRef; + if (isPrimitiveRef(classRef)) + classRef = resolvePrimitiveType(scope, typeInfo, true); - int prefix = scope.functionMode ? 0 : -1; - for (auto it = scope.parameters.start(); !it.eof(); ++it) { - auto paramInfo = *it; + ustr_t className = scope.moduleScope->module->resolveReference(classRef); + if (isWeakReference(className)) { + IdentifierString fullName(scope.module->name()); + fullName.append(className); - if (paramInfo.size > 0) { - if (paramInfo.typeInfo.typeRef == scope.moduleScope->buildins.intReference) { - writer.newNode(BuildKey::IntParameterAddress, it.key()); + writer.appendNode(BuildKey::ClassName, *fullName); } - else if (paramInfo.typeInfo.typeRef == scope.moduleScope->buildins.longReference) { - writer.newNode(BuildKey::LongParameterAddress, it.key()); - } - else if (paramInfo.typeInfo.typeRef == scope.moduleScope->buildins.realReference) { - writer.newNode(BuildKey::RealParameterAddress, it.key()); - } - else { - writer.newNode(BuildKey::ParameterAddress, it.key()); + else writer.appendNode(BuildKey::ClassName, className); + } + } + else if (size < 0) { + if (typeInfo.typeRef == V_INT16ARRAY) { + writer.newNode(BuildKey::ShortArrayParameter, name); + } + else if (typeInfo.typeRef == V_INT8ARRAY) { + writer.newNode(BuildKey::ByteArrayParameter, name); + } + else if (typeInfo.typeRef == V_INT32ARRAY) { + writer.newNode(BuildKey::IntArrayParameter, name); + } + else writer.newNode(BuildKey::Parameter, name); // !! temporal + } + else writer.newNode(BuildKey::Parameter, name); - ref_t classRef = paramInfo.typeInfo.typeRef; - if (isPrimitiveRef(classRef)) - classRef = resolvePrimitiveType(scope, paramInfo.typeInfo, true); + writer.appendNode(BuildKey::Index, index); + writer.closeNode(); - ustr_t className = scope.moduleScope->module->resolveReference(classRef); - if (isWeakReference(className)) { - IdentifierString fullName(scope.module->name()); - fullName.append(className); +} - writer.appendNode(BuildKey::ClassName, *fullName); - } - else writer.appendNode(BuildKey::ClassName, className); - } - } - else if (paramInfo.size < 0) { - if (paramInfo.typeInfo.typeRef == V_INT16ARRAY) { - writer.newNode(BuildKey::ShortArrayParameter, it.key()); - } - else if (paramInfo.typeInfo.typeRef == V_INT8ARRAY) { - writer.newNode(BuildKey::ByteArrayParameter, it.key()); - } - else if (paramInfo.typeInfo.typeRef == V_INT32ARRAY) { - writer.newNode(BuildKey::IntArrayParameter, it.key()); - } - else writer.newNode(BuildKey::Parameter, it.key()); // !! temporal - } - else writer.newNode(BuildKey::Parameter, it.key()); +void Compiler :: writeMethodDebugInfo(BuildTreeWriter& writer, MethodScope& scope) +{ + writer.newNode(BuildKey::ArgumentsInfo); - writer.appendNode(BuildKey::Index, prefix - paramInfo.offset); - writer.closeNode(); + if (!scope.functionMode) { + ref_t classRef = scope.getClassRef(); + + writeParameterDebugInfo(writer, scope, _logic->defineStructSize(*scope.moduleScope, classRef).size, + { classRef }, "self", -1); + } + + int prefix = scope.functionMode ? 0 : -1; + for (auto it = scope.parameters.start(); !it.eof(); ++it) { + auto paramInfo = *it; + + writeParameterDebugInfo(writer, scope, paramInfo.size, paramInfo.typeInfo, + it.key(), prefix - paramInfo.offset); } writer.closeNode(); diff --git a/elenasrc3/elc/compiler.h b/elenasrc3/elc/compiler.h index daa8eaad46..2ce80faea8 100644 --- a/elenasrc3/elc/compiler.h +++ b/elenasrc3/elc/compiler.h @@ -3,7 +3,7 @@ // // This file contains ELENA compiler class. // -// (C)2021-2023, by Aleksey Rakov +// (C)2021-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #ifndef COMPILER_H @@ -92,7 +92,7 @@ namespace elena_lang Wrapper, ClosureInfo, MemberInfo, - LocalField + LocalField, }; enum TargetMode @@ -112,7 +112,7 @@ namespace elena_lang BoxingPtr, Conditional, ConditionalUnboxingRequired, - Weak + Weak, }; struct ObjectInfo @@ -309,6 +309,7 @@ namespace elena_lang bool evalObjArrayOp(ref_t operator_id, ArgumentsInfo& args); bool evalDeclOp(ref_t operator_id, ArgumentsInfo& args, ObjectInfo& retVal); bool evalIntOp(ref_t operator_id, ArgumentsInfo& args, ObjectInfo& retVal); + bool evalRealOp(ref_t operator_id, ArgumentsInfo& args, ObjectInfo& retVal); public: ObjectInfo mapStringConstant(ustr_t s); @@ -813,6 +814,8 @@ namespace elena_lang pos_t allocated1, reserved1; // defines managed frame size pos_t allocated2, reserved2; // defines unmanaged frame size + bool withRetStatement; + Scope* getScope(ScopeLevel level) override { if (level == ScopeLevel::Code) { @@ -1278,7 +1281,9 @@ namespace elena_lang ref_t compileMessageArguments(BuildTreeWriter& writer, ExprScope& scope, SyntaxNode current, ArgumentsInfo& arguments, ref_t expectedSignRef, ExpressionAttribute mode, ArgumentsInfo* updatedOuterArgs, bool& variadicArgList); - void writeParameterDebugInfo(BuildTreeWriter& writer, MethodScope& scope); + void writeParameterDebugInfo(BuildTreeWriter& writer, Scope& scope, int size, TypeInfo typeInfo, + ustr_t name, int index); + void writeMethodDebugInfo(BuildTreeWriter& writer, MethodScope& scope); void writeMessageInfo(BuildTreeWriter& writer, MethodScope& scope); void compileInlineInitializing(BuildTreeWriter& writer, ClassScope& classScope, SyntaxNode node); @@ -1308,7 +1313,9 @@ namespace elena_lang ObjectInfo typecastObject(BuildTreeWriter& writer, ExprScope& scope, SyntaxNode node, ObjectInfo source, ref_t targetRef); ObjectInfo convertObject(BuildTreeWriter& writer, ExprScope& scope, SyntaxNode node, ObjectInfo source, ref_t targetRef, bool dynamicRequired, bool withoutBoxing); - ObjectInfo convertIntLiteral(ExprScope& scope, SyntaxNode node, ObjectInfo source, ref_t targetRef); + ObjectInfo convertIntLiteral(ExprScope& scope, SyntaxNode node, ObjectInfo source, ref_t targetRef, bool ignoreError = false); + + void convertIntLiteralForOperation(ExprScope& scope, SyntaxNode node, int operatorId, ArgumentsInfo& messageArguments); bool compileSymbolConstant(SymbolScope& scope, ObjectInfo retVal); @@ -1353,11 +1360,11 @@ namespace elena_lang ref_t expectedRef, ExpressionAttribute mode); ObjectInfo compileSpecialOperation(BuildTreeWriter& writer, ExprScope& scope, SyntaxNode node, int operatorId, ref_t expectedRef); ObjectInfo compileBranchingOperands(BuildTreeWriter& writer, ExprScope& scope, SyntaxNode rnode, - SyntaxNode r2node, bool retValExpected); + SyntaxNode r2node, bool retValExpected, bool withoutDebugInfo); ObjectInfo compileBranchingOperation(WriterContext& context, ObjectInfo loperand, SyntaxNode rnode, - SyntaxNode r2node, int operatorId, ArgumentsInfo* updatedOuterArgs, bool retValExpected); + SyntaxNode r2node, int operatorId, ArgumentsInfo* updatedOuterArgs, bool retValExpected, bool withoutDebugInfo); ObjectInfo compileBranchingOperation(BuildTreeWriter& writer, ExprScope& scope, SyntaxNode node, - int operatorId, bool retValExpected); + int operatorId, bool retValExpected, bool withoutDebugInfo); ObjectInfo compileCatchOperation(BuildTreeWriter& writer, ExprScope& scope, SyntaxNode node); ObjectInfo compileFinalOperation(BuildTreeWriter& writer, ExprScope& scope, SyntaxNode node); ObjectInfo compileAltOperation(BuildTreeWriter& writer, ExprScope& scope, SyntaxNode node); @@ -1422,7 +1429,7 @@ namespace elena_lang ObjectInfo compileResendCode(BuildTreeWriter& writer, CodeScope& codeScope, ObjectInfo source, SyntaxNode node); ObjectInfo compileRedirect(BuildTreeWriter& writer, CodeScope& codeScope, SyntaxNode node); - ObjectInfo compileCode(BuildTreeWriter& writer, CodeScope& codeScope, SyntaxNode node, bool closureMode); + ObjectInfo compileCode(BuildTreeWriter& writer, CodeScope& codeScope, SyntaxNode node, bool closureMode, bool noDebugInfoMode = false); void beginMethod(BuildTreeWriter& writer, MethodScope& scope, SyntaxNode node, BuildKey scopeKey, bool withDebugInfo); diff --git a/elenasrc3/elc/compilerlogic.cpp b/elenasrc3/elc/compilerlogic.cpp index 075f56325e..e123a98129 100644 --- a/elenasrc3/elc/compilerlogic.cpp +++ b/elenasrc3/elc/compilerlogic.cpp @@ -41,7 +41,7 @@ bool testMethodHint(ref_t hint, MethodHint mask) typedef CompilerLogic::Op Op; -constexpr auto OperationLength = 198; +constexpr auto OperationLength = 199; constexpr Op Operations[OperationLength] = { { @@ -290,6 +290,9 @@ constexpr Op Operations[OperationLength] = { BNOT_OPERATOR_ID, BuildKey::LongSOp, V_INT64, 0, 0, V_INT64 }, + { + NEGATE_OPERATOR_ID, BuildKey::LongSOp, V_INT64, 0, 0, V_INT64 + }, { EQUAL_OPERATOR_ID, BuildKey::LongCondOp, V_INT64, V_INT64, 0, V_FLAG }, @@ -1717,13 +1720,17 @@ SizeInfo CompilerLogic :: defineStructSize(ClassInfo& info) SizeInfo CompilerLogic :: defineStructSize(ModuleScopeBase& scope, ref_t reference) { + if (!reference) + return {}; + auto sizeInfo = scope.cachedSizes.get(reference); if (!sizeInfo.size) { ClassInfo classInfo; if (defineClassInfo(scope, classInfo, reference)) { sizeInfo = defineStructSize(classInfo); - scope.cachedSizes.add(reference, sizeInfo); + if (sizeInfo.size) + scope.cachedSizes.add(reference, sizeInfo); return sizeInfo; } @@ -2019,6 +2026,16 @@ inline mssg_t resolveNonpublic(mssg_t weakMessage, ClassInfo& info, bool selfCal return nonpublicMessage; } +inline ref_t mapWeakSignature(ModuleScopeBase& scope, int counter) +{ + ref_t signatures[ARG_COUNT] = { 0 }; + ref_t signatureLen = counter; + for (int i = 0; i < counter; i++) + signatures[i] = scope.buildins.superReference; + + return scope.module->mapSignature(signatures, signatureLen, false); +} + mssg_t CompilerLogic :: resolveMultimethod(ModuleScopeBase& scope, mssg_t weakMessage, ref_t targetRef, ref_t implicitSignatureRef, int& stackSafeAttr, bool selfCall) { @@ -2033,6 +2050,10 @@ mssg_t CompilerLogic :: resolveMultimethod(ModuleScopeBase& scope, mssg_t weakMe // check if it is non public message mssg_t nonPublicMultiMessage = resolveNonpublic(weakMessage, info, selfCall, scope.isInternalOp(targetRef)); if (nonPublicMultiMessage != 0) { + if (!implicitSignatureRef && test(nonPublicMultiMessage, STATIC_MESSAGE) && getArgCount(weakMessage) > 1) { + implicitSignatureRef = mapWeakSignature(scope, getArgCount(weakMessage) - 1); + } + mssg_t resolved = resolveMultimethod(scope, nonPublicMultiMessage, targetRef, implicitSignatureRef, stackSafeAttr, selfCall); if (!resolved) { return nonPublicMultiMessage; @@ -2040,7 +2061,8 @@ mssg_t CompilerLogic :: resolveMultimethod(ModuleScopeBase& scope, mssg_t weakMe else return resolved; } - if (!implicitSignatureRef) + // allow to check the variadic message without arguments + if (!implicitSignatureRef && ((weakMessage & PREFIX_MESSAGE_MASK) != VARIADIC_MESSAGE)) return 0; ref_t signatures[ARG_COUNT]; @@ -2729,3 +2751,24 @@ bool CompilerLogic :: clearMetaData(ModuleScopeBase* moduleScope, ustr_t name) return true; } + +ref_t CompilerLogic :: retrievePrimitiveType(ModuleScopeBase& scope, ref_t reference) +{ + if (!reference || isPrimitiveRef(reference)) + return reference; + + ClassInfo info; + if (!scope.loadClassInfo(info, reference)) + return 0; + + if (isWrapper(info)) { + auto inner = *info.fields.start(); + + if (isPrimitiveRef(inner.typeInfo.typeRef)) + return inner.typeInfo.typeRef; + + return retrievePrimitiveType(scope, inner.typeInfo.typeRef); + } + + return 0; +} diff --git a/elenasrc3/elc/compilerlogic.h b/elenasrc3/elc/compilerlogic.h index db58080433..a4b5cf60de 100644 --- a/elenasrc3/elc/compilerlogic.h +++ b/elenasrc3/elc/compilerlogic.h @@ -141,6 +141,8 @@ namespace elena_lang bool isNumericType(ModuleScopeBase& scope, ref_t& reference); + ref_t retrievePrimitiveType(ModuleScopeBase& scope, ref_t reference); + void tweakClassFlags(ModuleScopeBase& scope, ref_t classRef, ClassInfo& info, bool classClassMode); void tweakPrimitiveClassFlags(ClassInfo& info, ref_t classRef); diff --git a/elenasrc3/elc/compiling.cpp b/elenasrc3/elc/compiling.cpp index db1bcbe565..ea6f81dfb3 100644 --- a/elenasrc3/elc/compiling.cpp +++ b/elenasrc3/elc/compiling.cpp @@ -726,7 +726,8 @@ int CompilingProcess :: build(Project& project, pos_t defaultStackAlignment, pos_t defaultRawStackAlignment, pos_t defaultEHTableEntrySize, - int minimalArgList) + int minimalArgList, + ustr_t profile) { try { @@ -740,6 +741,9 @@ int CompilingProcess :: build(Project& project, _presenter->printLine(ELC_STARTING, project.ProjectName(), getPlatformName(project.Platform()), getTargetTypeName(targetType, project.SystemTarget())); + if (!profile.empty()) + _presenter->printLine(ELC_PROFILE_INFO, profile); + // Cleaning up _presenter->printLine(ELC_CLEANING); cleanUp(project); diff --git a/elenasrc3/elc/compiling.h b/elenasrc3/elc/compiling.h index 7d6618966f..557ac13196 100644 --- a/elenasrc3/elc/compiling.h +++ b/elenasrc3/elc/compiling.h @@ -133,7 +133,8 @@ namespace elena_lang pos_t defaultStackAlignment, pos_t defaultRawStackAlignment, pos_t defaultEHTableEntrySize, - int minimalArgList); + int minimalArgList, + ustr_t profile); int clean(Project& project); void setVerboseOn() diff --git a/elenasrc3/elc/derivation.cpp b/elenasrc3/elc/derivation.cpp index bb2e0daf7f..7ed187d473 100644 --- a/elenasrc3/elc/derivation.cpp +++ b/elenasrc3/elc/derivation.cpp @@ -516,6 +516,8 @@ void SyntaxTreeBuilder :: generateTemplateOperation(SyntaxTreeWriter& writer, Sc { if (writer.CurrentNode() == SyntaxKey::Expression) writer.CurrentNode().setKey(SyntaxKey::CodeBlock); + + writer.CurrentNode().appendChild(SyntaxKey::Autogenerated); } else { _errorProcessor->raiseTerminalError(errInvalidOperation, retrievePath(node), node); @@ -774,7 +776,7 @@ void SyntaxTreeBuilder :: flushTypeAttribute(SyntaxTreeWriter& writer, Scope& sc SyntaxNode current = node.firstChild(); while (current != SyntaxKey::None) { if (current == SyntaxKey::ArrayType) { - flushAttribute(writer, scope, current, previusCategory, allowType, 1); + flushAttribute(writer, scope, current.firstChild(), previusCategory, allowType, 1); } else if (current == SyntaxKey::TemplateType) { flushTemplateType(writer, scope, current, false); diff --git a/elenasrc3/elc/errors.h b/elenasrc3/elc/errors.h index c7738b7954..b52b5ff58e 100644 --- a/elenasrc3/elc/errors.h +++ b/elenasrc3/elc/errors.h @@ -118,6 +118,7 @@ namespace elena_lang constexpr auto infoMsgUnknownMessage = "\ninfo 706: unhandled message: %s\n"; constexpr auto infoMsgTargetClass = "info 707: target class: %s\n"; constexpr auto infoMsgScopeMethod = "info 708: in the method: %s\n"; + constexpr auto infoMssgExptectedType = "\ninfo 709: the expected type is %s, but the actual type is %s\n"; } // _ELENA_ diff --git a/elenasrc3/elc/linux/elc.cpp b/elenasrc3/elc/linux/elc.cpp index fc04b109b3..da46908d3a 100644 --- a/elenasrc3/elc/linux/elc.cpp +++ b/elenasrc3/elc/linux/elc.cpp @@ -179,7 +179,7 @@ int main(int argc, char* argv[]) // Initializing... PathString configPath(*dataPath, DEFAULT_CONFIG); - project.loadConfig(*configPath, false/*, true, false*/); + project.loadConfig(*configPath, nullptr, false); // Reading command-line arguments... if (argc < 2) { @@ -187,9 +187,20 @@ int main(int argc, char* argv[]) return -3; } + IdentifierString profile; for (int i = 1; i < argc; i++) { if (argv[i][0] == '-') { switch (argv[i][1]) { + case 'f': + { + IdentifierString setting(argv[i] + 2); + process.addForward(*setting); + + break; + } + case 'l': + profile.copy(argv[i] + 2); + break; case 'm': project.addBoolSetting(ProjectOption::MappingOutputMode, true); break; @@ -204,6 +215,9 @@ int main(int argc, char* argv[]) project.addIntSetting(ProjectOption::OptimizationMode, optMiddle); } break; + case 'p': + project.setBasePath(argv[i] + 2); + break; case 'r': cleanMode = true; break; @@ -224,9 +238,6 @@ int main(int argc, char* argv[]) project.loadConfigByName(*dataPath, *configName, true); break; } - case 'p': - project.setBasePath(argv[i] + 2); - break; case 'v': process.setVerboseOn(); break; @@ -255,13 +266,6 @@ int main(int argc, char* argv[]) project.addBoolSetting(ProjectOption::GenerateParamNameInfo, argv[i][3] != '-'); } break; - case 'f': - { - IdentifierString setting(argv[i] + 2); - process.addForward(*setting); - - break; - } default: break; } @@ -269,9 +273,20 @@ int main(int argc, char* argv[]) else if (PathUtil::checkExtension(argv[i], "project")) { PathString path(argv[i]); - if (!project.loadProject(*path)) { + if (!project.loadProject(*path, *profile)) { errorProcessor.raisePathError(errProjectAlreadyLoaded, *path); } + else if (profile.empty() && project.availableProfileList.count() != 0) { + IdentifierString profileList; + for (auto it = project.availableProfileList.start(); !it.eof(); ++it) { + if (profileList.length() != 0) + profileList.append(", "); + + profileList.append(*it); + } + + Presenter::getInstance().printLine(ELC_PROFILE_WARNING, *profileList); + } } else { FileNameString fileName(argv[i]); @@ -289,13 +304,12 @@ int main(int argc, char* argv[]) DEFAULT_STACKALIGNMENT, DEFAULT_RAW_STACKALIGNMENT, DEFAULT_EHTABLE_ENTRY_SIZE, - MINIMAL_ARG_LIST); + MINIMAL_ARG_LIST, + *profile); } } catch (CLIException e) { return -2; } - - } diff --git a/elenasrc3/elc/messages.h b/elenasrc3/elc/messages.h index c5703aca37..5c9107861e 100644 --- a/elenasrc3/elc/messages.h +++ b/elenasrc3/elc/messages.h @@ -3,14 +3,14 @@ // // Copmpiler messages // -// (C)2021-2023, by Aleksey Rakov +// (C)2021-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #include "errors.h" namespace elena_lang { - constexpr auto MessageLength = 92; + constexpr auto MessageLength = 93; const Pair Messages[MessageLength] = { {errDuplicatedSymbol, errMsgDuplicatedSymbol}, @@ -104,7 +104,8 @@ namespace elena_lang {infoMixedUpVariadic, infoMssgMixedUpVariadic}, {errRedirectToItself, errMsgRedirectToItself}, {errIllegalStaticMethod, errMsgIllegalStaticMethod }, - {errAssigningRealOnly, errMssgAssigningRealOnly } + {errAssigningRealOnly, errMssgAssigningRealOnly }, + {infoExptectedType, infoMssgExptectedType }, }; } diff --git a/elenasrc3/elc/parser.h b/elenasrc3/elc/parser.h index e1c27b26ac..6db4aaee44 100644 --- a/elenasrc3/elc/parser.h +++ b/elenasrc3/elc/parser.h @@ -52,6 +52,7 @@ namespace elena_lang { this->eof = this->identifier = 0; this->reference = 0; + this->globalreference = 0; this->string = this->character = 0; this->wide = 0; this->integer = this->hexinteger = 0; diff --git a/elenasrc3/elc/project.cpp b/elenasrc3/elc/project.cpp index 6251e45d1d..51c0581e48 100644 --- a/elenasrc3/elc/project.cpp +++ b/elenasrc3/elc/project.cpp @@ -3,7 +3,7 @@ // // This file contains the project class body // -// (C)2021-2023, by Aleksey Rakov +// (C)2021-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #include "elena.h" @@ -264,7 +264,7 @@ bool Project :: loadConfigByName(path_t configPath, ustr_t name, bool markAsLoad if (!relativePath.empty()) { PathString baseConfigPath(configPath, relativePath); - if (loadConfig(*baseConfigPath, false)) { + if (loadConfig(*baseConfigPath, nullptr, false)) { if (markAsLoaded) _loaded = true; @@ -274,6 +274,16 @@ bool Project :: loadConfigByName(path_t configPath, ustr_t name, bool markAsLoad return false; } +void Project :: loadConfig(ConfigFile& config, path_t configPath, ConfigFile::Node& root, ustr_t profileName) +{ + loadConfig(config, configPath, root); + if (!profileName.empty()) { + ConfigFile::Node profileRoot = getProfileRoot(config, root, profileName); + + loadConfig(config, configPath, profileRoot); + } +} + void Project :: loadConfig(ConfigFile& config, path_t configPath, ConfigFile::Node& root) { if (!root.isNotFound()) { @@ -326,15 +336,15 @@ void Project :: loadConfig(ConfigFile& config, path_t configPath, ConfigFile::No } } -void Project :: loadConfig(ConfigFile& config, path_t configPath) +void Project :: loadConfig(ConfigFile& config, path_t configPath, ustr_t profileName) { ConfigFile::Node root = config.selectRootNode(); ConfigFile::Node platformRoot = getPlatformRoot(config, _platform); // load common project settings - loadConfig(config, configPath, root); + loadConfig(config, configPath, root, profileName); // load common target dependent settings - loadConfig(config, configPath, platformRoot); + loadConfig(config, configPath, platformRoot, profileName); } void Project :: loadDefaultConfig() @@ -344,11 +354,11 @@ void Project :: loadDefaultConfig() if (templateNode != ProjectOption::None) { PathString templatePath(_paths.get(templateNode.arg.value)); - loadConfig(*templatePath, false); + loadConfig(*templatePath, nullptr, false); } } -bool Project :: loadConfig(path_t path, bool mainConfig) +bool Project :: loadConfig(path_t path, ustr_t profileName, bool mainConfig) { PathString configPath; configPath.copySubPath(path, false); @@ -359,9 +369,11 @@ bool Project :: loadConfig(path_t path, bool mainConfig) _projectPath.copy(*configPath); _loaded = true; + + loadProfileList(config); } - loadConfig(config, *configPath); + loadConfig(config, *configPath, profileName); return true; } @@ -372,10 +384,10 @@ bool Project :: loadConfig(path_t path, bool mainConfig) } } -bool Project :: loadProject(path_t path) +bool Project :: loadProject(path_t path, ustr_t profileName) { if (_projectName.empty()) { - if(loadConfig(path, true)) { + if(loadConfig(path, profileName, true)) { FileNameString fileName(path); IdentifierString name(*fileName); @@ -431,3 +443,33 @@ void Project :: forEachForward(void* arg, void (* feedback)(void* arg, ustr_t ke feedback(arg, f_it.key(), *f_it); } } + +inline void loadProfileList(ConfigFile& config, ConfigFile::Node& root, IdentifierList* profileList) +{ + ConfigFile::Collection profiles; + if (config.select(root, PROFILE_CATEGORY, profiles)) { + for (auto it = profiles.start(); !it.eof(); ++it) { + ConfigFile::Node profileNode = *it; + + DynamicString key; + profileNode.readAttribute("key", key); + + if (profileList->retrieveIndex(key.str(), [](ustr_t arg, ustr_t current) + { + return current.compare(arg); + }) == -1) + { + profileList->add(ustr_t(key.str()).clone()); + } + } + } +} + +void Project :: loadProfileList(ConfigFile& config) +{ + ConfigFile::Node root = config.selectRootNode(); + ConfigFile::Node platformRoot = getPlatformRoot(config, _platform); + + ::loadProfileList(config, root, &availableProfileList); + ::loadProfileList(config, platformRoot, &availableProfileList); +} diff --git a/elenasrc3/elc/project.h b/elenasrc3/elc/project.h index 2e01872cda..df95d7471a 100644 --- a/elenasrc3/elc/project.h +++ b/elenasrc3/elc/project.h @@ -3,7 +3,7 @@ // // This file contains the project class declaration // -// (C)2021-2023, by Aleksey Rakov +// (C)2021-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #ifndef PROJECT_H @@ -42,12 +42,17 @@ namespace elena_lang void loadTargetType(ConfigFile& config, ConfigFile::Node& configRoot); - void loadConfig(ConfigFile& config, path_t configPath); + void loadConfig(ConfigFile& config, path_t configPath, ustr_t profileName); void loadConfig(ConfigFile& config, path_t configPath, ConfigFile::Node& root); + void loadConfig(ConfigFile& config, path_t configPath, ConfigFile::Node& root, ustr_t profileName); void loadDefaultConfig(); + void loadProfileList(ConfigFile& config); + public: + IdentifierList availableProfileList; + PlatformType SystemTarget(); PlatformType Platform(); PlatformType TargetType(); @@ -80,14 +85,14 @@ namespace elena_lang bool loadConfigByName(path_t configPath, ustr_t name, bool markAsLoaded); - bool loadConfig(path_t path, bool mainConfig); + bool loadConfig(path_t path, ustr_t profileName, bool mainConfig); - bool loadProject(path_t path); + bool loadProject(path_t path, ustr_t profileName); void prepare(); Project(path_t path, PlatformType platform, PresenterBase* presenter) - : XmlProjectBase(platform), _basePath(path) + : XmlProjectBase(platform), _basePath(path), availableProfileList(DEFAULT_STR) { _encoding = FileEncoding::UTF8; diff --git a/elenasrc3/elc/windows/elc.cpp b/elenasrc3/elc/windows/elc.cpp index 98b15747bd..0960502b59 100644 --- a/elenasrc3/elc/windows/elc.cpp +++ b/elenasrc3/elc/windows/elc.cpp @@ -3,7 +3,7 @@ // // This file contains the main body of the win32 / win64 command-line compiler // -// (C)2021-2023, by Aleksey Rakov +// (C)2021-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #include @@ -141,7 +141,7 @@ int main() // Initializing... PathString configPath(*appPath, DEFAULT_CONFIG); - project.loadConfig(*configPath, false/*, true, false*/); + project.loadConfig(*configPath, nullptr, false); // Reading command-line arguments... int argc; @@ -152,9 +152,23 @@ int main() return -2; } + IdentifierString profile; for (int i = 1; i < argc; i++) { if (argv[i][0] == '-') { switch (argv[i][1]) { + case 'f': + { + IdentifierString setting(argv[i] + 2); + process.addForward(*setting); + + break; + } + case 'l': + { + IdentifierString setting(argv[i] + 2); + profile.copy(*setting); + break; + } case 'm': project.addBoolSetting(ProjectOption::MappingOutputMode, true); break; @@ -169,6 +183,9 @@ int main() project.addIntSetting(ProjectOption::OptimizationMode, optMiddle); } break; + case 'p': + project.setBasePath(argv[i] + 2); + break; case 'r': cleanMode = true; break; @@ -189,9 +206,6 @@ int main() project.loadConfigByName(*appPath, *configName, true); break; } - case 'p': - project.setBasePath(argv[i] + 2); - break; case 'v': process.setVerboseOn(); break; @@ -220,23 +234,27 @@ int main() project.addBoolSetting(ProjectOption::GenerateParamNameInfo, argv[i][3] != '-'); } break; - case 'f': - { - IdentifierString setting(argv[i] + 2); - process.addForward(*setting); - - break; - } default: break; } } else if (PathUtil::checkExtension(argv[i], "prj")) { PathString path(argv[i]); - - if (!project.loadProject(*path)) { + if (!project.loadProject(*path, *profile)) { return ERROR_RET_CODE; } + + if (profile.empty() && project.availableProfileList.count() != 0) { + IdentifierString profileList; + for (auto it = project.availableProfileList.start(); !it.eof(); ++it) { + if (profileList.length() != 0) + profileList.append(", "); + + profileList.append(*it); + } + + Presenter::getInstance().printLine(ELC_PROFILE_WARNING, *profileList); + } } else { FileNameString fileName(argv[i]); @@ -254,7 +272,8 @@ int main() DEFAULT_STACKALIGNMENT, DEFAULT_RAW_STACKALIGNMENT, DEFAULT_EHTABLE_ENTRY_SIZE, - MINIMAL_ARG_LIST); + MINIMAL_ARG_LIST, + *profile); } } catch (CLIException) diff --git a/elenasrc3/elenart/rtcommon.h b/elenasrc3/elenart/rtcommon.h index 071585b268..edc2c08769 100644 --- a/elenasrc3/elenart/rtcommon.h +++ b/elenasrc3/elenart/rtcommon.h @@ -14,7 +14,7 @@ namespace elena_lang { -#define ELENART_REVISION_NUMBER 0x0025 +#define ELENART_REVISION_NUMBER 0x0026 } diff --git a/elenasrc3/elenasm/cfparser.cpp b/elenasrc3/elenasm/cfparser.cpp index 3ff9173ebc..cf9a6c899a 100644 --- a/elenasrc3/elenasm/cfparser.cpp +++ b/elenasrc3/elenasm/cfparser.cpp @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------- // E L E N A P r o j e c t: ELENA VM Script Engine // -// (C)2023, by Aleksey Rakov +// (C)2023-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #include "elena.h" @@ -15,12 +15,13 @@ constexpr auto IDENTIFIER_KEYWORD = "$identifier"; constexpr auto LITERAL_KEYWORD = "$literal"; constexpr auto NUMERIC_KEYWORD = "$numeric"; constexpr auto EPS_KEYWORD = "$eps"; -constexpr auto IF_KEYWORD = "$if"; // NOTE : conditional eps rule +constexpr auto IF_KEYWORD = "$if"; // NOTE : conditional eps rule constexpr auto EOF_KEYWORD = "$eof"; constexpr auto EOL_KEYWORD = "$eol"; -constexpr auto ANYCHR_KEYWORD = "$chr"; // > 32 +constexpr auto ANYCHR_KEYWORD = "$chr"; // > 32 constexpr auto CURRENT_KEYWORD = "$current"; constexpr auto CHARACTER_KEYWORD = "$character"; +constexpr auto INTLITERAL_KEYWORD = "$intliteral"; // NOTE : quote containing a number constexpr auto REFERENCE_MODE = 1; constexpr auto IDENTIFIER_MODE = 2; @@ -35,6 +36,7 @@ constexpr auto EXCLUDE_MODE = 10; constexpr auto CHARACTER_MODE = 11; constexpr auto IF_MODE = 12; constexpr auto IFNOT_MODE = 13; +constexpr auto INTLITERAL_MODE = 14; constexpr auto WITHFORWARD_MASK = 0x80000000; constexpr auto POSTFIXSAVE_MODE = 0x80000000; @@ -83,6 +85,20 @@ bool normalLiteralApplyRule(ScriptEngineCFParser::Rule&, ScriptBookmark& bm, Scr return (bm.state == dfaQuote); } +bool normalIntLiteralApplyRule(ScriptEngineCFParser::Rule&, ScriptBookmark& bm, ScriptEngineReaderBase& reader, ScriptEngineCFParser*) +{ + if (bm.state == dfaQuote) { + ustr_t value = reader.lookup(bm); + for (pos_t i = 0; i < getlength(value); i++) { + if (value[i] < '0' && value[i] > '9') + return false; + } + + return true; + } + return false; +} + bool normalNumericApplyRule(ScriptEngineCFParser::Rule&, ScriptBookmark& bm, ScriptEngineReaderBase&, ScriptEngineCFParser*) { return (bm.state == dfaInteger || bm.state == dfaLong || bm.state == dfaReal); @@ -254,6 +270,9 @@ void ScriptEngineCFParser :: defineApplyRule(Rule& rule, int mode, bool forwardM case LITERAL_MODE: rule.apply = normalLiteralApplyRule; break; + case INTLITERAL_MODE: + rule.apply = normalIntLiteralApplyRule; + break; case NUMERIC_MODE: rule.apply = normalNumericApplyRule; break; @@ -353,6 +372,12 @@ void ScriptEngineCFParser :: saveScript(ScriptEngineReaderBase& reader, Rule& ru mode = LITERAL_MODE; } + else if (reader.compare(INTLITERAL_KEYWORD)) { + rule.terminal = INVALID_REF; + rule.saveTo = saveReference; + + mode = INTLITERAL_MODE; + } else if (reader.compare(NUMERIC_KEYWORD)) { rule.terminal = INVALID_REF; rule.saveTo = saveReference; diff --git a/elenasrc3/elenasm/smcommon.h b/elenasrc3/elenasm/smcommon.h index bd4fe548f9..b2d2d53313 100644 --- a/elenasrc3/elenasm/smcommon.h +++ b/elenasrc3/elenasm/smcommon.h @@ -9,7 +9,7 @@ #ifndef RTCOMMON_H #define RTCOMMON_H -#define ELENASM_REVISION_NUMBER 0x000E +#define ELENASM_REVISION_NUMBER 0x000F namespace elena_lang { diff --git a/elenasrc3/elenavm/elenavmmachine.cpp b/elenasrc3/elenavm/elenavmmachine.cpp index 21c3aae291..cd9761ff29 100644 --- a/elenasrc3/elenavm/elenavmmachine.cpp +++ b/elenasrc3/elenavm/elenavmmachine.cpp @@ -120,7 +120,9 @@ void ELENAVMMachine :: init(JITLinker& linker, SystemEnv* exeEnv) (uintptr_t)exeEnv->th_table, (uintptr_t)exeEnv->th_single_content); - linker.prepare(_compiler); + linker.setCompiler(_compiler); + + linker.prepare(); _env = (SystemEnv*)_compiler->getSystemEnv(); @@ -728,4 +730,11 @@ size_t ELENAVMMachine :: loadClassMessages(void* classPtr, mssg_t* output, size_ return SystemRoutineProvider::LoadMessages(msection, classPtr, output, skip, maxLength, true); +} + +bool ELENAVMMachine :: checkClassMessage(void* classPtr, mssg_t message) +{ + MemoryBase* msection = getMDataSection(); + + return SystemRoutineProvider::CheckMessage(msection, classPtr, message); } \ No newline at end of file diff --git a/elenasrc3/elenavm/elenavmmachine.h b/elenasrc3/elenavm/elenavmmachine.h index 9ce918cdb8..33508a373d 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-2023, by Aleksey Rakov +// (C)2022-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #ifndef ELENAVMMACHINE_H @@ -16,7 +16,7 @@ namespace elena_lang { - constexpr auto ELENAVM_GREETING = "ELENA VM %d.%d.%d (C)2022-2023 by Aleksey Rakov"; + constexpr auto ELENAVM_GREETING = "ELENA VM %d.%d.%d (C)2022-2024 by Aleksey Rakov"; constexpr auto ELENAVM_INITIALIZING = "Initializing..."; // --- ELENAVMConfiguration --- @@ -122,6 +122,8 @@ namespace elena_lang size_t loadClassMessages(void* classPtr, mssg_t* output, size_t skip, size_t maxLength); + bool checkClassMessage(void* classPtr, mssg_t message); + int loadExtensionDispatcher(const char* moduleList, mssg_t message, void* output); void Exit(int exitCode); diff --git a/elenasrc3/elenavm/vmcommon.h b/elenasrc3/elenavm/vmcommon.h index 64a8468d4d..4995bc1f0f 100644 --- a/elenasrc3/elenavm/vmcommon.h +++ b/elenasrc3/elenavm/vmcommon.h @@ -3,12 +3,12 @@ // // This file contains the compiler common interfaces & types // -// (C)2021-2023, by Aleksey Rakov +// (C)2021-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #ifndef VMCOMMON_H #define VMCOMMON_H -#define ELENAVM_REVISION_NUMBER 0x001E +#define ELENAVM_REVISION_NUMBER 0x0020 #endif diff --git a/elenasrc3/elenavm/windows/dllmain.cpp b/elenasrc3/elenavm/windows/dllmain.cpp index 583e3384ef..bcb5a22421 100644 --- a/elenasrc3/elenavm/windows/dllmain.cpp +++ b/elenasrc3/elenavm/windows/dllmain.cpp @@ -304,6 +304,11 @@ EXTERN_DLL_EXPORT size_t LoadClassMessagesLA(void* classPtr, mssg_t* output, siz return machine->loadClassMessages(classPtr, output, skip, maxLength); } +EXTERN_DLL_EXPORT bool CheckClassMessageLA(void* classPtr, mssg_t message) +{ + return machine->checkClassMessage(classPtr, message); +} + EXTERN_DLL_EXPORT void GetRandomSeedLA(SeedStruct& seed) { machine->initRandomSeed(seed); diff --git a/elenasrc3/engine/bcwriter.cpp b/elenasrc3/engine/bcwriter.cpp index 6582e1b7d8..0d1f32b5c1 100644 --- a/elenasrc3/engine/bcwriter.cpp +++ b/elenasrc3/engine/bcwriter.cpp @@ -1257,6 +1257,12 @@ void longSOp(CommandTape& tape, BuildNode& node, TapeScope&) case BNOT_OPERATOR_ID: tape.write(ByteCode::INotDPN, targetOffset, 8); break; + case NEGATE_OPERATOR_ID: + tape.write(ByteCode::PeekSI); + tape.write(ByteCode::LLoad); + tape.write(ByteCode::LNeg); + tape.write(ByteCode::LSaveDP, targetOffset); + break; default: throw InternalError(errFatalError); } @@ -2155,13 +2161,7 @@ inline bool intCopying(BuildNode lastNode) inline bool intOpWithConsts(BuildNode lastNode) { - int size = lastNode.findChild(BuildKey::Size).arg.value; - if (size != 4) - return false; - - BuildNode targetNode = lastNode; - BuildNode tempNode = getPrevious(targetNode); - BuildNode opNode = getPrevious(tempNode); + BuildNode opNode = lastNode; BuildNode savingOp2 = getPrevious(opNode); BuildNode intNode = getPrevious(savingOp2); BuildNode valueNode = intNode.findChild(BuildKey::Value); @@ -2169,25 +2169,20 @@ inline bool intOpWithConsts(BuildNode lastNode) BuildNode sourceNode = getPrevious(savingOp1); int tempTarget = opNode.findChild(BuildKey::Index).arg.value; - if (tempTarget != tempNode.arg.value) - return false; - switch (opNode.arg.value) { case ADD_OPERATOR_ID: case SUB_OPERATOR_ID: savingOp1.setKey(BuildKey::Copying); - savingOp1.setArgumentValue(targetNode.arg.value); + savingOp1.setArgumentValue(tempTarget); savingOp1.appendChild(BuildKey::Size, 4); intNode.setKey(BuildKey::AddingInt); - intNode.setArgumentValue(targetNode.arg.value); + intNode.setArgumentValue(tempTarget); if (opNode.arg.value == SUB_OPERATOR_ID) { // revert the value valueNode.setArgumentValue(-valueNode.arg.value); } savingOp2.setKey(BuildKey::Idle); opNode.setKey(BuildKey::Idle); - tempNode.setKey(BuildKey::Idle); - targetNode.setKey(BuildKey::Idle); break; case MUL_OPERATOR_ID: savingOp1.setKey(BuildKey::LoadingAccToIndex); @@ -2195,25 +2190,20 @@ inline bool intOpWithConsts(BuildNode lastNode) intNode.setKey(BuildKey::IndexOp); intNode.setArgumentValue(opNode.arg.value); savingOp2.setKey(BuildKey::SavingIndex); - savingOp2.setArgumentValue(targetNode.arg.value); + savingOp2.setArgumentValue(tempTarget); opNode.setKey(BuildKey::Idle); - tempNode.setKey(BuildKey::Idle); - targetNode.setKey(BuildKey::Idle); break; case BAND_OPERATOR_ID: case BOR_OPERATOR_ID: case SHL_OPERATOR_ID: case SHR_OPERATOR_ID: setChild(intNode, BuildKey::Source, sourceNode.arg.value); - setChild(intNode, BuildKey::Index, targetNode.arg.value); + setChild(intNode, BuildKey::Index, tempTarget); intNode.setKey(BuildKey::IntConstOp); intNode.setArgumentValue(opNode.arg.value); - targetNode.setKey(BuildKey::Idle); - tempNode.setKey(BuildKey::Idle); opNode.setKey(BuildKey::Idle); savingOp2.setKey(BuildKey::Idle); - targetNode.setKey(BuildKey::Idle); savingOp1.setKey(BuildKey::Idle); sourceNode.setKey(BuildKey::Idle); break; @@ -2224,48 +2214,44 @@ inline bool intOpWithConsts(BuildNode lastNode) return true; } -inline bool intOpWithConsts2(BuildNode lastNode) +inline bool optIntOpWithConsts(BuildNode lastNode) { - BuildNode copyingOp = lastNode; - BuildNode targetNode2 = getPrevious(copyingOp); - BuildNode stackOp = getPrevious(targetNode2); - BuildNode tempOp = getPrevious(stackOp); - BuildNode assigningOp = getPrevious(tempOp); - BuildNode createOp = getPrevious(assigningOp); - BuildNode intOp = getPrevious(createOp); - BuildNode stackOp2 = getPrevious(intOp); - BuildNode intLiteralOp = getPrevious(stackOp2); - BuildNode stackOp3 = getPrevious(intLiteralOp); - BuildNode sourceOp = getPrevious(stackOp3); - - BuildNode valueNode = intLiteralOp.findChild(BuildKey::Value); - BuildNode intOpIndex = intOp.findChild(BuildKey::Index); - - if (targetNode2.arg.reference != assigningOp.arg.reference) - return false; + BuildNode copyNode = lastNode; + BuildNode sourNode = getPrevious(copyNode); + BuildNode opNode = getPrevious(sourNode); + BuildNode sourceCopyNode = getPrevious(opNode); - if (tempOp.arg.reference != intOpIndex.arg.reference) - return false; + if (sourNode.arg.reference == opNode.arg.reference && sourNode.arg.reference == sourceCopyNode.arg.reference) { + opNode.setArgumentReference(copyNode.arg.reference); + sourceCopyNode.setArgumentReference(copyNode.arg.reference); - // !! temporal - exclude div - if (intOp.arg.value == DIV_OPERATOR_ID) - return false; + copyNode.setKey(BuildKey::Idle); + sourNode.setKey(BuildKey::Idle); + + return true; + } + + return false; +} - tempOp.setKey(BuildKey::LoadingIndex); - tempOp.setArgumentReference(sourceOp.arg.reference); +inline bool doubleCopyingIntOp(BuildNode lastNode) +{ + BuildNode copyingOp = lastNode; + BuildNode tempLocalOp = getPrevious(copyingOp); + BuildNode savingIndexOp = getPrevious(tempLocalOp); - stackOp.setKey(BuildKey::IndexOp); - stackOp.setArgumentValue(intOp.arg.value); - stackOp.appendChild(BuildKey::Value, valueNode.arg.value); - copyingOp.setKey(BuildKey::SavingIndexToAcc); + int size = copyingOp.findChild(BuildKey::Size).arg.value; - intOp.setKey(BuildKey::Idle); - stackOp2.setKey(BuildKey::Idle); - intLiteralOp.setKey(BuildKey::Idle); - stackOp3.setKey(BuildKey::Idle); - sourceOp.setKey(BuildKey::Idle); + if (tempLocalOp.arg.reference == savingIndexOp.arg.reference && size == 4) { + savingIndexOp.setArgumentReference(copyingOp.arg.reference); - return true; + copyingOp.setKey(BuildKey::Idle); + tempLocalOp.setKey(BuildKey::Idle); + + return true; + } + + return false; } inline bool assignIntOpWithConsts(BuildNode lastNode) @@ -2601,7 +2587,7 @@ ByteCodeWriter::Transformer transformers[] = { nullptr, duplicateBreakpoints, doubleAssigningByRefHandler, intCopying, intOpWithConsts, assignIntOpWithConsts, boxingInt, nativeBranchingOp, intConstBranchingOp, doubleAssigningConverting, doubleAssigningIntRealOp, - intOpWithConsts2, inplaceCallOp, intConstAssigning, inplaceCallOp2 + doubleCopyingIntOp, inplaceCallOp, intConstAssigning, inplaceCallOp2, optIntOpWithConsts }; // --- ByteCodeWriter --- @@ -3163,7 +3149,8 @@ void ByteCodeWriter :: saveYieldDispatch(CommandTape& tape, BuildNode node, Tape tape.setLabel(); } -inline void saveDebugSymbol(DebugSymbol symbol, int offset, ustr_t name, TapeScope& tapeScope) +inline void saveDebugSymbol(DebugSymbol symbol, int offset, ustr_t name, TapeScope& tapeScope, + ustr_t className = nullptr) { DebugLineInfo info = { symbol }; info.addresses.local.offset = offset; @@ -3172,6 +3159,13 @@ inline void saveDebugSymbol(DebugSymbol symbol, int offset, ustr_t name, TapeSco tapeScope.scope->debugStrings->writeString(name); tapeScope.scope->debug->write(&info, sizeof(info)); + + if (!emptystr(className)) { + DebugLineInfo classInfo = { DebugSymbol::LocalInfo }; + classInfo.addresses.source.nameRef = tapeScope.scope->debugStrings->position(); + tapeScope.scope->debug->write(&classInfo, sizeof(classInfo)); + tapeScope.scope->debugStrings->writeString(className); + } } void ByteCodeWriter :: saveVariableInfo(CommandTape& tape, BuildNode node, TapeScope& tapeScope) @@ -3187,7 +3181,8 @@ void ByteCodeWriter :: saveVariableInfo(CommandTape& tape, BuildNode node, TapeS saveDebugSymbol(DebugSymbol::Local, current.findChild(BuildKey::Index).arg.value, current.identifier(), tapeScope); break; case BuildKey::VariableAddress: - saveDebugSymbol(DebugSymbol::LocalAddress, current.findChild(BuildKey::Index).arg.value, current.identifier(), tapeScope); + saveDebugSymbol(DebugSymbol::LocalAddress, current.findChild(BuildKey::Index).arg.value, current.identifier(), + tapeScope, current.findChild(BuildKey::ClassName).identifier()); break; case BuildKey::IntVariableAddress: saveDebugSymbol(DebugSymbol::IntLocalAddress, current.findChild(BuildKey::Index).arg.value, current.identifier(), tapeScope); @@ -3239,7 +3234,7 @@ inline void saveParameterDebugSymbol(DebugSymbol symbol, int offset, ustr_t name } } -void ByteCodeWriter :: saveParameterInfo(CommandTape& tape, BuildNode node, TapeScope& tapeScope) +void ByteCodeWriter :: saveArgumentsInfo(CommandTape& tape, BuildNode node, TapeScope& tapeScope) { BuildNode current = node.firstChild(); while (current != BuildKey::None) { @@ -3307,9 +3302,9 @@ void ByteCodeWriter :: saveTape(CommandTape& tape, BuildNode node, TapeScope& ta // declaring variables / setting array size saveVariableInfo(tape, current, tapeScope); break; - case BuildKey::ParameterInfo: + case BuildKey::ArgumentsInfo: // declaring variables / setting array size - saveParameterInfo(tape, current, tapeScope); + saveArgumentsInfo(tape, current, tapeScope); break; case BuildKey::MethodName: // declaring variables / setting array size @@ -3442,6 +3437,10 @@ inline bool isNonOperational(BuildKey key) case BuildKey::ByRefOpMark: case BuildKey::InplaceCall: case BuildKey::IntBranchOp: + case BuildKey::CatchOp: + case BuildKey::AltOp: + case BuildKey::LoopOp: + case BuildKey::ShortCircuitOp: return false; case BuildKey::OpenStatement: case BuildKey::EndStatement: diff --git a/elenasrc3/engine/bcwriter.h b/elenasrc3/engine/bcwriter.h index e4092dd033..86c40a7113 100644 --- a/elenasrc3/engine/bcwriter.h +++ b/elenasrc3/engine/bcwriter.h @@ -98,7 +98,7 @@ namespace elena_lang void saveYielding(CommandTape& tape, BuildNode node, TapeScope& tapeScope, ReferenceMap& paths, bool tapeOptMode); void saveYieldDispatch(CommandTape& tape, BuildNode node, TapeScope& tapeScope, ReferenceMap& paths, bool tapeOptMode); void saveVariableInfo(CommandTape& tape, BuildNode node, TapeScope& tapeScope); - void saveParameterInfo(CommandTape& tape, BuildNode node, TapeScope& tapeScope); + void saveArgumentsInfo(CommandTape& tape, BuildNode node, TapeScope& tapeScope); void saveMethodInfo(CommandTape& tape, BuildNode node, TapeScope& tapeScope); void saveProcedure(BuildNode node, Scope& scope, bool classMode, pos_t sourcePathRef, diff --git a/elenasrc3/engine/buildtree.h b/elenasrc3/engine/buildtree.h index 10c252e3a4..2937db4f7a 100644 --- a/elenasrc3/engine/buildtree.h +++ b/elenasrc3/engine/buildtree.h @@ -3,7 +3,7 @@ // // This file contains ELENA Engine Byte code Build Tree classes // -// (C)2021-2023, by Aleksey Rakov +// (C)2021-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #ifndef BUILDTREE_H @@ -194,7 +194,7 @@ namespace elena_lang IntArrayAddress = 0x00B8, UIntVariableAddress = 0x00B9, - ParameterInfo = 0x00C0, + ArgumentsInfo = 0x00C0, Parameter = 0x00C1, IntParameterAddress = 0x00C2, LongParameterAddress = 0x00C3, @@ -278,6 +278,8 @@ namespace elena_lang map.add("int_real_op", BuildKey::IntRealOp); map.add("real_int_op", BuildKey::RealIntOp); map.add("direct_call_op", BuildKey::DirectCallOp); + map.add("addingint", BuildKey::AddingInt); + map.add("saving_index", BuildKey::SavingIndex); } }; diff --git a/elenasrc3/engine/bytecode.cpp b/elenasrc3/engine/bytecode.cpp index 18c2c8f410..fb7b4c5dbd 100644 --- a/elenasrc3/engine/bytecode.cpp +++ b/elenasrc3/engine/bytecode.cpp @@ -3,7 +3,7 @@ // // This file contains common ELENA byte code classes and constants // -// (C)2021-2023, by Aleksey Rakov +// (C)2021-2024, by Aleksey Rakov //------------------------------------------------------------------------------ #include "bytecode.h" @@ -17,8 +17,8 @@ const char* _fnOpcodes[256] = "nop", "breakpoint", "snop", "redirect", "quit", "mov env", "load", "len", "class", "save", "throw", "unhook", "loadv", "xcmp", "bload", "wload", - "incude", "exclude", "assign", "mov frm", "loads", "mlen", "dalloc", "tststck", - "dtrans", "xassign", "lload", "convl", "xlcmp", "xload", "xlload", OPCODE_UNKNOWN, + "exclude", "incude", "assign", "mov frm", "loads", "mlen", "dalloc", "tststck", + "dtrans", "xassign", "lload", "convl", "xlcmp", "xload", "xlload", "lneg", "coalesce", "not", "neg", "bread", "lsave", "fsave", "wread", "xjump", "bcopy", "wcopy", "xpeekeq", "trylock", "freelock", OPCODE_UNKNOWN, "xget", "xcall", diff --git a/elenasrc3/engine/bytecode.h b/elenasrc3/engine/bytecode.h index 3808f3a0f9..b23bbeaca0 100644 --- a/elenasrc3/engine/bytecode.h +++ b/elenasrc3/engine/bytecode.h @@ -3,7 +3,7 @@ // // This file contains common ELENA byte code classes and constants // -// (C)2021-2023, by Aleksey Rakov +// (C)2021-2024, by Aleksey Rakov //------------------------------------------------------------------------------ #ifndef BYTECODE_H @@ -50,6 +50,7 @@ namespace elena_lang XLCmp = 0x1C, XLoad = 0x1D, XLLoad = 0x1E, + LNeg = 0x1F, Coalesce = 0x20, Not = 0x21, diff --git a/elenasrc3/engine/elena.h b/elenasrc3/engine/elena.h index 85b3771289..c31895cf0c 100644 --- a/elenasrc3/engine/elena.h +++ b/elenasrc3/engine/elena.h @@ -430,6 +430,7 @@ namespace elena_lang { public: virtual void info(int code, ustr_t arg) = 0; + virtual void info(int code, ustr_t arg, ustr_t arg2) = 0; virtual void raiseInternalError(int code) = 0; virtual void raiseError(int code, ustr_t arg) = 0; diff --git a/elenasrc3/engine/elenaconst.h b/elenasrc3/engine/elenaconst.h index b883dbe86b..cccad9f9d1 100644 --- a/elenasrc3/engine/elenaconst.h +++ b/elenasrc3/engine/elenaconst.h @@ -302,6 +302,7 @@ namespace elena_lang ParameterInfo = 0x0302, MessageInfo = 0x0303, FieldInfo = 0x0304, + LocalInfo = 0x0305, }; // --- ClassAttribute --- diff --git a/elenasrc3/engine/elenamachine.cpp b/elenasrc3/engine/elenamachine.cpp index bc4e26fb66..6092790adb 100644 --- a/elenasrc3/engine/elenamachine.cpp +++ b/elenasrc3/engine/elenamachine.cpp @@ -81,6 +81,8 @@ void SystemRoutineProvider :: Init(SystemEnv* env, SystemSettings settings) void SystemRoutineProvider :: InitSTA(SystemEnv* env) { + + SystemSettings settings; FillSettings(env, settings); diff --git a/elenasrc3/engine/jitcompiler.cpp b/elenasrc3/engine/jitcompiler.cpp index 364493ce77..81392e3460 100644 --- a/elenasrc3/engine/jitcompiler.cpp +++ b/elenasrc3/engine/jitcompiler.cpp @@ -22,7 +22,7 @@ CodeGenerator _codeGenerators[256] = loadOp, loadOp, loadOp, loadOp, loadOp, loadOp, loadOp, loadOp, loadOp, loadOp, loadOp, loadOp, loadOp, loadOp, loadOp, loadOp, - loadOp, loadOp, loadOp, loadOp, loadOp, loadOp, loadOp, loadNop, + loadOp, loadOp, loadOp, loadOp, loadOp, loadOp, loadOp, loadOp, loadOp, loadOp, loadOp, loadOp, loadOp, loadOp, loadOp, loadOp, loadOp, loadOp, loadOp, loadOp, loadOp, loadNop, loadOp, loadOp, @@ -90,7 +90,7 @@ constexpr ref_t coreFunctions[coreFunctionNumber] = }; // preloaded bc commands -constexpr size_t bcCommandNumber = 173; +constexpr size_t bcCommandNumber = 174; constexpr ByteCode bcCommands[bcCommandNumber] = { ByteCode::MovEnv, ByteCode::SetR, ByteCode::SetDP, ByteCode::CloseN, ByteCode::AllocI, @@ -127,7 +127,7 @@ constexpr ByteCode bcCommands[bcCommandNumber] = ByteCode::FISub,ByteCode::FIMul,ByteCode::FIDiv, ByteCode::SNop, ByteCode::TstStck, ByteCode::Shl, ByteCode::Shr, ByteCode::XLabelDPR, ByteCode::TryLock, ByteCode::FreeLock, ByteCode::XQuit, ByteCode::ExtCloseN, ByteCode::XCmpSI, ByteCode::LoadSI, ByteCode::XFSave, - ByteCode::XSaveN, ByteCode::XSaveDispN, ByteCode::XStoreFIR + ByteCode::XSaveN, ByteCode::XSaveDispN, ByteCode::XStoreFIR, ByteCode::LNeg }; void elena_lang :: writeCoreReference(JITCompilerScope* scope, ref_t reference, @@ -591,10 +591,9 @@ void elena_lang :: loadNOp(JITCompilerScope* scope) scope->compiler->writeImm16(writer, scope->command.arg1 & 0xFFFF, 0); break; default: - // to make compiler happy + writeCoreReference(scope, entries->reference, entries->offset, code); break; } - //else writeCoreReference(); entries++; count--; @@ -3009,6 +3008,9 @@ void JITCompiler :: writeDump(ReferenceHelperBase* helper, MemoryWriter& writer, writer.align(4, 0); + if (!section->getReferences()) + return; + for (auto it = RelocationMap::Iterator(section->getReferences()); !it.eof(); ++it) { pos_t imageOffset = *it + position; diff --git a/elenasrc3/engine/jitcompiler.h b/elenasrc3/engine/jitcompiler.h index 950c50f778..feea4bf571 100644 --- a/elenasrc3/engine/jitcompiler.h +++ b/elenasrc3/engine/jitcompiler.h @@ -242,7 +242,7 @@ namespace elena_lang protected: int calcFrameOffset(int argument, bool extMode) override { - return (extMode ? 16 : 4) + (argument > 0 ? align(argument + 8, 4) : 0); + return (extMode ? 20 : 4) + (argument > 0 ? align(argument + 8, 4) : 0); } int calcTotalSize(int numberOfFields) override; diff --git a/elenasrc3/engine/jitlinker.cpp b/elenasrc3/engine/jitlinker.cpp index caa6095337..b07fc540f3 100644 --- a/elenasrc3/engine/jitlinker.cpp +++ b/elenasrc3/engine/jitlinker.cpp @@ -1446,9 +1446,9 @@ void JITLinker :: copyMetaList(ModuleInfo info, ModuleInfoList& output) } } -void JITLinker :: prepare(JITCompilerBase* compiler) +void JITLinker :: prepare() { - setCompiler(compiler); + assert(_compiler != nullptr); _withDebugInfo = _compiler->isWithDebugInfo(); diff --git a/elenasrc3/engine/jitlinker.h b/elenasrc3/engine/jitlinker.h index be1476d08c..8ff942322d 100644 --- a/elenasrc3/engine/jitlinker.h +++ b/elenasrc3/engine/jitlinker.h @@ -238,7 +238,7 @@ namespace elena_lang ref_t resolveAction(ustr_t actionName); void loadPreloaded(ustr_t preloadedSection); - void prepare(JITCompilerBase* compiler); + void prepare(); void setCompiler(JITCompilerBase* compiler) { _compiler = compiler; diff --git a/elenasrc3/engine/langcommon.h b/elenasrc3/engine/langcommon.h index 8462752288..096ea647c8 100644 --- a/elenasrc3/engine/langcommon.h +++ b/elenasrc3/engine/langcommon.h @@ -3,7 +3,7 @@ // // This file contains the language common constants // -// (C)2021-2023, by Aleksey Rakov +// (C)2021-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #ifndef LANGCOMMON_H @@ -156,6 +156,7 @@ namespace elena_lang constexpr auto infoUnknownMessage = 706; constexpr auto infoTargetClass = 707; constexpr auto infoScopeMethod = 708; + constexpr auto infoExptectedType = 709; constexpr auto errVMBroken = 800; constexpr auto errVMNotInitialized = 801; @@ -405,6 +406,7 @@ namespace elena_lang constexpr auto CONFIG_ROOT = "configuration"; constexpr auto PLATFORM_CATEGORY = "configuration/platform"; + constexpr auto TEMPLATE_CATEGORY = "templates/*"; constexpr auto PRIMITIVE_CATEGORY = "primitives/*"; constexpr auto FORWARD_CATEGORY = "forwards/*"; @@ -414,6 +416,7 @@ namespace elena_lang constexpr auto MODULE_CATEGORY = "files/*"; constexpr auto FILE_CATEGORY = "include/*"; constexpr auto PARSER_TARGET_CATEGORY = "targets/*"; + constexpr auto PROFILE_CATEGORY = "/profile"; constexpr auto LIB_PATH = "project/libpath"; constexpr auto OUTPUT_PATH = "project/output"; @@ -476,11 +479,11 @@ namespace elena_lang map.add("script_method", V_SCRIPTSELFMODE); map.add("public_namespace", V_PUBLIC); map.add("script_function", V_SCRIPTSELFMODE); + map.add("script_function", V_FUNCTION); map.add("public_symbol", V_PUBLIC); - //map.add("script_function", V_FUNCTION); map.add("new_variable", V_VARIABLE); map.add("new_identifier", V_NEWOP); - //map.add("prev_identifier", V_PREVIOUS); + map.add("super_identifier", V_SUPERIOR); //map.add("loop_expression", V_LOOP); } }; diff --git a/elenasrc3/engine/syntaxtree.cpp b/elenasrc3/engine/syntaxtree.cpp index 7526938761..857c38eb2f 100644 --- a/elenasrc3/engine/syntaxtree.cpp +++ b/elenasrc3/engine/syntaxtree.cpp @@ -3,7 +3,7 @@ // // This file contains Syntax Tree class implementation // -// (C)2021-2023, by Aleksey Rakov +// (C)2021-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #include "elena.h" @@ -61,10 +61,10 @@ void SyntaxTree :: loadTokens(TokenMap& map) // tokens.add("preloaded_symbol", lxSymbol); map.add("literal", SyntaxKey::string); map.add("identifier", SyntaxKey::identifier); + map.add("super_identifier", SyntaxKey::identifier); map.add("character", SyntaxKey::character); // tokens.add("variable_identifier", lxIdentifier); // tokens.add("new_identifier", lxIdentifier); - // tokens.add("prev_identifier", lxIdentifier); map.add("integer", SyntaxKey::integer); map.add("parameter", SyntaxKey::Parameter); //// tokens.add("include", lxInclude); diff --git a/elenasrc3/engine/windows/winroutines.cpp b/elenasrc3/engine/windows/winroutines.cpp index 85626c7c75..a1805ab08c 100644 --- a/elenasrc3/engine/windows/winroutines.cpp +++ b/elenasrc3/engine/windows/winroutines.cpp @@ -119,6 +119,9 @@ LONG WINAPI ELENAVectoredHandler(struct _EXCEPTION_POINTERS* ExceptionInfo) ExceptionInfo->ContextRecord->Eax = ELENA_ERR_STACKOVERFLOW; ExceptionInfo->ContextRecord->Eip = CriticalHandler; return EXCEPTION_CONTINUE_EXECUTION; + case 0x000006ba: + // !! HOTFIX : temporally ignore + return EXCEPTION_CONTINUE_SEARCH; default: if (ExceptionInfo->ExceptionRecord->ExceptionCode < 0xE0000000) { ExceptionInfo->ContextRecord->Edx = ExceptionInfo->ContextRecord->Eip; diff --git a/elenasrc3/engine/xmlprojectbase.cpp b/elenasrc3/engine/xmlprojectbase.cpp index 673132f352..e70c00170b 100644 --- a/elenasrc3/engine/xmlprojectbase.cpp +++ b/elenasrc3/engine/xmlprojectbase.cpp @@ -3,7 +3,7 @@ // // This file contains the xml project base class implementation // -// (C)2021-2023, by Aleksey Rakov +// (C)2021-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #include "xmlprojectbase.h" @@ -98,6 +98,16 @@ ConfigFile::Node XmlProjectBase :: getPlatformRoot(ConfigFile& config, PlatformT return platformRoot; } +ConfigFile::Node XmlProjectBase :: getProfileRoot(ConfigFile& config, ConfigFile::Node& root, ustr_t profileName) +{ + ConfigFile::Node profileRoot = config.selectNode(root, PROFILE_CATEGORY, profileName, [](ustr_t key, ConfigFile::Node& node) + { + return node.compareAttribute("key", key); + }); + + return profileRoot; +} + void XmlProjectBase :: loadPathCollection(ConfigFile& config, ConfigFile::Node& configRoot, ustr_t xpath, ProjectOption collectionKey, path_t configPath) { diff --git a/elenasrc3/engine/xmlprojectbase.h b/elenasrc3/engine/xmlprojectbase.h index 6910b2ef6a..798299eef9 100644 --- a/elenasrc3/engine/xmlprojectbase.h +++ b/elenasrc3/engine/xmlprojectbase.h @@ -3,7 +3,7 @@ // // This file contains the xml project base class declaration // -// (C)2021-2023, by Aleksey Rakov +// (C)2021-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #ifndef XMLPROJECTBASE_H @@ -194,6 +194,7 @@ namespace elena_lang ProjectNode _root; ConfigFile::Node getPlatformRoot(ConfigFile& config, PlatformType platform); + ConfigFile::Node getProfileRoot(ConfigFile& config, ConfigFile::Node& root, ustr_t profileName); void loadKeyCollection(ConfigFile& config, ConfigFile::Node& root, ustr_t xpath, ProjectOption collectionKey, ProjectOption itemKey, ustr_t prefix); diff --git a/elenasrc3/gui/controller.cpp b/elenasrc3/gui/controller.cpp index 57311c3603..226f0fdee2 100644 --- a/elenasrc3/gui/controller.cpp +++ b/elenasrc3/gui/controller.cpp @@ -11,11 +11,6 @@ using namespace elena_lang; // --- TextViewController --- -//void TextViewController :: onFrameChange() -//{ -// -//} - void TextViewController :: newDocument(TextViewModelBase* model, ustr_t name) { Text* text = new Text(_settings.eolMode); @@ -58,20 +53,15 @@ void TextViewController :: selectPreviousDocument(TextViewModelBase* model) model->selectDocumentView(currentIndex); } -bool TextViewController :: selectDocument(TextViewModelBase* model, int index, NotificationStatus& status) +bool TextViewController :: selectDocument(TextViewModelBase* model, int index) { - if (model->selectDocumentView(index)) { - status |= FRAME_CHANGED; - - return true; - } - return false; + return model->selectDocumentView(index); } -void TextViewController :: closeDocument(TextViewModelBase* model, int index, NotificationStatus& status) +void TextViewController :: closeDocument(TextViewModelBase* model, int index, int& status) { if (model->closeDocumentView(index)) - status |= FRAME_CHANGED; + status |= STATUS_FRAME_CHANGED; } void TextViewController :: indent(TextViewModelBase* model) @@ -90,7 +80,7 @@ void TextViewController :: indent(TextViewModelBase* model) else docView->tabbing(status, ' ', _settings.tabSize, true); } - notifyOnChange(model, status); + notifyTextModelChange(model, status); } void TextViewController :: outdent(TextViewModelBase* model) @@ -105,17 +95,19 @@ void TextViewController :: outdent(TextViewModelBase* model) docView->tabbing(status, ' ', _settings.tabSize, false); } - notifyOnChange(model, status); + notifyTextModelChange(model, status); } void TextViewController :: undo(TextViewModelBase* model) { DocumentChangeStatus status = {}; auto docView = model->DocView(); + if (docView->isReadOnly()) + return; docView->undo(status); - notifyOnChange(model, status); + notifyTextModelChange(model, status); } void TextViewController :: redo(TextViewModelBase* model) @@ -124,8 +116,10 @@ void TextViewController :: redo(TextViewModelBase* model) auto docView = model->DocView(); docView->redo(status); + if (docView->isReadOnly()) + return; - notifyOnChange(model, status); + notifyTextModelChange(model, status); } bool TextViewController :: copyToClipboard(TextViewModelBase* model, ClipboardBase* clipboard) @@ -155,7 +149,7 @@ void TextViewController :: pasteFromClipboard(TextViewModelBase* model, Clipboar if (!docView->isReadOnly()) { clipboard->pasteFromClipboard(status, docView); - notifyOnChange(model, status); + notifyTextModelChange(model, status); } } @@ -167,7 +161,7 @@ bool TextViewController :: insertNewLine(TextViewModelBase* model) docView->eraseSelection(status); docView->insertNewLine(status); - notifyOnChange(model, status); + notifyTextModelChange(model, status); return true; } @@ -183,7 +177,7 @@ bool TextViewController :: insertChar(TextViewModelBase* model, text_c ch) docView->eraseSelection(status); docView->insertChar(status, ch); - notifyOnChange(model, status); + notifyTextModelChange(model, status); return true; } @@ -201,7 +195,7 @@ bool TextViewController :: eraseChar(TextViewModelBase* model, bool moveback) } else docView->eraseChar(status, moveback); - notifyOnChange(model, status); + notifyTextModelChange(model, status); return true; } @@ -217,7 +211,7 @@ void TextViewController :: deleteText(TextViewModelBase* model) docView->eraseSelection(status); } - notifyOnChange(model, status); + notifyTextModelChange(model, status); } void TextViewController :: trim(TextViewModelBase* model) @@ -228,7 +222,7 @@ void TextViewController :: trim(TextViewModelBase* model) docView->trim(status); } - notifyOnChange(model, status); + notifyTextModelChange(model, status); } void TextViewController :: eraseLine(TextViewModelBase* model) @@ -239,7 +233,7 @@ void TextViewController :: eraseLine(TextViewModelBase* model) docView->eraseLine(status); } - notifyOnChange(model, status); + notifyTextModelChange(model, status); } void TextViewController :: duplicateLine(TextViewModelBase* model) @@ -250,7 +244,7 @@ void TextViewController :: duplicateLine(TextViewModelBase* model) docView->duplicateLine(status); } - notifyOnChange(model, status); + notifyTextModelChange(model, status); } void TextViewController :: insertBlockText(TextViewModelBase* model, const_text_t s, size_t length) @@ -261,7 +255,7 @@ void TextViewController :: insertBlockText(TextViewModelBase* model, const_text_ docView->blockInserting(status, s, length); } - notifyOnChange(model, status); + notifyTextModelChange(model, status); } void TextViewController :: deleteBlockText(TextViewModelBase* model, const_text_t s, size_t length) @@ -272,7 +266,7 @@ void TextViewController :: deleteBlockText(TextViewModelBase* model, const_text_ docView->blockDeleting(status, s, length); } - notifyOnChange(model, status); + notifyTextModelChange(model, status); } void TextViewController :: lowerCase(TextViewModelBase* model) @@ -283,7 +277,7 @@ void TextViewController :: lowerCase(TextViewModelBase* model) docView->toLowercase(status); } - notifyOnChange(model, status); + notifyTextModelChange(model, status); } void TextViewController :: upperCase(TextViewModelBase* model) @@ -294,7 +288,7 @@ void TextViewController :: upperCase(TextViewModelBase* model) docView->toUppercase(status); } - notifyOnChange(model, status); + notifyTextModelChange(model, status); } void TextViewController :: moveCaretDown(TextViewModelBase* model, bool kbShift, bool kbCtrl) @@ -307,7 +301,7 @@ void TextViewController :: moveCaretDown(TextViewModelBase* model, bool kbShift, } else docView->moveDown(status, kbShift); - notifyOnChange(model, status); + notifyTextModelChange(model, status); } void TextViewController :: moveCaretLeft(TextViewModelBase* model, bool kbShift, bool kbCtrl) @@ -320,7 +314,7 @@ void TextViewController :: moveCaretLeft(TextViewModelBase* model, bool kbShift, } else docView->moveLeft(status, kbShift); - notifyOnChange(model, status); + notifyTextModelChange(model, status); } void TextViewController :: selectWord(TextViewModelBase* model) @@ -331,7 +325,7 @@ void TextViewController :: selectWord(TextViewModelBase* model) docView->moveLeftToken(status, false); docView->moveRightToken(status, true, true); - notifyOnChange(model, status); + notifyTextModelChange(model, status); } void TextViewController::selectAll(TextViewModelBase* model) @@ -342,17 +336,23 @@ void TextViewController::selectAll(TextViewModelBase* model) docView->moveFirst(status, false); docView->moveEnd(status, true); - notifyOnChange(model, status); + notifyTextModelChange(model, status); } -void TextViewController :: notifyOnChange(TextViewModelBase* model, DocumentChangeStatus& changeStatus) +void TextViewController :: notifyOnClipboardOperation(ClipboardBase* clipboard) { - model->notifyOnChange(changeStatus); + } -void TextViewController :: notifyOnClipboardOperation(ClipboardBase* clipboard) +void TextViewController :: notifyTextModelChange(TextViewModelBase* model, DocumentChangeStatus& changeStatus) { - + model->refresh(changeStatus); + + if (!_notifier) + return; + + TextViewModelEvent event = { STATUS_DOC_READY, changeStatus }; + _notifier->notify(&event); } void TextViewController :: moveCaretRight(TextViewModelBase* model, bool kbShift, bool kbCtrl) @@ -365,7 +365,7 @@ void TextViewController :: moveCaretRight(TextViewModelBase* model, bool kbShift } else docView->moveRight(status, kbShift); - notifyOnChange(model, status); + notifyTextModelChange(model, status); } void TextViewController :: moveCaretUp(TextViewModelBase* model, bool kbShift, bool kbCtrl) @@ -378,7 +378,7 @@ void TextViewController :: moveCaretUp(TextViewModelBase* model, bool kbShift, b } else docView->moveFrameUp(status); - notifyOnChange(model, status); + notifyTextModelChange(model, status); } void TextViewController :: moveCaretHome(TextViewModelBase* model, bool kbShift, bool kbCtrl) @@ -391,7 +391,7 @@ void TextViewController :: moveCaretHome(TextViewModelBase* model, bool kbShift, } else docView->moveHome(status, kbShift); - notifyOnChange(model, status); + notifyTextModelChange(model, status); } void TextViewController :: moveCaretEnd(TextViewModelBase* model, bool kbShift, bool kbCtrl) @@ -404,7 +404,7 @@ void TextViewController :: moveCaretEnd(TextViewModelBase* model, bool kbShift, } else docView->moveLast(status, kbShift); - notifyOnChange(model, status); + notifyTextModelChange(model, status); } void TextViewController :: movePageDown(TextViewModelBase* model, bool kbShift) @@ -414,7 +414,7 @@ void TextViewController :: movePageDown(TextViewModelBase* model, bool kbShift) docView->movePageDown(status, kbShift); - notifyOnChange(model, status); + notifyTextModelChange(model, status); } void TextViewController :: movePageUp(TextViewModelBase* model, bool kbShift) @@ -424,7 +424,7 @@ void TextViewController :: movePageUp(TextViewModelBase* model, bool kbShift) docView->movePageUp(status, kbShift); - notifyOnChange(model, status); + notifyTextModelChange(model, status); } void TextViewController :: moveToFrame(TextViewModelBase* model, int col, int row, bool kbShift) @@ -434,7 +434,7 @@ void TextViewController :: moveToFrame(TextViewModelBase* model, int col, int ro docView->moveToFrame(status, col, row, kbShift); - notifyOnChange(model, status); + notifyTextModelChange(model, status); } void TextViewController :: resizeModel(TextViewModelBase* model, Point size) @@ -448,7 +448,7 @@ void TextViewController :: resizeModel(TextViewModelBase* model, Point size) status.frameChanged = true; } - notifyOnChange(model, status); + //notifyTextModelChange(model, status); } bool TextViewController :: findText(TextViewModelBase* model, FindModel* findModel) @@ -459,7 +459,7 @@ bool TextViewController :: findText(TextViewModelBase* model, FindModel* findMod if (docView && docView->findLine(docStatus, findModel->text.str(), findModel->matchCase, findModel->wholeWord)) { - notifyOnChange(model, docStatus); + notifyTextModelChange(model, docStatus); return true; } @@ -472,9 +472,9 @@ bool TextViewController :: replaceText(TextViewModelBase* model, FindModel* find DocumentChangeStatus docStatus = {}; auto docView = model->DocView(); - if (docView) { + if (docView && !docView->isReadOnly()) { docView->insertLine(docStatus, findModel->newText.str(), findModel->newText.length()); - notifyOnChange(model, docStatus); + notifyTextModelChange(model, docStatus); return true; } @@ -493,6 +493,6 @@ void TextViewController :: goToLine(TextViewModelBase* model, int row) caret.y = row - 1; docView->setCaret(caret, false, docStatus); - notifyOnChange(model, docStatus); + notifyTextModelChange(model, docStatus); } } diff --git a/elenasrc3/gui/controller.h b/elenasrc3/gui/controller.h index 92e25103df..93fe535a69 100644 --- a/elenasrc3/gui/controller.h +++ b/elenasrc3/gui/controller.h @@ -89,19 +89,25 @@ namespace elena_lang { protected: TextViewSettings _settings; + NotifierBase* _notifier; //void onTextChanged(TextViewModelBase* model, DocumentView* view); - void notifyOnChange(TextViewModelBase* model, DocumentChangeStatus& status); - void notifyOnClipboardOperation(ClipboardBase* clipboard); + void notifyOnClipboardOperation(ClipboardBase* clipboard); // !! obsolete + void notifyTextModelChange(TextViewModelBase* model, DocumentChangeStatus& changeStatus); public: + void setNotifier(NotifierBase* notifier) + { + _notifier = notifier; + } + bool openDocument(TextViewModelBase* model, ustr_t name, path_t path, FileEncoding encoding) override; - bool selectDocument(TextViewModelBase* model, int index, NotificationStatus& status) override; + bool selectDocument(TextViewModelBase* model, int index) override; void selectNextDocument(TextViewModelBase* model); void selectPreviousDocument(TextViewModelBase* model); - void closeDocument(TextViewModelBase* model, int index, NotificationStatus& status) override; + void closeDocument(TextViewModelBase* model, int index, int& status) override; void newDocument(TextViewModelBase* model, ustr_t name) override; @@ -147,7 +153,7 @@ namespace elena_lang bool findText(TextViewModelBase* model, FindModel* findModel); bool replaceText(TextViewModelBase* model, FindModel* findModel); - void goToLine(TextViewModelBase* model, int row); + void goToLine(TextViewModelBase* model, int row); TextViewController(TextViewSettings& settings) { diff --git a/elenasrc3/gui/document.cpp b/elenasrc3/gui/document.cpp index 0999f5280b..4468f7cc9d 100644 --- a/elenasrc3/gui/document.cpp +++ b/elenasrc3/gui/document.cpp @@ -230,7 +230,6 @@ bool DocumentView::LexicalReader :: readNext(TextWriter& writer, pos_t l DocumentView :: DocumentView(Text* text, TextFormatterBase* formatter) : _undoBuffer(UNDO_BUFFER_SIZE), _formatter(text, formatter, &_markers), - _notifiers(nullptr), _markers({}) { _text = text; @@ -639,16 +638,12 @@ void DocumentView :: movePageUp(DocumentChangeStatus& changeStatus, bool selecti } } -void DocumentView :: notifyOnChange(DocumentChangeStatus& changeStatus) +void DocumentView :: refresh(DocumentChangeStatus& changeStatus) { if (status.oldModified != status.modifiedMode) { changeStatus.modifiedChanged = true; status.oldModified = status.modifiedMode; } - - for(auto it = _notifiers.start(); !it.eof(); ++it) { - (*it)->onDocumentUpdate(changeStatus); - } } void DocumentView :: blockInserting(DocumentChangeStatus& changeStatus, const_text_t subs, size_t length) @@ -1048,9 +1043,6 @@ void DocumentView :: save(path_t path) status.modifiedMode = false; status.unnamed = false; - - DocumentChangeStatus changeStatus = {}; - notifyOnChange(changeStatus); } bool DocumentView :: canRedo() diff --git a/elenasrc3/gui/document.h b/elenasrc3/gui/document.h index f90a77fba4..ae16d479b0 100644 --- a/elenasrc3/gui/document.h +++ b/elenasrc3/gui/document.h @@ -103,6 +103,7 @@ namespace elena_lang bool formatterChanged; bool textChanged; bool modifiedChanged; + bool readOnlyChanged; bool isViewChanged() { @@ -120,6 +121,7 @@ namespace elena_lang selelectionChanged = false; formatterChanged = false; textChanged = false; + readOnlyChanged = false; } DocumentChangeStatus() @@ -235,7 +237,6 @@ namespace elena_lang int _maxColumn; MarkerList _markers; - DocumentNotifiers _notifiers; pos_t format(LexicalReader& reader); @@ -248,16 +249,6 @@ namespace elena_lang void setCaret(int column, int row, bool selecting, DocumentChangeStatus& changeStatus); public: - void attachNotifier(DocumentNotifier* notifier) - { - _notifiers.add(notifier); - } - - void removeNotifier(DocumentNotifier* notifier) - { - _notifiers.cut(notifier); - } - void addMarker(int row, pos_t style, bool instanteMode, bool togleMark, DocumentChangeStatus& changeStatus) { _markers.add(row, { style, togleMark }); @@ -295,6 +286,10 @@ namespace elena_lang { setCaret(caret.x, caret.y, selecting, changeStatus); } + void setReadOnlyMode(bool mode) + { + status.readOnly = mode; + } int getRowCount() const { return _text->getRowCount(); } int getMaxColumn() const { return _maxColumn; } @@ -378,7 +373,7 @@ namespace elena_lang void save(path_t path); - void notifyOnChange(DocumentChangeStatus& changeStatus); + void refresh(DocumentChangeStatus& changeStatus); bool findLine(DocumentChangeStatus& changeStatus, const_text_t text, bool matchCase, bool wholeWord); diff --git a/elenasrc3/gui/guicommon.h b/elenasrc3/gui/guicommon.h index 18c7152700..2bd89bf8c7 100644 --- a/elenasrc3/gui/guicommon.h +++ b/elenasrc3/gui/guicommon.h @@ -33,9 +33,6 @@ namespace elena_lang #endif - // --- Misc types - typedef unsigned int NotificationStatus; - // --- Point --- struct Point { @@ -167,21 +164,31 @@ namespace elena_lang }; // --- NotifierBase --- + class EventBase + { + public: + int status; + + virtual int eventId() = 0; + + EventBase(int status) + : status(status) + { + + } + }; + class NotifierBase { public: - virtual void notify(int id, NotificationStatus status) = 0; - virtual void notifySelection(int id, size_t param) = 0; - virtual void notifyTreeItem(int id, size_t item, size_t param) = 0; - virtual void notifyCompletion(int id, int param) = 0; - virtual void notifyContextMenu(int id, short x, short y, bool hasSelection) = 0; + virtual void notify(EventBase* event) = 0; }; // --- GUIApp --- class GUIApp : public NotifierBase { public: - virtual int run(GUIControlBase* mainWindow, bool maximized, int notificationId, NotificationStatus notificationStatus) = 0; + virtual int run(GUIControlBase* mainWindow, bool maximized, EventBase* startEvent) = 0; virtual ~GUIApp() = default; }; diff --git a/elenasrc3/gui/guieditor.h b/elenasrc3/gui/guieditor.h index 64012dd5c1..1cd50ae47a 100644 --- a/elenasrc3/gui/guieditor.h +++ b/elenasrc3/gui/guieditor.h @@ -91,14 +91,8 @@ namespace elena_lang return _currentView; } - virtual void beforeDocumentSelect(int index) = 0; - //virtual void afterDocumentSelect(int index) = 0; - virtual void attachListener(TextViewListener* listener) = 0; - virtual void attachDocListener(DocumentNotifier* listener) = 0; - virtual void removeDocListener(DocumentNotifier* listener) = 0; - virtual void addDocumentView(ustr_t name, Text* text, path_t path) = 0; virtual void renameDocumentView(ustr_t oldName, ustr_t newName, path_t path) = 0; @@ -116,14 +110,15 @@ namespace elena_lang virtual void resize(Point size) = 0; - virtual void notifyOnChange(DocumentChangeStatus& status) + bool isAssigned() const { - _currentView->notifyOnChange(status); + return _currentView != nullptr; } - bool isAssigned() const + virtual void refresh(DocumentChangeStatus& changeStatus) { - return _currentView != nullptr; + if (_currentView) + _currentView->refresh(changeStatus); } TextViewModelBase() @@ -144,9 +139,9 @@ namespace elena_lang virtual bool openDocument(TextViewModelBase* model, ustr_t name, path_t path, FileEncoding encoding) = 0; - virtual bool selectDocument(TextViewModelBase* model, int index, NotificationStatus& status) = 0; + virtual bool selectDocument(TextViewModelBase* model, int index) = 0; - virtual void closeDocument(TextViewModelBase* model, int index, NotificationStatus& status) = 0; + virtual void closeDocument(TextViewModelBase* model, int index, int& status) = 0; virtual bool insertNewLine(TextViewModelBase* model) = 0; virtual bool insertChar(TextViewModelBase* model, text_c ch) = 0; diff --git a/elenasrc3/gui/view.cpp b/elenasrc3/gui/view.cpp index 71c96249a8..5f41b1a0c0 100644 --- a/elenasrc3/gui/view.cpp +++ b/elenasrc3/gui/view.cpp @@ -68,24 +68,6 @@ void TextViewModel :: attachListener(TextViewListener* listener) listener->onDocumentSelect(selected); } -void TextViewModel::attachDocListener(DocumentNotifier* listener) -{ - _docListeners.add(listener); - - for (auto it = _documents.start(); !it.eof(); ++it) { - (*it)->documentView->attachNotifier(listener); - } -} - -void TextViewModel :: removeDocListener(DocumentNotifier* listener) -{ - for (auto it = _documents.start(); !it.eof(); ++it) { - (*it)->documentView->removeNotifier(listener); - } - - _docListeners.cut(listener); -} - void TextViewModel :: onDocumentNew(int index) { for (auto it = _listeners.start(); !it.eof(); ++it) { @@ -160,10 +142,6 @@ void TextViewModel :: addDocumentView(ustr_t name, Text* text, path_t path) docView->markAsModified(); } - for (auto it = _docListeners.start(); !it.eof(); ++it) { - docView->attachNotifier(*it); - } - onDocumentNew(_documents.count()); } diff --git a/elenasrc3/gui/view.h b/elenasrc3/gui/view.h index 548b3d6177..7cf2f377a0 100644 --- a/elenasrc3/gui/view.h +++ b/elenasrc3/gui/view.h @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------- // E L E N A P r o j e c t: ELENA IDE // IDE View class header File -// (C)2021-2022, by Aleksey Rakov +// (C)2021-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #ifndef VIEW_H @@ -55,13 +55,8 @@ namespace elena_lang void onDocumentClose(int index); public: - //void afterDocumentSelect(int index) override; - void attachListener(TextViewListener* listener) override; - void attachDocListener(DocumentNotifier* listener) override; - void removeDocListener(DocumentNotifier* listener) override; - void addDocumentView(ustr_t name, Text* text, path_t path) override; void renameDocumentView(ustr_t oldName, ustr_t newName, path_t path) override; @@ -86,6 +81,28 @@ namespace elena_lang void resize(Point size) override; + bool isAnyDocumentModified() + { + auto it = _documents.start(); + while (!it.eof()) { + if ((*it)->documentView->isModified()) + return true; + + it++; + } + return false; + } + + void setReadOnlyMode(bool mode) + { + auto it = _documents.start(); + while (!it.eof()) { + (*it)->documentView->setReadOnlyMode(mode); + + it++; + } + } + TextViewModel(); virtual ~TextViewModel() = default; }; diff --git a/elenasrc3/gui/windows/wincommon.cpp b/elenasrc3/gui/windows/wincommon.cpp index 4b7278e2a8..4848d6cf11 100644 --- a/elenasrc3/gui/windows/wincommon.cpp +++ b/elenasrc3/gui/windows/wincommon.cpp @@ -1,13 +1,33 @@ //--------------------------------------------------------------------------- // E L E N A P r o j e c t: ELENA IDE // WinAPI Common Body File -// (C)2021-2022, by Aleksey Rakov +// (C)2021-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #include "wincommon.h" using namespace elena_lang; +// --- DateTime --- + +DateTime DateTime::getFileTime(const wchar_t* path) +{ + DateTime dt; + + HANDLE hFile = ::CreateFile(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); + if (hFile) { + FILETIME ftCreate, ftAccess, ftWrite; + + if (::GetFileTime(hFile, &ftCreate, &ftAccess, &ftWrite)) { + FileTimeToSystemTime(&ftWrite, &dt._time); + } + + ::CloseHandle(hFile); + } + + return dt; +} + // --- ControlBase --- HWND ControlBase :: create(HINSTANCE instance, wstr_t className, ControlBase* owner) @@ -197,68 +217,20 @@ bool WindowApp :: initInstance(WindowBase* mainWindow, int cmdShow) return TRUE; } -void WindowApp :: notify(int messageCode, NotificationStatus status) +void WindowApp :: notify(int id, NMHDR* notification) { - StatusNMHDR notification; - - notification.nmhrd.code = STATUS_NOTIFICATION; - notification.nmhrd.hwndFrom = _hwnd; - notification.code = messageCode; - notification.status = status; - - ::SendMessage(_hwnd, WM_NOTIFY, 0, (LPARAM)¬ification); -} - -void WindowApp :: notifySelection(int messageCode, size_t param) -{ - SelectionNMHDR notification; - - notification.nmhrd.code = STATUS_SELECTION; - notification.nmhrd.hwndFrom = _hwnd; - notification.code = messageCode; - notification.param = param; - - ::SendMessage(_hwnd, WM_NOTIFY, 0, (LPARAM)¬ification); -} - -void WindowApp :: notifyTreeItem(int messageCode, size_t item, size_t param) -{ - TreeItemNMHDR notification; - - notification.nmhrd.code = STATUS_TREEITEM; - notification.nmhrd.hwndFrom = _hwnd; - notification.code = messageCode; - notification.item = item; - notification.param = param; - - ::SendMessage(_hwnd, WM_NOTIFY, 0, (LPARAM)¬ification); -} - -void WindowApp::notifyCompletion(int messageCode, int param) -{ - CompletionNMHDR notification; - - notification.nmhrd.code = STATUS_COMPLETION; - notification.nmhrd.hwndFrom = _hwnd; - notification.code = messageCode; - notification.param = param; + notification->code = id; + notification->hwndFrom = _hwnd; - ::SendMessage(_hwnd, WM_NOTIFY, 0, (LPARAM)¬ification); + ::SendMessage(_hwnd, WM_NOTIFY, 0, (LPARAM)notification); } -void WindowApp :: notifyContextMenu(int id, short x, short y, bool hasSelection) +void WindowApp :: notify(EventBase* event) { - ContextMenuNMHDR notification; - notification.nmhrd.code = id; - notification.nmhrd.hwndFrom = _hwnd; - notification.x = x; - notification.y = y; - notification.hasSelection = hasSelection; - - ::SendMessage(_hwnd, WM_NOTIFY, 0, (LPARAM)¬ification); + _eventFormatter->sendMessage(event, this); } -int WindowApp :: run(GUIControlBase* mainWindow, bool maximized, int notificationId, NotificationStatus notificationStatus) +int WindowApp :: run(GUIControlBase* mainWindow, bool maximized, EventBase* startEvent) { // Perform application initialization: if (!initInstance(dynamic_cast(mainWindow), maximized ? SW_MAXIMIZE : SW_SHOW)) @@ -266,8 +238,8 @@ int WindowApp :: run(GUIControlBase* mainWindow, bool maximized, int notificatio return FALSE; } - if (notificationId) - notify(notificationId, notificationStatus); + if (startEvent) + notify(startEvent); HACCEL hAccelTable = LoadAccelerators(_instance, _accelerators.str()); diff --git a/elenasrc3/gui/windows/wincommon.h b/elenasrc3/gui/windows/wincommon.h index f6fde9a30e..663029149b 100644 --- a/elenasrc3/gui/windows/wincommon.h +++ b/elenasrc3/gui/windows/wincommon.h @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------- // E L E N A P r o j e c t: ELENA IDE // WinAPI Common Header File -// (C)2021-2023, by Aleksey Rakov +// (C)2021-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #ifndef WINCOMMON_H @@ -23,6 +23,59 @@ namespace elena_lang { + // --- DateTime --- + + struct DateTime + { + private: + SYSTEMTIME _time; + + public: + static DateTime getFileTime(const wchar_t* path); + + bool operator > (const DateTime dt) const + { + if (_time.wYear > dt._time.wYear) + return true; + + if (_time.wYear == dt._time.wYear) { + if (_time.wMonth > dt._time.wMonth) + return true; + + if (_time.wMonth == dt._time.wMonth) { + if (_time.wDay > dt._time.wDay) + return true; + + if (_time.wDay == dt._time.wDay) { + if (_time.wHour > dt._time.wHour) + return true; + + if (_time.wHour == dt._time.wHour) { + if (_time.wMinute > dt._time.wMinute) + return true; + + if (_time.wMinute == dt._time.wMinute) { + if (_time.wSecond > dt._time.wSecond) + return true; + + if (_time.wSecond == dt._time.wSecond) { + return (_time.wMilliseconds > dt._time.wMilliseconds); + } + } + } + } + } + } + return false; + } + + DateTime() + { + _time.wYear = 0; + //memset(&_time, 0, sizeof(_time)); + } + }; + // --- Cursor types --- constexpr int CURSOR_TEXT = 0; constexpr int CURSOR_ARROW = 1; @@ -30,49 +83,13 @@ namespace elena_lang constexpr int CURSOR_SIZENS = 3; // --- Notification types --- + // NOTE : the systen related notifications must be greater than 0x100 constexpr int STATUS_NOTIFICATION = 0x101; constexpr int STATUS_SELECTION = 0x102; constexpr int STATUS_COMPLETION = 0x103; constexpr int STATUS_TREEITEM = 0x104; constexpr int CONTEXT_MENU_ON = 0x105; - // --- ExtNMHDR --- - struct StatusNMHDR - { - NMHDR nmhrd; - int code; - NotificationStatus status; - }; - - struct SelectionNMHDR - { - NMHDR nmhrd; - int code; - int param; - }; - - struct TreeItemNMHDR - { - NMHDR nmhrd; - int code; - size_t item; - size_t param; - }; - - struct CompletionNMHDR - { - NMHDR nmhrd; - int code; - int param; - }; - - struct ContextMenuNMHDR - { - NMHDR nmhrd; - int x, y; - bool hasSelection; - }; - // --- Color --- class Color { @@ -171,6 +188,15 @@ namespace elena_lang } }; + // --- EventFormatterBase --- + class WindowApp; + + class EventFormatterBase + { + public: + virtual void sendMessage(EventBase* event, WindowApp* app) = 0; + }; + // --- WindowBase --- class WindowBase : public ControlBase { @@ -204,27 +230,27 @@ namespace elena_lang class WindowApp : public GUIApp { protected: - HINSTANCE _instance; - HWND _hwnd; + HINSTANCE _instance; + HWND _hwnd; + + wstr_t _accelerators; - wstr_t _accelerators; + EventFormatterBase* _eventFormatter; bool initInstance(WindowBase* mainWindow, int cmdShow); public: - int run(GUIControlBase* mainWindow, bool maximized, int notificationId, NotificationStatus notificationStatus) override; + int run(GUIControlBase* mainWindow, bool maximized, EventBase* startEvent) override; - void notify(int messageCode, NotificationStatus status) override; - void notifySelection(int id, size_t param) override; - void notifyTreeItem(int id, size_t item, size_t param) override; - void notifyCompletion(int id, int param) override; - void notifyContextMenu(int id, short x, short y, bool hasSelection) override; + void notify(int id, NMHDR* notification); + void notify(EventBase* event) override; - WindowApp(HINSTANCE instance, wstr_t accelerators) + WindowApp(HINSTANCE instance, wstr_t accelerators, EventFormatterBase* formatter) { _instance = instance; _hwnd = nullptr; _accelerators = accelerators; + _eventFormatter = formatter; } }; diff --git a/elenasrc3/gui/windows/winsdi.cpp b/elenasrc3/gui/windows/winsdi.cpp index 9f780f1814..1f26642652 100644 --- a/elenasrc3/gui/windows/winsdi.cpp +++ b/elenasrc3/gui/windows/winsdi.cpp @@ -107,10 +107,10 @@ void VerticalBox :: setRectangle(Rectangle rec) int width = rec.width(); int height = rec.height(); - size_t count = _list.count(); + int count = _list.count_int(); if (_stretchMode) { int meanHeight = height / count; - for (size_t i = 0; i < count; i++) { + for (int i = 0; i < count; i++) { if (i == count - 1) meanHeight = height; @@ -130,7 +130,7 @@ void VerticalBox :: setRectangle(Rectangle rec) height -= fixedHeight; } else height = 5; - for (size_t i = 0; i < count; i++) { + for (int i = 0; i < count; i++) { if (i != 0) height = _list[i]->getRectangle().height(); @@ -195,10 +195,10 @@ void HorizontalBox :: setRectangle(Rectangle rec) int width = rec.width(); int height = rec.height(); - size_t count = _list.count(); + int count = _list.count_int(); if (_stretchMode) { int meanWidth = width / count; - for (size_t i = 0; i < count; i++) { + for (int i = 0; i < count; i++) { if (i == count - 1) meanWidth = width; @@ -210,7 +210,7 @@ void HorizontalBox :: setRectangle(Rectangle rec) } else { int fixedWidth = 0; - for (size_t i = 1; i < count; i++) { + for (int i = 1; i < count; i++) { fixedWidth += _list[i]->getRectangle().width(); fixedWidth += _spacer; } @@ -218,7 +218,7 @@ void HorizontalBox :: setRectangle(Rectangle rec) width -= fixedWidth; } else width = 5; - for (size_t i = 0; i < count; i++) { + for (int i = 0; i < count; i++) { if (i != 0) width = _list[i]->getRectangle().width(); diff --git a/elenasrc3/gui/windows/winsplitter.cpp b/elenasrc3/gui/windows/winsplitter.cpp index 6596740414..8157418238 100644 --- a/elenasrc3/gui/windows/winsplitter.cpp +++ b/elenasrc3/gui/windows/winsplitter.cpp @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------- // E L E N A P r o j e c t: ELENA IDE // WinAPI Splitter class implementation -// (C)2022, by Aleksey Rakov +// (C)2022-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #include "winsplitter.h" @@ -32,12 +32,11 @@ static LRESULT CALLBACK hookProcMouse(int nCode, WPARAM wParam, LPARAM lParam) // --- Splitter --- -Splitter :: Splitter(NotifierBase* notifier, int notifyCode, NotificationStatus notifyStatus, ControlBase* client, bool vertical) +Splitter :: Splitter(NotifierBase* notifier, ControlBase* client, bool vertical, EventInvoker invoker) : WindowBase(nullptr, 800, 4), _instance(nullptr), _notifier(notifier), - _notifyCode(notifyCode), - _notifyStatus(notifyStatus), + _layoutEventInvoker(invoker), _client(client), _vertical(vertical), _srcPos({}), @@ -226,5 +225,5 @@ void Splitter :: shiftOn(int delta) setRectangle({rec.topLeft.x, rec.topLeft.y, width, height}); - _notifier->notify(_notifyCode, _notifyStatus); + _layoutEventInvoker(_notifier); } diff --git a/elenasrc3/gui/windows/winsplitter.h b/elenasrc3/gui/windows/winsplitter.h index 16cf503324..74e8a3ea72 100644 --- a/elenasrc3/gui/windows/winsplitter.h +++ b/elenasrc3/gui/windows/winsplitter.h @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------- // E L E N A P r o j e c t: ELENA IDE // WinAPI Splitter class header -// (C)2022-2023, by Aleksey Rakov +// (C)2022-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #ifndef WINSPLITTER_H @@ -17,7 +17,6 @@ namespace elena_lang NotifierBase* _notifier; int _notifyCode; - NotificationStatus _notifyStatus; ControlBase* _client; bool _vertical; @@ -35,8 +34,12 @@ namespace elena_lang void shiftOn(int delta); public: + typedef void(*EventInvoker)(NotifierBase*); + static void registerSplitterWindow(HINSTANCE hInstance, wstr_t className, bool vertical); + EventInvoker _layoutEventInvoker; + HWND create(HINSTANCE instance, wstr_t className, ControlBase* owner) override; bool visible() override; @@ -48,7 +51,7 @@ namespace elena_lang LRESULT proceed(UINT message, WPARAM wParam, LPARAM lParam) override; - Splitter(NotifierBase* notifier, int notifyCode, NotificationStatus notifyStatus , ControlBase* client, bool vertical); + Splitter(NotifierBase* notifier, ControlBase* client, bool vertical, EventInvoker invoker); }; } diff --git a/elenasrc3/gui/windows/wintabbar.cpp b/elenasrc3/gui/windows/wintabbar.cpp index a4de439d68..e739a1113f 100644 --- a/elenasrc3/gui/windows/wintabbar.cpp +++ b/elenasrc3/gui/windows/wintabbar.cpp @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------- // E L E N A P r o j e c t: ELENA IDE // WinAPI TabBar Implementation File -// (C)2021-2022, by Aleksey Rakov +// (C)2021-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #include "idecommon.h" @@ -18,7 +18,7 @@ CustomTabBar :: CustomTabBar(NotifierBase* notifier, bool withAbovescore, int wi : ControlBase(nullptr, 0, 0, width, height) { _notifier = notifier; - _selNotificationId = 0; + _selectionInvoker = nullptr; _withAbovescore = withAbovescore; _notSelected = true; } @@ -83,8 +83,8 @@ void CustomTabBar :: selectTab(int index) { int previous = (int)::SendMessage(_handle, TCM_SETCURSEL, index, 0); if (_notSelected || previous != index) { - if (_selNotificationId) - _notifier->notifySelection(_selNotificationId, index); + if (_selectionInvoker) + _selectionInvoker(_notifier, index); _notSelected = false; } diff --git a/elenasrc3/gui/windows/wintabbar.h b/elenasrc3/gui/windows/wintabbar.h index 1147c50a9b..457f8c426b 100644 --- a/elenasrc3/gui/windows/wintabbar.h +++ b/elenasrc3/gui/windows/wintabbar.h @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------- // E L E N A P r o j e c t: ELENA IDE // WinAPI TabBar Header File -// (C)2021-2022, by Aleksey Rakov +// (C)2021-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #ifndef WINTABBAR_H @@ -14,12 +14,15 @@ namespace elena_lang // --- CustomTabBar --- class CustomTabBar : public ControlBase { + public: + typedef void(*SelectionEventInvoker)(NotifierBase*, int); + protected: - NotifierBase* _notifier; - int _selNotificationId; + NotifierBase* _notifier; + SelectionEventInvoker _selectionInvoker; - bool _withAbovescore; - bool _notSelected; + bool _withAbovescore; + bool _notSelected; public: void onDrawItem(DRAWITEMSTRUCT* item) override; diff --git a/elenasrc3/gui/windows/wintextframe.cpp b/elenasrc3/gui/windows/wintextframe.cpp index aa79a2b5e1..726e60b30d 100644 --- a/elenasrc3/gui/windows/wintextframe.cpp +++ b/elenasrc3/gui/windows/wintextframe.cpp @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------- // E L E N A P r o j e c t: ELENA IDE // Win32 EditFrame container File -// (C)2021-2023, by Aleksey Rakov +// (C)2021-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #include "wintextframe.h" @@ -11,10 +11,10 @@ using namespace elena_lang; // --- TextViewFrame --- -TextViewFrame :: TextViewFrame(NotifierBase* notifier, bool withAbovescore, ControlBase* view, TextViewModel* model, int selNotificationId) +TextViewFrame :: TextViewFrame(NotifierBase* notifier, bool withAbovescore, ControlBase* view, TextViewModel* model, SelectionEventInvoker invoker) : MultiTabControl(notifier, withAbovescore, view) { - _selNotificationId = selNotificationId; + _selectionInvoker = invoker; _model = model; model->attachListener(this); @@ -73,8 +73,9 @@ void TextViewFrame :: onSelChanged() if (index >= 0) { _model->selectDocumentView(index + 1); - if (_selNotificationId) - _notifier->notifySelection(_selNotificationId, index); + if (_selectionInvoker) { + _selectionInvoker(_notifier, index); + } } else { _child->hide(); diff --git a/elenasrc3/gui/windows/wintextframe.h b/elenasrc3/gui/windows/wintextframe.h index 9232bd943d..9bd601318c 100644 --- a/elenasrc3/gui/windows/wintextframe.h +++ b/elenasrc3/gui/windows/wintextframe.h @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------- // E L E N A P r o j e c t: ELENA IDE // Win32 EditFrame container File -// (C)2021-2023, by Aleksey Rakov +// (C)2021-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #ifndef WINTEXTFRAME_H @@ -16,7 +16,7 @@ namespace elena_lang class TextViewFrame : public MultiTabControl, TextViewListener { protected: - TextViewModel* _model; + TextViewModel* _model; public: void onDocumentNew(int index) override; @@ -27,11 +27,9 @@ namespace elena_lang void beforeDocumentClose(int index) override; void onDocumentClose(int index) override; - - void onSelChanged() override; - TextViewFrame(NotifierBase* notifier, bool withAbovescore, ControlBase* view, TextViewModel* model, int selNotificationId); + TextViewFrame(NotifierBase* notifier, bool withAbovescore, ControlBase* view, TextViewModel* model, SelectionEventInvoker invoker); }; } diff --git a/elenasrc3/gui/windows/wintextview.cpp b/elenasrc3/gui/windows/wintextview.cpp index 82917a1000..84e12902a6 100644 --- a/elenasrc3/gui/windows/wintextview.cpp +++ b/elenasrc3/gui/windows/wintextview.cpp @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------- // E L E N A P r o j e c t: ELENA IDE // WinAPI TextView Control Body File -// (C)2021-2023, by Aleksey Rakov +// (C)2021-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #include "wintextview.h" @@ -43,7 +43,8 @@ void ViewStyles::release() // --- TextViewWindow --- TextViewWindow :: TextViewWindow(NotifierBase* notifier, TextViewModelBase* model, - TextViewControllerBase* controller, ViewStyles* styles) + TextViewControllerBase* controller, ViewStyles* styles, + ContextInvoker contextInvoker, MarginInvoker marginInvoker) : WindowBase(nullptr, 50, 50) { _notifier = notifier; @@ -56,13 +57,12 @@ TextViewWindow :: TextViewWindow(NotifierBase* notifier, TextViewModelBase* mode _caretChanged = false; _mouseCaptured = false; _caret_x = 0; - - _model->attachDocListener(this); + _contextInvoker = contextInvoker; + _marginInvoker = marginInvoker; } TextViewWindow :: ~TextViewWindow() { - _model->removeDocListener(this); } void TextViewWindow :: registerTextViewWindow(HINSTANCE hInstance, wstr_t className) @@ -459,6 +459,10 @@ void TextViewWindow :: onButtonDown(Point point, bool kbShift) _controller->moveToFrame(_model, col, row, kbShift); + if (margin && _marginInvoker) { + _marginInvoker(_notifier); + } + captureMouse(); } @@ -567,9 +571,7 @@ void TextViewWindow :: onContextMenu(short x, short y) { auto docView = _model->DocView(); - if (_notifier && docView) { - _notifier->notifyContextMenu(CONTEXT_MENU_ON, x, y, docView->hasSelection()); - } + _contextInvoker(_notifier, x, y, docView->hasSelection()); } LRESULT TextViewWindow :: proceed(UINT message, WPARAM wParam, LPARAM lParam) diff --git a/elenasrc3/gui/windows/wintextview.h b/elenasrc3/gui/windows/wintextview.h index 41e6065746..f3da417e55 100644 --- a/elenasrc3/gui/windows/wintextview.h +++ b/elenasrc3/gui/windows/wintextview.h @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------- // E L E N A P r o j e c t: ELENA IDE // WinAPI TextView Control Header File -// (C)2021-2022, by Aleksey Rakov +// (C)2021-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #ifndef WINTEXTVIEW_H @@ -73,9 +73,16 @@ namespace elena_lang // --- TextViewWindow --- class TextViewWindow : public WindowBase, public DocumentNotifier { + public: + typedef void(*ContextInvoker)(NotifierBase*, int, int, bool); + typedef void(*MarginInvoker)(NotifierBase*); + protected: NotifierBase* _notifier; + ContextInvoker _contextInvoker; + MarginInvoker _marginInvoker; + TextViewModelBase* _model; ViewStyles* _styles; TextViewControllerBase* _controller; @@ -156,7 +163,8 @@ namespace elena_lang LRESULT proceed(UINT message, WPARAM wParam, LPARAM lParam) override; - TextViewWindow(NotifierBase* notifier, TextViewModelBase* model, TextViewControllerBase* controller, ViewStyles* styles); + TextViewWindow(NotifierBase* notifier, TextViewModelBase* model, TextViewControllerBase* controller, ViewStyles* styles, + ContextInvoker contextInvoker, MarginInvoker marginInvoker); virtual ~TextViewWindow(); }; } diff --git a/elenasrc3/gui/windows/wintreeview.cpp b/elenasrc3/gui/windows/wintreeview.cpp index 9b40c6db34..c38891400e 100644 --- a/elenasrc3/gui/windows/wintreeview.cpp +++ b/elenasrc3/gui/windows/wintreeview.cpp @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------- // E L E N A P r o j e c t: ELENA IDE // WinAPI TreeView Implementation File -// (C)2021-2022, by Aleksey Rakov +// (C)2021-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #include "idecommon.h" @@ -13,10 +13,11 @@ using namespace elena_lang; // --- TreeView --- -TreeView :: TreeView(int width, int height, NotifierBase* notifier, int notificationId, - bool persistentSelection, bool enableIcons, int iconId) +TreeView :: TreeView(int width, int height, NotifierBase* notifier, bool persistentSelection, + SelectionEventInvoker invoker, bool enableIcons, int iconId +) : ControlBase(nullptr, 0, 0, width, height), - _notifier(notifier), _notificationId(notificationId), + _notifier(notifier), _selectionInvoker(invoker), _persistentSelection(persistentSelection), _enableIcons(enableIcons), _iconId(iconId) { @@ -65,7 +66,8 @@ void TreeView :: onSelChanged() { size_t param = getParam(getCurrent()); - _notifier->notifySelection(_notificationId, param); + if (_selectionInvoker) + _selectionInvoker(_notifier, param); } size_t TreeView :: getParam(TreeViewItem item) diff --git a/elenasrc3/gui/windows/wintreeview.h b/elenasrc3/gui/windows/wintreeview.h index c084df2b05..0a453d6107 100644 --- a/elenasrc3/gui/windows/wintreeview.h +++ b/elenasrc3/gui/windows/wintreeview.h @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------- // E L E N A P r o j e c t: ELENA IDE // WinAPI TreeView Header File -// (C)2021-2022, by Aleksey Rakov +// (C)2021-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #ifndef WINTREEVIEW_H @@ -17,17 +17,20 @@ namespace elena_lang // --- TreeView --- class TreeView : public ControlBase { + public: + typedef void(*SelectionEventInvoker)(NotifierBase*, size_t); + protected: NotifierBase* _notifier; private: - int _notificationId; + SelectionEventInvoker _selectionInvoker; - bool _persistentSelection; - bool _enableIcons; - int _iconId; + bool _persistentSelection; + bool _enableIcons; + int _iconId; - HIMAGELIST _hImages; + HIMAGELIST _hImages; public: virtual HWND createControl(HINSTANCE instance, ControlBase* owner); @@ -56,8 +59,8 @@ namespace elena_lang void clear(TreeViewItem item); void remove(TreeViewItem item); - TreeView(int width, int height, NotifierBase* notifier, int notificationId, - bool persistentSelection, bool enableIcons = false, int iconId = 0); + TreeView(int width, int height, NotifierBase* notifier, bool persistentSelection, + SelectionEventInvoker invoker, bool enableIcons = false, int iconId = 0); virtual ~TreeView(); }; } diff --git a/elenasrc3/ide/debugcontroller.cpp b/elenasrc3/ide/debugcontroller.cpp index 1a2873cfb5..ee6b8b0313 100644 --- a/elenasrc3/ide/debugcontroller.cpp +++ b/elenasrc3/ide/debugcontroller.cpp @@ -3,7 +3,7 @@ // // This file contains implematioon of the DebugController class and // its helpers -// (C)2021-2023, by Aleksey Rakov +// (C)2021-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #include "elena.h" @@ -245,6 +245,7 @@ bool DebugInfoProvider :: loadSymbol(ustr_t reference, StreamReader& addressRead case DebugSymbol::FieldAddress: case DebugSymbol::ParameterInfo: case DebugSymbol::FieldInfo: + case DebugSymbol::LocalInfo: // replace field name reference with the name stringReader.seek(info.addresses.source.nameRef); @@ -481,7 +482,7 @@ DebugLineInfo* DebugInfoProvider :: seekClassInfo(addr_t address, IdentifierStri // --- DebugController --- DebugController :: DebugController(DebugProcessBase* process, ProjectModel* model, - SourceViewModel* sourceModel, NotifierBase* notifier, DebugSourceController* sourceController) + SourceViewModel* sourceModel, DebugSourceController* sourceController) : _provider(model) { _started = false; @@ -489,7 +490,6 @@ DebugController :: DebugController(DebugProcessBase* process, ProjectModel* mode _running = false; _sourceModel = sourceModel; _model = model; - _notifier = notifier; _currentPath = nullptr; _sourceController = sourceController; } @@ -527,6 +527,7 @@ void DebugController :: debugThread() _process->run(); _process->resetEvent(DEBUG_RESUME); _process->setEvent(DEBUG_ACTIVE); + break; case DEBUG_SUSPEND: _running = false; @@ -657,25 +658,19 @@ void DebugController :: processStep() void DebugController :: onCurrentStep(DebugLineInfo* lineInfo, ustr_t moduleName, ustr_t sourcePath) { - bool found = true; if (lineInfo) { - _sourceModel->clearTraceLine(); - + bool found = true; if (!_currentModule.compare(moduleName) || !sourcePath.compare(_currentPath)) { _currentModule.copy(moduleName); _currentPath = sourcePath; - PathString path(sourcePath);found = _sourceController->selectSource(_model, _sourceModel, moduleName, *path); + PathString path(sourcePath); + found = _sourceController->selectSource(_model, _sourceModel, moduleName, *path); } - if (found) { - _sourceModel->setTraceLine(lineInfo->row, true); - - _notifier->notify(NOTIFY_DEBUG_CHANGE, DEBUGWATCH_CHANGED | FRAME_CHANGED); - } - else _notifier->notify(NOTIFY_DEBUG_NOSOURCE, FRAME_CHANGED); - + _sourceController->traceStep(_sourceModel, found, lineInfo->row); } + else _sourceController->traceStep(_sourceModel, false, -1); } void DebugController :: onStop() @@ -687,7 +682,7 @@ void DebugController :: onStop() _currentModule.clear(); _currentPath = nullptr; - _notifier->notifyCompletion(NOTIFY_DEBUGGER_RESULT, DEBUGGER_STOPPED); + _sourceController->traceFinish(_sourceModel); } void DebugController :: run() @@ -731,13 +726,16 @@ void DebugController :: runToCursor(ustr_t ns, ustr_t path, int row) _process->setEvent(DEBUG_RESUME); } -void DebugController :: addBreakpoint(Breakpoint* bp) +void DebugController :: toggleBreakpoint(Breakpoint* bp, bool adding) { ModuleBase* currentModule = _provider.resolveModule(*bp->module); if (currentModule != nullptr) { addr_t address = _provider.findNearestAddress(currentModule, *bp->source, bp->row); if (address != INVALID_ADDR) { - _process->addBreakpoint(address); + if (adding) { + _process->addBreakpoint(address); + } + else _process->removeBreakpoint(address); } } } @@ -818,9 +816,6 @@ bool DebugController :: startThread() while (_process->waitForEvent(DEBUG_ACTIVE, 0)); - //_listener->onStart(); - _notifier->notify(NOTIFY_DEBUG_START, 0); - return _process->isStarted(); } @@ -865,8 +860,8 @@ void DebugController :: loadDebugSection(StreamReader& reader, bool starting) // if there are new records in debug section if (!reader.eof()) { _provider.load(reader, starting, _process); - - _notifier->notify(NOTIFY_DEBUG_LOAD, 0); + + _sourceController->traceStart(_model); _provider.setDebugInfoSize(reader.position()); @@ -925,12 +920,15 @@ void DebugController :: readObjectContent(ContextBrowserBase* watch, void* item, } } -void* DebugController :: readObject(ContextBrowserBase* watch, void* parent, addr_t address, ustr_t name, int level, ustr_t className) +void* DebugController :: readObject(ContextBrowserBase* watch, void* parent, addr_t address, ustr_t name, int level, ustr_t className, addr_t vmtAddress) { if (address != 0) { // read class VMT address if not provided IdentifierString classNameStr; - addr_t vmtAddress = _process->getClassVMT(address); + + if (!vmtAddress) + vmtAddress = _process->getClassVMT(address); + ref_t flags = 0; if (!emptystr(className)) { classNameStr.copy(className); @@ -1017,7 +1015,7 @@ void* DebugController :: readIntArrayLocal(ContextBrowserBase* watch, void* pare unsigned int b = _process->getDWORD(address + i * 4); value.copy("["); - value.appendInt(i); + value.appendInt((int)i); value.append("]"); WatchContext context = { item, address + i * 4}; @@ -1078,9 +1076,9 @@ void DebugController :: readObjectArray(ContextBrowserBase* watch, void* parent, if (level <= 0) return; - size_t length = _min(_process->getArrayLength(address) / sizeof(addr_t), 100); + int length = (int)_min(_process->getArrayLength(address) / sizeof(addr_t), 100); IdentifierString value; - for (size_t i = 0; i < length; i++) { + for (int i = 0; i < length; i++) { addr_t itemAddress = _process->getField(address, i); value.copy("["); @@ -1168,7 +1166,7 @@ inline disp_t getFrameDisp(DebugLineInfo& frameInfo, disp_t offset) inline const char* getClassInfo(DebugLineInfo& frameInfo) { - if (frameInfo.symbol == DebugSymbol::ParameterInfo) { + if (frameInfo.symbol == DebugSymbol::ParameterInfo || frameInfo.symbol == DebugSymbol::LocalInfo) { return (const char*)frameInfo.addresses.source.nameRef; } else return nullptr; @@ -1267,12 +1265,28 @@ void DebugController :: readAutoContext(ContextBrowserBase* watch, int level, Wa (const char*)lineInfo[index].addresses.local.nameRef, level - 1); break; case DebugSymbol::ParameterAddress: + { + ustr_t className = getClassInfo(lineInfo[index + 2]); + addr_t vmtAddress = _provider.getClassAddress(className); + item = readObject(watch, nullptr, _process->getStackItem( lineInfo[index].addresses.local.offset, -getFrameDisp(lineInfo[index + 1], _process->getDataOffset() * 2) - _process->getDataOffset()), - (const char*)lineInfo[index].addresses.local.nameRef, level - 1, - getClassInfo(lineInfo[index + 2])); + (const char*)lineInfo[index].addresses.local.nameRef, level - 1, + className, vmtAddress); break; + } + case DebugSymbol::LocalAddress: + { + ustr_t className = getClassInfo(lineInfo[index + 1]); + addr_t vmtAddress = _provider.getClassAddress(className); + + item = readObject(watch, nullptr, + _process->getStackItemAddress(getFPOffset(lineInfo[index].addresses.local.offset, _process->getDataOffset())), + (const char*)lineInfo[index].addresses.local.nameRef, level - 1, + className, vmtAddress); + break; + } default: break; } diff --git a/elenasrc3/ide/debugcontroller.h b/elenasrc3/ide/debugcontroller.h index 4500efd4ab..6ffe32b9ff 100644 --- a/elenasrc3/ide/debugcontroller.h +++ b/elenasrc3/ide/debugcontroller.h @@ -2,7 +2,7 @@ // E L E N A P r o j e c t: ELENA Engine // // This file contains the DebugController class and its helpers header -// (C)2021-2023, by Aleksey Rakov +// (C)2021-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #ifndef DEBUGCONTROLLER_H @@ -20,9 +20,15 @@ namespace elena_lang class DebugSourceController { public: + virtual void traceStart(ProjectModel* model) = 0; + + virtual void traceStep(SourceViewModel* sourceModel, bool found, int row) = 0; + virtual bool selectSource(ProjectModel* model, SourceViewModel* sourceModel, ustr_t moduleName, path_t sourcePath) = 0; + virtual void traceFinish(SourceViewModel* sourceModel) = 0; + virtual ~DebugSourceController() = default; }; @@ -223,7 +229,6 @@ namespace elena_lang ProjectModel* _model; SourceViewModel* _sourceModel; - NotifierBase* _notifier; DebugSourceController* _sourceController; IdentifierString _currentModule; @@ -246,7 +251,7 @@ namespace elena_lang void readFields(ContextBrowserBase* watch, void* parent, addr_t address, int level, DebugLineInfo* info); void readObjectArray(ContextBrowserBase* watch, void* parent, addr_t address, int level, DebugLineInfo* info); - void* readObject(ContextBrowserBase* watch, void* parent, addr_t address, ustr_t name, int level, ustr_t className = nullptr); + void* readObject(ContextBrowserBase* watch, void* parent, addr_t address, ustr_t name, int level, ustr_t className = nullptr, addr_t vmtAddress = 0); void* readFieldValue(ContextBrowserBase* watch, void* parent, addr_t address, ustr_t name, int level, int size, ustr_t className = nullptr); void* readIntLocal(ContextBrowserBase* watch, void* parent, addr_t address, ustr_t name, int level); void* readUIntLocal(ContextBrowserBase* watch, void* parent, addr_t address, ustr_t name, int level); @@ -271,7 +276,7 @@ namespace elena_lang void stepInto(); void stop(); void runToCursor(ustr_t name, ustr_t path, int row); - void addBreakpoint(Breakpoint* bp); + void toggleBreakpoint(Breakpoint* bp, bool adding); void readAutoContext(ContextBrowserBase* watch, int level, WatchItems* refreshedItems); void readContext(ContextBrowserBase* watch, void* parentItem, addr_t address, int level); @@ -290,7 +295,7 @@ namespace elena_lang } DebugController(DebugProcessBase* process, ProjectModel* model, - SourceViewModel* sourceModel, NotifierBase* notifier, DebugSourceController* sourceController); + SourceViewModel* sourceModel, DebugSourceController* sourceController); }; } diff --git a/elenasrc3/ide/editframe.cpp b/elenasrc3/ide/editframe.cpp index 50ca6ec96c..64b0212d68 100644 --- a/elenasrc3/ide/editframe.cpp +++ b/elenasrc3/ide/editframe.cpp @@ -15,66 +15,46 @@ SourceViewModel :: SourceViewModel() { } -void SourceViewModel :: beforeDocumentSelect(int index) +void SourceViewModel :: setTraceLine(int row, bool withCursor, DocumentChangeStatus& status) { - clearErrorLine(); -} - -void SourceViewModel :: setTraceLine(int row, bool withCursor) -{ - DocumentChangeStatus status = {}; - _currentView->removeMarker(STYLE_TRACE_LINE, status); _currentView->addMarker(row, STYLE_TRACE_LINE, false, false, status); if (withCursor) _currentView->setCaret({ 0, row - 1 }, false, status); - - _currentView->notifyOnChange(status); } -void SourceViewModel :: clearTraceLine() +void SourceViewModel :: clearTraceLine(DocumentChangeStatus& status) { if (_currentView != nullptr) { - DocumentChangeStatus status = {}; - _currentView->removeMarker(STYLE_TRACE_LINE, status); - - _currentView->notifyOnChange(status); } } -void SourceViewModel :: setErrorLine(int row, int column, bool withCursor) +void SourceViewModel :: setErrorLine(int row, int column, bool withCursor, DocumentChangeStatus& status) { - DocumentChangeStatus status = {}; - _currentView->removeMarker(STYLE_ERROR_LINE, status); _currentView->addMarker(row, STYLE_ERROR_LINE, true, false, status); if (withCursor) _currentView->setCaret({ column - 1, row - 1 }, false, status); - - _currentView->notifyOnChange(status); } -void SourceViewModel :: clearErrorLine() +void SourceViewModel :: clearErrorLine(DocumentChangeStatus& status) { - DocumentChangeStatus status = {}; - if(_currentView->removeMarker(STYLE_ERROR_LINE, status)) { status.formatterChanged = true; - _currentView->notifyOnChange(status); } } -void SourceViewModel :: notifyOnChange(DocumentChangeStatus& status) +void SourceViewModel :: refresh(DocumentChangeStatus& status) { if (status.textChanged || status.caretChanged) { - clearErrorLine(); + clearErrorLine(status); status.formatterChanged = true; } - TextViewModel::notifyOnChange(status); + TextViewModel::refresh(status); } void SourceViewModel :: clearDocumentView() diff --git a/elenasrc3/ide/editframe.h b/elenasrc3/ide/editframe.h index b82e662f24..4539e2d478 100644 --- a/elenasrc3/ide/editframe.h +++ b/elenasrc3/ide/editframe.h @@ -16,15 +16,13 @@ namespace elena_lang class SourceViewModel : public TextViewModel { public: - void beforeDocumentSelect(int index) override; + void refresh(DocumentChangeStatus& status) override; - void notifyOnChange(DocumentChangeStatus& status) override; + void setTraceLine(int row, bool withCursor, DocumentChangeStatus& status); + void clearTraceLine(DocumentChangeStatus& status); - void setTraceLine(int row, bool withCursor); - void clearTraceLine(); - - void setErrorLine(int row, int column, bool withCursor); - void clearErrorLine(); + void setErrorLine(int row, int column, bool withCursors, DocumentChangeStatus& status); + void clearErrorLine(DocumentChangeStatus& status); void clearDocumentView() override; diff --git a/elenasrc3/ide/eng/messages.h b/elenasrc3/ide/eng/messages.h index a156d445b7..a8fad85fb2 100644 --- a/elenasrc3/ide/eng/messages.h +++ b/elenasrc3/ide/eng/messages.h @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------- // E L E N A P r o j e c t: ELENA IDE Messages // -// (C)2021-2023, by Aleksex Rakov +// (C)2021-2024, by Aleksex Rakov //--------------------------------------------------------------------------- #ifndef MESSAGES_H @@ -19,6 +19,9 @@ namespace elena_lang constexpr auto QUESTION_CLOSE_UNSAVED = _T("Close the tab anyway"); constexpr auto QUESTION_NOSOURCE_CONTINUE = _T("The source code is not found. Do you want to continue?"); + constexpr auto INFO_RUN_OUT_OF_DATE = _T("The project modules are out of date\nPlease recompile the project"); + constexpr auto INFO_RUN_UNSAVED_PROJECT = _T("The project files are not saved\nPlease save them and recompile the project"); + constexpr auto NOT_FOUND_TEXT = _T("Search string not found"); constexpr auto REPLACE_TEXT = _T("Replace this occurence?"); @@ -41,7 +44,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-2021: 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-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 ELENA_HOMEPAGE = _T("https://elena-lang.github.io/"); } diff --git a/elenasrc3/ide/idecommon.cpp b/elenasrc3/ide/idecommon.cpp index 901ae6dd0b..ec2b0a1530 100644 --- a/elenasrc3/ide/idecommon.cpp +++ b/elenasrc3/ide/idecommon.cpp @@ -191,3 +191,91 @@ void ContextBrowserBase :: populateFLOAT64(WatchContext* context, double value) clearNode(context->root); populateNode(context->root, number.str()); } + +// --- SelectionEvent --- + +SelectionEvent :: SelectionEvent(int id, int index) + : EventBase(0), _eventId(id), _index(index) +{ +} + +int SelectionEvent :: eventId() +{ + return _eventId; +} + +// --- ParamSelectionEvent --- + +ParamSelectionEvent :: ParamSelectionEvent(int id, size_t param) + : EventBase(0), _eventId(id), _param(param) +{ +} + +int ParamSelectionEvent :: eventId() +{ + return _eventId; +} + +// --- BrowseEvent --- + +BrowseEvent :: BrowseEvent(int id, size_t item, size_t param) + : EventBase(0), _eventId(id), _item(item), _param(param) +{ +} + +// --- LayoutEvent --- + +LayoutEvent::LayoutEvent(int status) + : EventBase(status) +{ +} + +int LayoutEvent::eventId() +{ + return EVENT_LAYOUT; +} + +// --- StartUpEvent --- + +StartUpEvent::StartUpEvent(int status) + : EventBase(status) +{ +} + +int StartUpEvent::eventId() +{ + return EVENT_STARTUP; +} + +// --- TextViewModelEvent --- + +int TextViewModelEvent::eventId() +{ + return EVENT_TEXTVIEW_MODEL_CHANGED; +} + +// --- ContextMenuEvent --- + +ContextMenuEvent :: ContextMenuEvent(int id, int x, int y, bool hasSelection) + : EventBase(0), _eventId(id), _x(x), _y(y), _hasSelection(hasSelection) +{ +} + +int ContextMenuEvent :: eventId() +{ + return _eventId; +} + +// --- SimpleEvent --- + +SimpleEvent :: SimpleEvent(int id) + : EventBase(0) +{ + _eventId = id; +} + +int SimpleEvent :: eventId() +{ + return _eventId; +} + diff --git a/elenasrc3/ide/idecommon.h b/elenasrc3/ide/idecommon.h index 75076f264f..7e686a55f1 100644 --- a/elenasrc3/ide/idecommon.h +++ b/elenasrc3/ide/idecommon.h @@ -25,6 +25,8 @@ namespace elena_lang constexpr auto OPTIONS_SUB_CATEGORY = "project/options"; constexpr auto OUTPUT_SUB_CATEGORY = "project/output"; + constexpr auto PROFILE_CATEGORY = "/profile"; + constexpr auto MODULE_CATEGORY = "files/*"; constexpr auto WIN_X86_KEY = "Win_x86"; @@ -39,20 +41,41 @@ namespace elena_lang constexpr auto ERROR_RUN_NEED_RECOMPILE = 0x0003; constexpr auto DEBUGGER_STOPPED = 0x0004; - // --- Notification codes --- - //constexpr auto NOTIFY_SOURCEMODEL = 1; - constexpr auto NOTIFY_CURRENTVIEW_CHANGED = 2; - //constexpr auto NOTIFY_CURRENTVIEW_HIDE = 4; - //constexpr auto NOTIFY_LAYOUT_CHANGED = 5; - //constexpr auto NOTIFY_ACTIVATE_EDITFRAME = 9; - //constexpr auto NOTIFY_START_COMPILATION = 10; - //constexpr auto NOTIFY_PROJECTMODEL = 11; + // --- Event IDs --- + // NOTE : the generic notifications must be less than 0x100 + constexpr int EVENT_TEXTVIEW_MODEL_CHANGED = 0x0001; + constexpr int EVENT_TEXTFRAME_SELECTION_CHANGED = 0x0002; + constexpr int EVENT_STARTUP = 0x0003; + constexpr int EVENT_LAYOUT = 0x0004; + constexpr int EVENT_PROJECTVIEW_SELECTION_CHANGED = 0x0005; + constexpr int EVENT_COMPILATION_END = 0x0006; + constexpr int EVENT_ERRORLIST_SELECTION = 0x0007; + constexpr int EVENT_TEXT_CONTEXTMENU = 0x0008; + constexpr int EVENT_BROWSE_CONTEXT = 0x0009; + constexpr int EVENT_TEXT_MARGINLICK = 0x000A; + + // --- Event Statuses --- + constexpr int STATUS_NONE = 0x0000; + constexpr int STATUS_DOC_READY = 0x0001; + constexpr int STATUS_STATUS_CHANGED = 0x0002; + constexpr int STATUS_PROJECT_CHANGED = 0x0004; + constexpr int STATUS_FRAME_VISIBILITY_CHANGED = 0x0108; + constexpr int STATUS_FRAME_CHANGED = 0x0010; + constexpr int STATUS_DEBUGGER_NOSOURCE = 0x0020; + constexpr int STATUS_DEBUGGER_STOPPED = 0x0040; + constexpr int STATUS_DEBUGGER_STEP = 0x0080; + constexpr int STATUS_LAYOUT_CHANGED = 0x0100; + constexpr int STATUS_COMPILING = 0x0200; + constexpr int STATUS_PROJECT_REFRESH = 0x0400; + constexpr int STATUS_WITHERRORS = 0x0800; + constexpr int STATUS_DEBUGGER_RUNNING = 0x1000; + constexpr int STATUS_DEBUGGER_FINISHED = 0x2000; + constexpr int STATUS_FRAME_ACTIVATE = 0x4000; + constexpr int NOTIFY_DEBUGGER_RESULT = 6; constexpr int NOTIFY_ERROR_SEL = 7; constexpr int NOTIFY_COMPILATION_RESULT = 8; constexpr int NOTIFY_SHOW_RESULT = 9; - constexpr int NOTIFY_TEXTFRAME_SEL = 10; - constexpr int NOTIFY_PROJECTVIEW_SEL = 11; constexpr int NOTIFY_DEBUG_CHANGE = 12; constexpr int NOTIFY_IDE_CHANGE = 13; constexpr int NOTIFY_ONSTART = 14; @@ -61,21 +84,7 @@ namespace elena_lang constexpr int NOTIFY_DEBUG_CONTEXT_EXPANDED = 17; constexpr int NOTIFY_DEBUG_LOAD = 18; constexpr int NOTIFY_DEBUG_NOSOURCE = 19; - - // --- Notification statuses --- - constexpr NotificationStatus IDE_ONSTART = -1; - constexpr NotificationStatus NONE_CHANGED = 0x00000; - - constexpr NotificationStatus IDE_LAYOUT_CHANGED = 0x00001; - constexpr NotificationStatus IDE_STATUS_CHANGED = 0x00002; - constexpr NotificationStatus FRAME_CHANGED = 0x00004; - constexpr NotificationStatus PROJECT_CHANGED = 0x00008; - constexpr NotificationStatus FRAME_VISIBILITY_CHANGED = 0x00010; - constexpr NotificationStatus DEBUGWATCH_CHANGED = 0x00020; - constexpr NotificationStatus IDE_COMPILATION_STARTED = 0x00040; - constexpr NotificationStatus OUTPUT_SHOWN = 0x00080; - constexpr NotificationStatus FRAME_ACTIVATE = 0x00100; - constexpr NotificationStatus COLOR_SCHEME_CHANGED = 0x00200; + constexpr int NOTIFY_DEBUG_RUNNING = 20; // --- PathSettings --- struct PathSettings @@ -88,7 +97,6 @@ namespace elena_lang { Empty = 0, Ready = 1, - Busy = 2, AutoRecompiling = 3, Compiling = 4, CompiledSuccessfully = 5, @@ -96,6 +104,8 @@ namespace elena_lang CompiledWithErrors = 7, Broken = 8, DebuggerStopped = 9, + Running = 10, + Stopped = 11, }; inline bool testIDEStatus(IDEStatus value, IDEStatus mask) @@ -282,6 +292,7 @@ namespace elena_lang virtual void setBreakpoint(addr_t address, bool withStackLevelControl) = 0; virtual void addBreakpoint(addr_t address) = 0; + virtual void removeBreakpoint(addr_t address) = 0; virtual void addStep(addr_t address, void* current) = 0; @@ -327,6 +338,112 @@ namespace elena_lang virtual GUIControlBase* createMainWindow(NotifierBase* notifier, ProcessBase* outputProcess, ProcessBase* vmConsoleProcess) = 0; }; + + // --- SelectionEvent --- + class SelectionEvent : public EventBase + { + int _eventId; + int _index; + + public: + int eventId() override; + + int Index() { return _index; } + + SelectionEvent(int id, int index); + }; + + // --- ParamSelectionEvent --- + class ParamSelectionEvent : public EventBase + { + int _eventId; + size_t _param; + + public: + int eventId() override; + + size_t Param() { return _param; } + + ParamSelectionEvent(int id, size_t param); + }; + + // --- BrowseEvent --- + class BrowseEvent : public EventBase + { + int _eventId; + size_t _item; + size_t _param; + + public: + int eventId() override { return _eventId; } + + size_t Item() { return _item; } + + size_t Param() { return _param; } + + BrowseEvent(int id, size_t item, size_t param); + }; + + // --- LayoutEvent --- + class LayoutEvent : public EventBase + { + public: + int eventId() override; + + LayoutEvent(int status); + }; + + // --- ContextMenuEvent --- + class ContextMenuEvent : public EventBase + { + int _eventId; + int _x, _y; + bool _hasSelection; + + public: + int eventId() override; + + int X() { return _x; } + int Y() { return _y; } + bool HasSelection() { return _hasSelection; } + + ContextMenuEvent(int id, int x, int y, bool hasSelection); + }; + + // --- StartUpEvent --- + class StartUpEvent : public EventBase + { + public: + int eventId() override; + + StartUpEvent(int status); + }; + + // --- SimpleEvent --- + class SimpleEvent : public EventBase + { + int _eventId; + + public: + int eventId() override; + + SimpleEvent(int eventId); + }; + + // --- TextViewModelEvent --- + struct TextViewModelEvent : public EventBase + { + public: + DocumentChangeStatus changeStatus; + + int eventId() override; + + TextViewModelEvent(int status, DocumentChangeStatus changeStatus) + : EventBase(status), changeStatus(changeStatus) + { + } + }; + } #endif diff --git a/elenasrc3/ide/idecontroller.cpp b/elenasrc3/ide/idecontroller.cpp index 1bdd585a01..19cb82b734 100644 --- a/elenasrc3/ide/idecontroller.cpp +++ b/elenasrc3/ide/idecontroller.cpp @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------- // E L E N A P r o j e c t: ELENA IDE // IDE Controller implementation File -// (C)2005-2023, by Aleksey Rakov +// (C)2005-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #include @@ -36,7 +36,7 @@ inline ustr_t getPlatformName(PlatformType type) // --- SourceViewController --- -void SourceViewController :: newSource(TextViewModelBase* model, ustr_t caption, bool autoSelect, NotificationStatus& status) +void SourceViewController :: newSource(TextViewModelBase* model, ustr_t caption, bool autoSelect, int& status) { IdentifierString tabName("unnamed"); @@ -45,28 +45,31 @@ void SourceViewController :: newSource(TextViewModelBase* model, ustr_t caption, newDocument(model, caption); if (empty) - status |= FRAME_VISIBILITY_CHANGED; + status |= STATUS_FRAME_VISIBILITY_CHANGED; if (autoSelect) { int index = model->getDocumentIndex(caption); - selectDocument(model, index, status); + if (selectDocument(model, index)) { + status |= STATUS_FRAME_CHANGED; + } } } bool SourceViewController :: openSource(TextViewModelBase* model, ustr_t caption, path_t sourcePath, - FileEncoding encoding, bool autoSelect, NotificationStatus& status) + FileEncoding encoding, bool autoSelect, int& status) { bool empty = model->empty; if (openDocument(model, caption, sourcePath, encoding)) { if (empty) - status |= FRAME_VISIBILITY_CHANGED; + status |= STATUS_FRAME_VISIBILITY_CHANGED; if (autoSelect) { int index = model->getDocumentIndex(caption); - selectDocument(model, index, status); + if (selectDocument(model, index)) + status |= STATUS_FRAME_CHANGED; } return true; @@ -79,7 +82,7 @@ void SourceViewController :: renameSource(TextViewModelBase* model, ustr_t oldNa model->renameDocumentView(oldName, newName, newSourcePath); } -void SourceViewController :: closeSource(TextViewModelBase* model, int index, bool autoSelect, NotificationStatus& status) +void SourceViewController :: closeSource(TextViewModelBase* model, int index, bool autoSelect, int& status) { if (index > 0) { int count = model->getDocumentCount(); @@ -87,14 +90,18 @@ void SourceViewController :: closeSource(TextViewModelBase* model, int index, bo closeDocument(model, index, status); if (autoSelect && !model->empty) { + bool changed = false; if (index == count) { - selectDocument(model, count - 1, status); + changed = selectDocument(model, count - 1); } - else selectDocument(model, index, status); + else changed = selectDocument(model, index); + + if (changed) + status |= STATUS_FRAME_CHANGED; } - status |= IDE_LAYOUT_CHANGED; - status |= FRAME_VISIBILITY_CHANGED; + if (model->empty) + status |= STATUS_FRAME_VISIBILITY_CHANGED; } } @@ -107,8 +114,6 @@ void SourceViewController :: saveSource(TextViewModelBase* model, ustr_t name) if (docInfo) { docInfo->save(path); - - //model->onModelModeChanged(model->getDocumentIndex(name)); } } @@ -218,7 +223,7 @@ bool ProjectController :: startDebugger(ProjectModel& model) bool debugMode = model.getDebugMode(); if (debugMode) { if (!_debugController.start(exePath.str(), commandLine.str(), debugMode/*, _breakpoints */)) { - notifyCompletion(NOTIFY_DEBUGGER_RESULT, ERROR_DEBUG_FILE_NOT_FOUND_COMPILE); + //notifyCompletion(NOTIFY_DEBUGGER_RESULT, ERROR_DEBUG_FILE_NOT_FOUND_COMPILE); return false; } @@ -226,7 +231,7 @@ bool ProjectController :: startDebugger(ProjectModel& model) } else { if (!_debugController.start(exePath.str(), commandLine.str(), false/*, _breakpoints */)) { - notifyCompletion(NOTIFY_DEBUGGER_RESULT, ERROR_RUN_NEED_RECOMPILE); + //notifyCompletion(NOTIFY_DEBUGGER_RESULT, ERROR_RUN_NEED_RECOMPILE); return false; } @@ -235,25 +240,53 @@ bool ProjectController :: startDebugger(ProjectModel& model) return true; } else { - notifyCompletion(NOTIFY_DEBUGGER_RESULT, ERROR_RUN_NEED_TARGET); + //notifyCompletion(NOTIFY_DEBUGGER_RESULT, ERROR_RUN_NEED_TARGET); return false; } } -bool ProjectController :: isOutaged(bool noWarning) +bool ProjectController :: isOutaged(ProjectModel& projectModel, SourceViewModel& sourceModel) { - return false; // !! temporal + if (sourceModel.isAnyDocumentModified()) { + return false; + } + + size_t projectPathLen = projectModel.projectPath.length(); + + NamespaceString name; + PathString rootPath(*projectModel.projectPath, projectModel.getOutputPath()); + for (auto it = projectModel.sources.start(); !it.eof(); ++it) { + PathString source(*rootPath, *it); + + PathString module; + module.copySubPath(*source, true); + + name.copy(projectModel.getPackage()); + name.pathToName(*module + projectPathLen); // get a full name + + _debugController.resolveNamespace(name); + + ReferenceName::nameToPath(module, *name); + module.append(_T(".nl")); + + if (name.length() != 0) { + if (_compareFileModifiedTime(*source, *module)) + return false; + } + else return false; + } + + return true; } -bool ProjectController :: onDebugAction(ProjectModel& model, DebugAction action) +bool ProjectController :: onDebugAction(ProjectModel& model, SourceViewModel& sourceModel, DebugAction action, bool& outaged) { - if (model.getStatus() == IDEStatus::Busy) - return false; - if (!_debugController.isStarted()) { - bool toRecompile = model.autoRecompile && !testIDEStatus(model.getStatus(), IDEStatus::AutoRecompiling); - if (isOutaged(toRecompile)) { + bool toRecompile = model.autoRecompile; + if (!isOutaged(model, sourceModel)) { + outaged = true; + if (toRecompile) { if (!doCompileProject(model, action)) return false; @@ -268,34 +301,29 @@ bool ProjectController :: onDebugAction(ProjectModel& model, DebugAction action) void ProjectController :: doDebugAction(ProjectModel& model, SourceViewModel& sourceModel , DebugAction action) { - if (model.getStatus() != IDEStatus::Busy) { - if (onDebugAction(model, action)) { - switch (action) { - case DebugAction::Run: - _debugController.run(); - break; - case DebugAction::StepInto: - _debugController.stepInto(); - break; - case DebugAction::StepOver: - _debugController.stepOver(); - break; - case DebugAction::RunTo: - runToCursor(model, sourceModel); - break; - default: - break; - } - } + switch (action) { + case DebugAction::Run: + _debugController.run(); + break; + case DebugAction::StepInto: + _debugController.stepInto(); + break; + case DebugAction::StepOver: + _debugController.stepOver(); + break; + case DebugAction::RunTo: + runToCursor(model, sourceModel); + break; + default: + break; } } void ProjectController :: doDebugStop(ProjectModel& model) { - if (model.getStatus() != IDEStatus::Busy) { - _debugController.stop(); - } + _debugController.stop(); } + void ProjectController :: runToCursor(ProjectModel& model, SourceViewModel& sourceModel) { auto currentDoc = sourceModel.DocView(); @@ -338,6 +366,13 @@ bool ProjectController :: compileProject(ProjectModel& model) PathString cmdLine(*model.paths.compilerPath); cmdLine.append(" -w3 "); // !! temporal + + if (!model.profile.empty()) { + cmdLine.append(" -l"); + cmdLine.append(*model.profile); + cmdLine.append(" "); + } + cmdLine.append(*model.projectFile); PathString curDir; @@ -501,7 +536,7 @@ void ProjectController :: saveConfig(ProjectModel& model, ConfigFile& config, Co model.addedSources.clear(); } -NotificationStatus ProjectController :: newProject(ProjectModel& model) +int ProjectController :: newProject(ProjectModel& model) { model.sources.clear(); @@ -510,12 +545,33 @@ NotificationStatus ProjectController :: newProject(ProjectModel& model) model.package.copy("unnamed"); model.notSaved = true; - return PROJECT_CHANGED; + return STATUS_PROJECT_CHANGED; } -NotificationStatus ProjectController :: openProject(ProjectModel& model, path_t projectFile) +void ProjectController :: loadProfileList(ProjectModel& model, ConfigFile& config, ConfigFile::Node root) { - NotificationStatus status = PROJECT_CHANGED; + ConfigFile::Collection profiles; + if (config.select(root, PROFILE_CATEGORY, profiles)) { + for (auto it = profiles.start(); !it.eof(); ++it) { + ConfigFile::Node profileNode = *it; + + DynamicString key; + profileNode.readAttribute("key", key); + + if (model.profileList.retrieveIndex(key.str(), [](ustr_t arg, ustr_t current) + { + return current.compare(arg); + }) == -1) + { + model.profileList.add(ustr_t(key.str()).clone()); + } + } + } +} + +int ProjectController :: openProject(ProjectModel& model, path_t projectFile) +{ + int status = STATUS_PROJECT_CHANGED; ustr_t key = getPlatformName(_platform); @@ -541,10 +597,13 @@ NotificationStatus ProjectController :: openProject(ProjectModel& model, path_t return node.compareAttribute("key", key); }); + loadProfileList(model, projectConfig, root); + loadProfileList(model, projectConfig, platformRoot); + loadConfig(model, projectConfig, root); loadConfig(model, projectConfig, platformRoot); - status |= IDE_LAYOUT_CHANGED; + status |= STATUS_FRAME_VISIBILITY_CHANGED; } return status; @@ -563,7 +622,7 @@ void ProjectController :: setProjectPath(ProjectModel& model, path_t projectFile model.projectPath.copySubPath(projectFile, true); } -NotificationStatus ProjectController :: saveProject(ProjectModel& model) +void ProjectController :: saveProject(ProjectModel& model) { ustr_t key = getPlatformName(_platform); @@ -586,11 +645,9 @@ NotificationStatus ProjectController :: saveProject(ProjectModel& model) projectConfig.save(*path, FileEncoding::UTF8); model.notSaved = false; - - return PROJECT_CHANGED; } -NotificationStatus ProjectController :: closeProject(ProjectModel& model) +int ProjectController :: closeProject(ProjectModel& model) { model.empty = true; model.name.clear(); @@ -605,10 +662,10 @@ NotificationStatus ProjectController :: closeProject(ProjectModel& model) model.target.clear(); model.outputPath.clear(); - return PROJECT_CHANGED; + return STATUS_PROJECT_CHANGED; } -NotificationStatus ProjectController :: openSingleFileProject(ProjectModel& model, path_t singleProjectFile) +int ProjectController :: openSingleFileProject(ProjectModel& model, path_t singleProjectFile) { FileNameString src(singleProjectFile, true); FileNameString name(singleProjectFile); @@ -629,7 +686,7 @@ NotificationStatus ProjectController :: openSingleFileProject(ProjectModel& mode model.target.copy(*tmp); model.target.append(".exe"); - return PROJECT_CHANGED; + return STATUS_PROJECT_CHANGED; } path_t ProjectController :: getSourceByIndex(ProjectModel& model, int index) @@ -654,7 +711,7 @@ void ProjectController :: refreshDebugContext(ContextBrowserBase* contextBrowser _debugController.readContext(contextBrowser, (void*)param, address, 4); } -void ProjectController :: toggleBreakpoint(ProjectModel& model, SourceViewModel& sourceModel, int row) +bool ProjectController :: toggleBreakpoint(ProjectModel& model, SourceViewModel& sourceModel, int row, DocumentChangeStatus& status) { auto currentDoc = sourceModel.DocView(); if (currentDoc != nullptr) { @@ -674,15 +731,22 @@ void ProjectController :: toggleBreakpoint(ProjectModel& model, SourceViewModel& for(auto it = model.breakpoints.start(); !it.eof(); ++it) { auto bm = *it; if (bm->row == row && bm->module.compare(*ns) && bm->source.compare(*pathStr)) { + if (_debugController.isStarted()) + _debugController.toggleBreakpoint(bm, false); + model.breakpoints.cut(bm); addMode = false; break; } } - - DocumentChangeStatus status = {}; + if (addMode) { - model.breakpoints.add(new Breakpoint(row, *pathStr, *ns)); + Breakpoint* bm = new Breakpoint(row, *pathStr, *ns); + + model.breakpoints.add(bm); + + if (_debugController.isStarted()) + _debugController.toggleBreakpoint(bm, true); currentDoc->addMarker(row, STYLE_BREAKPOINT, false, true, status); } @@ -690,14 +754,16 @@ void ProjectController :: toggleBreakpoint(ProjectModel& model, SourceViewModel& currentDoc->removeMarker(row, STYLE_BREAKPOINT, status); } - currentDoc->notifyOnChange(status); + return true; } + + return false; } void ProjectController :: loadBreakpoints(ProjectModel& model) { for (auto it = model.breakpoints.start(); !it.eof(); ++it) { - _debugController.addBreakpoint(*it); + _debugController.toggleBreakpoint(*it, true); } } @@ -840,9 +906,9 @@ void IDEController :: saveConfig(IDEModel* model, path_t configPath) config.save(*model->projectModel.paths.configPath, FileEncoding::UTF8); } -void IDEController :: init(IDEModel* model) +void IDEController :: init(IDEModel* model, int& status) { - NotificationStatus status = IDE_STATUS_CHANGED | IDE_LAYOUT_CHANGED; + status |= STATUS_STATUS_CHANGED | STATUS_FRAME_VISIBILITY_CHANGED | STATUS_LAYOUT_CHANGED; if (model->projectModel.lastOpenProjects.count() > 0) { PathString path(model->projectModel.lastOpenProjects.get(1)); @@ -853,14 +919,41 @@ void IDEController :: init(IDEModel* model) } } else { - if (openProject(model, *path, status)) { - model->changeStatus(IDEStatus::Ready); + int retVal = openProject(model, *path); + if (retVal) { + status |= (retVal | STATUS_DOC_READY); } } } - else status |= PROJECT_CHANGED; - - _notifier->notify(NOTIFY_IDE_CHANGE, status); + else status |= STATUS_PROJECT_CHANGED; +} + +void IDEController :: traceStep(SourceViewModel* sourceModel, bool found, int row) +{ + int projectStatus = STATUS_DEBUGGER_STOPPED; + DocumentChangeStatus docStatus = {}; + + sourceModel->clearTraceLine(docStatus); + + if (found) { + sourceModel->setTraceLine(row, true, docStatus); + + projectStatus |= STATUS_DEBUGGER_STEP; + } + else projectStatus |= STATUS_DEBUGGER_NOSOURCE; + + TextViewModelEvent event = { projectStatus, docStatus }; + _notifier->notify(&event); +} + +void IDEController :: traceStart(ProjectModel* model) +{ + onDebuggerHook(model); +} + +void IDEController :: traceFinish(SourceViewModel* sourceModel) +{ + notifyOnModelChange(STATUS_DEBUGGER_FINISHED); } bool IDEController :: selectSource(ProjectModel* model, SourceViewModel* sourceModel, @@ -869,9 +962,9 @@ bool IDEController :: selectSource(ProjectModel* model, SourceViewModel* sourceM PathString fullPath; projectController.defineFullPath(*model, ns, sourcePath, fullPath); - NotificationStatus status = NONE_CHANGED; - if (openFile(sourceModel, model, *fullPath, status)) { - _notifier->notify(NOTIFY_IDE_CHANGE, status); + int projectStatus = STATUS_NONE; + if (openFile(sourceModel, model, *fullPath, projectStatus)) { + notifyOnModelChange(projectStatus); return true; } @@ -880,16 +973,13 @@ bool IDEController :: selectSource(ProjectModel* model, SourceViewModel* sourceM void IDEController :: doNewFile(IDEModel* model) { - NotificationStatus status = NONE_CHANGED; + int projectStatus = STATUS_NONE; NamespaceString sourceNameStr; projectController.defineSourceName(&model->projectModel, nullptr, sourceNameStr); - sourceController.newSource(&model->sourceViewModel, *sourceNameStr, true, status); - - if (test(status, FRAME_VISIBILITY_CHANGED)) - status |= IDE_LAYOUT_CHANGED; + sourceController.newSource(&model->sourceViewModel, *sourceNameStr, true, projectStatus); - _notifier->notify(NOTIFY_IDE_CHANGE, status); + notifyOnModelChange(projectStatus); } inline void removeDuplicate(ProjectPaths& lastOpenFiles, path_t value) @@ -913,7 +1003,7 @@ inline void addToRecentProjects(IDEModel* model, path_t path) model->projectModel.lastOpenProjects.insert(path.clone()); } -bool IDEController :: openFile(IDEModel* model, path_t sourceFile, NotificationStatus& status) +bool IDEController :: openFile(IDEModel* model, path_t sourceFile, int& status) { if (model->projectModel.name.empty()) { status |= projectController.openSingleFileProject(model->projectModel, sourceFile); @@ -924,13 +1014,19 @@ bool IDEController :: openFile(IDEModel* model, path_t sourceFile, NotificationS return openFile(&model->sourceViewModel, &model->projectModel, sourceFile, status); } -bool IDEController :: openFile(SourceViewModel* model, ProjectModel* projectModel, path_t sourceFile, NotificationStatus& status) +bool IDEController :: openFile(SourceViewModel* model, ProjectModel* projectModel, path_t sourceFile, int& status) { ustr_t sourceName = model->getDocumentNameByPath(sourceFile); int index = sourceName.empty() ? 0 : model->getDocumentIndex(sourceName); if (index > 0) { - return sourceController.selectDocument(model, index, status); + if (sourceController.selectDocument(model, index)) { + status |= STATUS_FRAME_CHANGED; + + return true; + } + + return false; } else { NamespaceString sourceNameStr; @@ -942,22 +1038,27 @@ bool IDEController :: openFile(SourceViewModel* model, ProjectModel* projectMode bool retVal = sourceController.openSource(model, sourceName, sourceFile, defaultEncoding, true, status); - if (test(status, FRAME_VISIBILITY_CHANGED)) - status |= IDE_LAYOUT_CHANGED; - return retVal; } +void IDEController :: notifyOnModelChange(int projectStatus) +{ + DocumentChangeStatus docStatus = { test(projectStatus, STATUS_FRAME_CHANGED) }; + + TextViewModelEvent event = { projectStatus, docStatus }; + _notifier->notify(&event); +} + bool IDEController :: doOpenProjectSourceByIndex(IDEModel* model, int index) { - NotificationStatus status = NONE_CHANGED; + int projectStatus = STATUS_NONE; path_t sourcePath = projectController.getSourceByIndex(model->projectModel, index); if (!sourcePath.empty()) { PathString fullPath(*model->projectModel.projectPath, sourcePath); - if(openFile(model, *fullPath, status)) { - _notifier->notify(NOTIFY_IDE_CHANGE, status); + if(openFile(model, *fullPath, projectStatus)) { + notifyOnModelChange(projectStatus); return true; } @@ -965,21 +1066,19 @@ bool IDEController :: doOpenProjectSourceByIndex(IDEModel* model, int index) return false; } -bool IDEController :: openProject(IDEModel* model, path_t projectFile, NotificationStatus& status) +int IDEController :: openProject(IDEModel* model, path_t projectFile) { - status |= projectController.openProject(model->projectModel, projectFile); - - return true; + return projectController.openProject(model->projectModel, projectFile); } void IDEController :: doOpenFile(FileDialogBase& dialog, IDEModel* model) { - NotificationStatus status = {}; + int projectStatus = STATUS_NONE; List files(nullptr); if (dialog.openFiles(files)) { for (auto it = files.start(); !it.eof(); ++it) { - if(openFile(model, *it, status)) { + if(openFile(model, *it, projectStatus)) { removeDuplicate(model->projectModel.lastOpenFiles, *it); while (model->projectModel.lastOpenFiles.count() >= MAX_RECENT_FILES) @@ -989,15 +1088,15 @@ void IDEController :: doOpenFile(FileDialogBase& dialog, IDEModel* model) } } - _notifier->notify(NOTIFY_IDE_CHANGE, status); + notifyOnModelChange(projectStatus); } } void IDEController :: doOpenFile(IDEModel* model, path_t path) { - NotificationStatus status = {}; + int projectStatus = STATUS_NONE; - if (openFile(model, path, status)) { + if (openFile(model, path, projectStatus)) { removeDuplicate(model->projectModel.lastOpenFiles, path); while (model->projectModel.lastOpenFiles.count() >= MAX_RECENT_FILES) @@ -1006,13 +1105,13 @@ void IDEController :: doOpenFile(IDEModel* model, path_t path) model->projectModel.lastOpenFiles.insert(path.clone()); } - _notifier->notify(NOTIFY_IDE_CHANGE, status); + notifyOnModelChange(projectStatus); } bool IDEController :: doSaveFile(FileDialogBase& dialog, IDEModel* model, bool saveAsMode, bool forcedSave) { auto docView = model->sourceViewModel.DocView(); - if (!docView) + if (!docView || docView->isReadOnly()) return false; if (docView->isUnnamed() || saveAsMode) { @@ -1028,16 +1127,22 @@ bool IDEController :: doSaveFile(FileDialogBase& dialog, IDEModel* model, bool s forcedSave = true; } - if (forcedSave) + if (forcedSave) { sourceController.saveSource(&model->sourceViewModel, nullptr); + DocumentChangeStatus docStatus = { }; + docView->refresh(docStatus); + + TextViewModelEvent event = { STATUS_NONE, docStatus }; + _notifier->notify(&event); + } + return true; } bool IDEController :: doSaveAll(FileDialogBase& dialog, FileDialogBase& projectDialog, IDEModel* model) { - NotificationStatus status = NONE_CHANGED; - if (!saveAll(dialog, model, true, status)) { + if (!saveAll(dialog, model, true)) { return true; } @@ -1045,44 +1150,42 @@ bool IDEController :: doSaveAll(FileDialogBase& dialog, FileDialogBase& projectD doSaveProject(dialog, projectDialog, model, false); } - if (status != NONE_CHANGED) - _notifier->notify(NOTIFY_IDE_CHANGE, status); - return false; } void IDEController :: doNewProject(FileDialogBase& dialog, MessageDialogBase& mssgDialog, ProjectSettingsBase& prjDialog, IDEModel* model) { - NotificationStatus status = NONE_CHANGED; - - if (!closeAll(dialog, mssgDialog, model, status)) + int projectStatus = STATUS_NONE; + if (!closeAll(dialog, mssgDialog, model, projectStatus)) return; - status |= projectController.newProject(model->projectModel); + projectStatus |= projectController.newProject(model->projectModel); if (prjDialog.showModal()) { - + notifyOnModelChange(projectStatus); } } bool IDEController :: doOpenProject(FileDialogBase& dialog, MessageDialogBase& mssgDialog, IDEModel* model) { - NotificationStatus status = NONE_CHANGED; + int projectStatus = STATUS_NONE; PathString path; if (dialog.openFile(path)) { - if (!closeProject(dialog, mssgDialog, model, status)) + if (!closeProject(dialog, mssgDialog, model, projectStatus)) return false; - if (openProject(model, *path, status)) { + int retVal = openProject(model, *path); + + if (retVal) { + projectStatus |= retVal; + addToRecentProjects(model, *path); - model->changeStatus(IDEStatus::Ready); - status |= IDE_LAYOUT_CHANGED; + projectStatus |= STATUS_DOC_READY; - if (status != NONE_CHANGED) - _notifier->notify(NOTIFY_IDE_CHANGE, status); + notifyOnModelChange(projectStatus); return true; } @@ -1091,19 +1194,19 @@ bool IDEController :: doOpenProject(FileDialogBase& dialog, MessageDialogBase& m return false; } -void IDEController :: doOpenProject(FileDialogBase& dialog, MessageDialogBase& mssgDialog, IDEModel* model, path_t path) +void IDEController::doOpenProject(FileDialogBase& dialog, MessageDialogBase& mssgDialog, IDEModel* model, path_t path) { - NotificationStatus status = {}; + int projectStatus = STATUS_NONE; - if (!closeProject(dialog, mssgDialog, model, status)) + if (!closeProject(dialog, mssgDialog, model, projectStatus)) return; if (PathUtil::checkExtension(path, "l")) { - openFile(model, path, status); + openFile(model, path, projectStatus); } - else openProject(model, path, status); + else projectStatus |= openProject(model, path); - _notifier->notify(NOTIFY_IDE_CHANGE, status); + notifyOnModelChange(projectStatus); } bool IDEController :: doSaveProject(FileDialogBase& dialog, FileDialogBase& projectDialog, IDEModel* model, bool forcedMode) @@ -1120,11 +1223,7 @@ bool IDEController :: doSaveProject(FileDialogBase& dialog, FileDialogBase& proj projectController.saveProject(model->projectModel); } - NotificationStatus status = NONE_CHANGED; - if(saveAll(dialog, model, forcedMode, status)) { - if (status != NONE_CHANGED) - _notifier->notify(NOTIFY_IDE_CHANGE, status); - + if(saveAll(dialog, model, forcedMode)) { return true; } @@ -1132,7 +1231,7 @@ bool IDEController :: doSaveProject(FileDialogBase& dialog, FileDialogBase& proj } bool IDEController :: closeProject(FileDialogBase& dialog, MessageDialogBase& mssgDialog, IDEModel* model, - NotificationStatus& status) + int& status) { if (closeAll(dialog, mssgDialog, model, status)) { status |= projectController.closeProject(model->projectModel); @@ -1144,15 +1243,15 @@ bool IDEController :: closeProject(FileDialogBase& dialog, MessageDialogBase& ms bool IDEController :: doCloseProject(FileDialogBase& dialog, MessageDialogBase& mssgDialog, IDEModel* model) { - NotificationStatus status = NONE_CHANGED; + int projectStatus = STATUS_NONE; + + if (closeAll(dialog, mssgDialog, model, projectStatus)) { + projectStatus |= projectController.closeProject(model->projectModel); - if (closeAll(dialog, mssgDialog, model, status)) { - status |= projectController.closeProject(model->projectModel); model->changeStatus(IDEStatus::Empty); - status |= IDE_LAYOUT_CHANGED; + projectStatus |= STATUS_STATUS_CHANGED; - if (status != NONE_CHANGED) - _notifier->notify(NOTIFY_IDE_CHANGE, status); + notifyOnModelChange(projectStatus); return true; } @@ -1167,7 +1266,7 @@ bool IDEController :: saveFile(FileDialogBase& dialog, IDEModel* model, int inde } bool IDEController :: closeFile(FileDialogBase& dialog, MessageDialogBase& mssgDialog, IDEModel* model, - int index, NotificationStatus& status) + int index, int& status) { auto docView = model->sourceViewModel.getDocument(index); if (docView->isUnnamed()) { @@ -1200,13 +1299,14 @@ bool IDEController :: closeFile(FileDialogBase& dialog, MessageDialogBase& mssgD bool IDEController :: doCloseFile(FileDialogBase& dialog, MessageDialogBase& mssgDialog, IDEModel* model, int index) { - NotificationStatus status = NONE_CHANGED; + int projectStatus = STATUS_NONE; if (index > 0) { - bool retVal = closeFile(dialog, mssgDialog, model, index, status); + bool retVal = closeFile(dialog, mssgDialog, model, index, projectStatus); - if (status != NONE_CHANGED) - _notifier->notify(NOTIFY_IDE_CHANGE, status); + notifyOnModelChange(projectStatus); + + return retVal; } return false; @@ -1222,7 +1322,7 @@ bool IDEController :: doCloseFile(FileDialogBase& dialog, MessageDialogBase& mss } bool IDEController :: closeAll(FileDialogBase& dialog, MessageDialogBase& mssgDialog, IDEModel* model, - NotificationStatus& status) + int& status) { while (model->sourceViewModel.getDocumentCount() > 0) { if (!closeFile(dialog, mssgDialog, model, 1, status)) @@ -1233,7 +1333,7 @@ bool IDEController :: closeAll(FileDialogBase& dialog, MessageDialogBase& mssgDi } bool IDEController :: closeAllButActive(FileDialogBase& dialog, MessageDialogBase& mssgDialog, IDEModel* model, - NotificationStatus& status) + int& status) { int index = model->sourceViewModel.getCurrentIndex(); for (int i = 1; i < index; i++) { @@ -1250,8 +1350,7 @@ bool IDEController :: closeAllButActive(FileDialogBase& dialog, MessageDialogBas return true; } -bool IDEController :: saveAll(FileDialogBase& dialog, IDEModel* model, bool forcedMode, - NotificationStatus& status) +bool IDEController :: saveAll(FileDialogBase& dialog, IDEModel* model, bool forcedMode) { for (pos_t i = 0; i < model->sourceViewModel.getDocumentCount(); i++) { if (!saveFile(dialog, model, i + 1, forcedMode)) @@ -1263,10 +1362,9 @@ bool IDEController :: saveAll(FileDialogBase& dialog, IDEModel* model, bool forc bool IDEController :: doCloseAll(FileDialogBase& dialog, MessageDialogBase& mssgDialog, IDEModel* model) { - NotificationStatus status = NONE_CHANGED; - if (closeAll(dialog, mssgDialog, model, status)) { - if (status != NONE_CHANGED) - _notifier->notify(NOTIFY_IDE_CHANGE, status); + int projectStatus = STATUS_NONE; + if (closeAll(dialog, mssgDialog, model, projectStatus)) { + notifyOnModelChange(projectStatus); return true; } @@ -1276,10 +1374,9 @@ bool IDEController :: doCloseAll(FileDialogBase& dialog, MessageDialogBase& mssg bool IDEController :: doCloseAllButActive(FileDialogBase& dialog, MessageDialogBase& mssgDialog, IDEModel* model) { - NotificationStatus status = NONE_CHANGED; - if (closeAllButActive(dialog, mssgDialog, model, status)) { - if (status != NONE_CHANGED) - _notifier->notify(NOTIFY_IDE_CHANGE, status); + int projectStatus = STATUS_NONE; + if (closeAllButActive(dialog, mssgDialog, model, projectStatus)) { + notifyOnModelChange(projectStatus); return true; } @@ -1308,14 +1405,12 @@ void IDEController :: doSelectWindow(TextViewModelBase* viewModel, path_t path) int index = sourceName.empty() ? 0 : viewModel->getDocumentIndex(sourceName); if (index > 0) { - NotificationStatus status = NONE_CHANGED; + int projectStatus = STATUS_NONE; - if(sourceController.selectDocument(viewModel, index, status)) { - if (test(status, FRAME_VISIBILITY_CHANGED)) - status |= IDE_LAYOUT_CHANGED; + if(sourceController.selectDocument(viewModel, index)) { + projectStatus |= STATUS_FRAME_CHANGED; - if (status != NONE_CHANGED) - _notifier->notify(NOTIFY_IDE_CHANGE, status); + notifyOnModelChange(projectStatus); } } } @@ -1328,42 +1423,48 @@ path_t IDEController :: retrieveSingleProjectFile(IDEModel* model) else return nullptr; } -void IDEController :: doDebugAction(IDEModel* model, DebugAction action) +void IDEController :: doDebugAction(IDEModel* model, DebugAction action, MessageDialogBase& mssgDialog) { - projectController.doDebugAction(model->projectModel, model->sourceViewModel, action); -} + if (model->running) + return; -void IDEController :: doDebugStop(IDEModel* model) -{ - projectController.doDebugStop(model->projectModel); -} + bool outaged = false; + if (projectController.onDebugAction(model->projectModel, model->sourceViewModel, action, outaged)) { + model->running = true; -void IDEController :: onCompilationStart(IDEModel* model) -{ - model->status = IDEStatus::Compiling; + model->sourceViewModel.setReadOnlyMode(true); + + DocumentChangeStatus docStatus = {}; + model->sourceViewModel.clearTraceLine(docStatus); + docStatus.readOnlyChanged = true; - _notifier->notify(NOTIFY_IDE_CHANGE, IDE_STATUS_CHANGED | IDE_COMPILATION_STARTED); - _notifier->notifySelection(NOTIFY_SHOW_RESULT, model->ideScheme.compilerOutputControl); + TextViewModelEvent event = { STATUS_DEBUGGER_RUNNING, docStatus }; + _notifier->notify(&event); + + projectController.doDebugAction(model->projectModel, model->sourceViewModel, action); + } + else if (model->sourceViewModel.isAnyDocumentModified()) + mssgDialog.info(INFO_RUN_UNSAVED_PROJECT); + else if (outaged) + mssgDialog.info(INFO_RUN_OUT_OF_DATE); } -void IDEController :: onCompilationStop(IDEModel* model) +void IDEController :: doDebugStop(IDEModel* model) { - model->status = IDEStatus::Ready; - - _notifier->notify(NOTIFY_IDE_CHANGE, IDE_STATUS_CHANGED); + if (projectController.isStarted()) + projectController.doDebugStop(model->projectModel); } -void IDEController :: onCompilationBreak(IDEModel* model) +void IDEController :: onCompilationStart(IDEModel* model) { - model->status = IDEStatus::Broken; + model->running = true; + model->status = IDEStatus::Compiling; - _notifier->notify(NOTIFY_IDE_CHANGE, IDE_STATUS_CHANGED); + notifyOnModelChange(STATUS_STATUS_CHANGED | STATUS_COMPILING | STATUS_LAYOUT_CHANGED); } void IDEController :: displayErrors(IDEModel* model, text_str output, ErrorLogBase* log) { - _notifier->notifySelection(NOTIFY_SHOW_RESULT, model->ideScheme.errorListControl); - log->clearMessages(); // parse output for errors @@ -1433,44 +1534,46 @@ void IDEController :: highlightError(IDEModel* model, int row, int column, path_ { PathString fullPath(*model->projectModel.projectPath, path); - NotificationStatus status = NONE_CHANGED; - openFile(model, *fullPath, status); + int projectStatus = STATUS_FRAME_ACTIVATE; + openFile(model, *fullPath, projectStatus); - model->viewModel()->setErrorLine(row, column, true); + DocumentChangeStatus docStatus = { test(projectStatus, STATUS_FRAME_CHANGED) }; + model->viewModel()->setErrorLine(row, column, true, docStatus); - _notifier->notify(NOTIFY_IDE_CHANGE, status | FRAME_ACTIVATE); + TextViewModelEvent event = { projectStatus, docStatus }; + _notifier->notify(&event); } void IDEController :: onCompilationCompletion(IDEModel* model, int exitCode, text_str output, ErrorLogBase* log) { + model->running = false; + if (exitCode == 0) { model->status = IDEStatus::CompiledSuccessfully; - _notifier->notify(NOTIFY_IDE_CHANGE, IDE_STATUS_CHANGED); + notifyOnModelChange(STATUS_STATUS_CHANGED | STATUS_PROJECT_REFRESH); } else { if (exitCode == -1) { model->status = IDEStatus::CompiledWithWarnings; } else model->status = IDEStatus::CompiledWithErrors; - _notifier->notify(NOTIFY_IDE_CHANGE, IDE_STATUS_CHANGED); displayErrors(model, output, log); + + notifyOnModelChange(STATUS_STATUS_CHANGED | STATUS_PROJECT_REFRESH | STATUS_WITHERRORS); } } bool IDEController :: doCompileProject(FileDialogBase& dialog, FileDialogBase& projectDialog, IDEModel* model) { - onCompilationStart(model); - - if (!doSaveProject(dialog, projectDialog, model, false)) { - onCompilationBreak(model); + if (doSaveProject(dialog, projectDialog, model, false)) { + onCompilationStart(model); - return false; + return projectController.doCompileProject(model->projectModel, DebugAction::None); } - - return projectController.doCompileProject(model->projectModel, DebugAction::None); + else return false; } void IDEController :: doStartVMConsole(IDEModel* model) @@ -1494,14 +1597,14 @@ void IDEController :: refreshDebugContext(ContextBrowserBase* contextBrowser, ID { projectController.refreshDebugContext(contextBrowser); - _notifier->notifySelection(NOTIFY_REFRESH, model->ideScheme.debugWatch); + //_notifier->notifySelection(NOTIFY_REFRESH, model->ideScheme.debugWatch); } void IDEController :: refreshDebugContext(ContextBrowserBase* contextBrowser, IDEModel* model, size_t item, size_t param) { projectController.refreshDebugContext(contextBrowser, item, param); - _notifier->notifySelection(NOTIFY_REFRESH, model->ideScheme.debugWatch); + //_notifier->notifySelection(NOTIFY_REFRESH, model->ideScheme.debugWatch); } bool IDEController :: onClose(FileDialogBase& dialog, MessageDialogBase& mssgDialog, IDEModel* model) @@ -1511,35 +1614,47 @@ bool IDEController :: onClose(FileDialogBase& dialog, MessageDialogBase& mssgDia return doCloseAll(dialog, mssgDialog, model); } -void IDEController :: onDebuggerHook(IDEModel* model) +void IDEController :: onDebuggerHook(ProjectModel* model) { - projectController.loadBreakpoints(model->projectModel); + projectController.loadBreakpoints(*model); } void IDEController :: onDebuggerStop(IDEModel* model) { - model->sourceViewModel.clearTraceLine(); + DocumentChangeStatus status = {}; + + model->sourceViewModel.clearTraceLine(status); + model->status = IDEStatus::DebuggerStopped; + + model->running = false; + model->sourceViewModel.setReadOnlyMode(false); - model->status = IDEStatus::DebuggerStopped; - _notifier->notify(NOTIFY_IDE_CHANGE, IDE_STATUS_CHANGED | FRAME_CHANGED); + status.readOnlyChanged = true; + + TextViewModelEvent event = { STATUS_STATUS_CHANGED, status }; + _notifier->notify(&event); } -void IDEController :: onProgramStop(IDEModel* model) +void IDEController :: onDebuggerStep(IDEModel* model) { - PathString path(*model->projectModel.paths.configPath); - - saveConfig(model, *path); + model->running = false; } -void IDEController :: onStatusChange(IDEModel* model, IDEStatus newStatus) +void IDEController :: onIDEStop(IDEModel* model) { - model->status = newStatus; - _notifier->notify(NOTIFY_IDE_CHANGE, IDE_STATUS_CHANGED); + PathString path(*model->projectModel.paths.configPath); + + saveConfig(model, *path); } void IDEController :: toggleBreakpoint(IDEModel* model, int row) { - projectController.toggleBreakpoint(model->projectModel, model->sourceViewModel, row); + DocumentChangeStatus status = {}; + + if (projectController.toggleBreakpoint(model->projectModel, model->sourceViewModel, row, status)) { + TextViewModelEvent event = { 0, status }; + _notifier->notify(&event); + } } void IDEController :: doInclude(IDEModel* model) @@ -1631,14 +1746,21 @@ void IDEController :: doConfigureEditorSettings(EditorSettingsBase& editorDialog if(editorDialog.showModal()) { if (prevSchemeIndex != model->viewModel()->schemeIndex) - _notifier->notify(NOTIFY_IDE_CHANGE, COLOR_SCHEME_CHANGED | FRAME_CHANGED); + notifyOnModelChange(STATUS_FRAME_CHANGED); } } void IDEController :: onDebuggerNoSource(MessageDialogBase& mssgDialog, IDEModel* model) { + model->running = false; + auto result = mssgDialog.question(QUESTION_NOSOURCE_CONTINUE); if (result == MessageDialogBase::Answer::Yes) - doDebugAction(model, DebugAction::StepInto); -} \ No newline at end of file + doDebugAction(model, DebugAction::StepInto, mssgDialog); +} + +void IDEController :: onDocSelection(IDEModel* model, int index) +{ + notifyOnModelChange(STATUS_FRAME_CHANGED); +} diff --git a/elenasrc3/ide/idecontroller.h b/elenasrc3/ide/idecontroller.h index 64d50c21fe..03fab878bb 100644 --- a/elenasrc3/ide/idecontroller.h +++ b/elenasrc3/ide/idecontroller.h @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------- // E L E N A P r o j e c t: ELENA IDE // IDE Controller header File -// (C)2021-2023, by Aleksey Rakov +// (C)2021-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #ifndef IDECONTROLLER_H @@ -18,10 +18,10 @@ namespace elena_lang class SourceViewController : public TextViewController { public: - void newSource(TextViewModelBase* model, ustr_t name, bool autoSelect, NotificationStatus& status); + void newSource(TextViewModelBase* model, ustr_t name, bool autoSelect, int& status); bool openSource(TextViewModelBase* model, ustr_t name, path_t sourcePath, - FileEncoding encoding, bool autoSelect, NotificationStatus& status); - void closeSource(TextViewModelBase* model, int index, bool autoSelect, NotificationStatus& status); + FileEncoding encoding, bool autoSelect, int& status); + void closeSource(TextViewModelBase* model, int index, bool autoSelect, int& status); void renameSource(TextViewModelBase* model, ustr_t oldName, ustr_t newName, path_t newSourcePath); @@ -43,6 +43,8 @@ namespace elena_lang RunTo }; + typedef bool(*CompareFileDateTime)(path_t, path_t); + // --- ProjectController --- class ProjectController : public NotifierBase { @@ -56,13 +58,16 @@ namespace elena_lang PathHelperBase* _pathHelper; + CompareFileDateTime _compareFileModifiedTime; + void loadConfig(ProjectModel& model, ConfigFile& config, ConfigFile::Node platformRoot); void saveConfig(ProjectModel& model, ConfigFile& config, ConfigFile::Node root, ConfigFile::Node platformRoot); + void loadProfileList(ProjectModel& model, ConfigFile& config, ConfigFile::Node platformRoot); + path_t retrieveSourceName(ProjectModel* model, path_t sourcePath, NamespaceString& retVal, PathString& subPath); - bool onDebugAction(ProjectModel& model, DebugAction action); - bool isOutaged(bool noWarning); + bool isOutaged(ProjectModel& projectModel, SourceViewModel& sourceModel); bool startDebugger(ProjectModel& model/*, bool stepMode*/); @@ -81,11 +86,11 @@ namespace elena_lang void setProjectPath(ProjectModel& model, path_t projectFile); - NotificationStatus openSingleFileProject(ProjectModel& model, path_t singleProjectFile); - NotificationStatus newProject(ProjectModel& model); - NotificationStatus openProject(ProjectModel& model, path_t projectFile); - NotificationStatus saveProject(ProjectModel& model); - NotificationStatus closeProject(ProjectModel& model); + int openSingleFileProject(ProjectModel& model, path_t singleProjectFile); + int newProject(ProjectModel& model); + int openProject(ProjectModel& model, path_t projectFile); + void saveProject(ProjectModel& model); + int closeProject(ProjectModel& model); path_t getSourceByIndex(ProjectModel& model, int index); @@ -98,6 +103,8 @@ namespace elena_lang bool startVMConsole(ProjectModel& model); void stopVMConsole(); + bool onDebugAction(ProjectModel& model, SourceViewModel& sourceModel, DebugAction action, bool& outaged); + void doDebugAction(ProjectModel& model, SourceViewModel& sourceModel, DebugAction action); void doDebugStop(ProjectModel& model); @@ -105,7 +112,7 @@ namespace elena_lang void refreshDebugContext(ContextBrowserBase* contextBrowser); void refreshDebugContext(ContextBrowserBase* contextBrowser, size_t param, addr_t address); - void toggleBreakpoint(ProjectModel& model, SourceViewModel& sourceModel, int row); + bool toggleBreakpoint(ProjectModel& model, SourceViewModel& sourceModel, int row, DocumentChangeStatus& status); void loadBreakpoints(ProjectModel& model); @@ -114,41 +121,22 @@ namespace elena_lang _notifier = notifier; } - void notify(int id, NotificationStatus status) override - { - if (_notifier) - _notifier->notify(id, status); - } - void notifySelection(int id, size_t param) override - { - if (_notifier) - _notifier->notifySelection(id, param); - } - void notifyCompletion(int id, int param) override + void notify(EventBase* event) override { if (_notifier) - _notifier->notifyCompletion(id, param); - } - void notifyTreeItem(int id, size_t item, size_t param) override - { - if (_notifier) - _notifier->notifyTreeItem(id, item, param); - } - void notifyContextMenu(int id, short x, short y, bool hasSelection) override - { - if (_notifier) - _notifier->notifyContextMenu(id, x, y, hasSelection); + _notifier->notify(event); } ProjectController(ProcessBase* outputProcess, ProcessBase* vmConsoleProcess, DebugProcessBase* debugProcess, ProjectModel* model, SourceViewModel* sourceModel, - DebugSourceController* sourceController, PlatformType platform, PathHelperBase* pathHelper) - : _outputProcess(outputProcess), _vmProcess(vmConsoleProcess), _debugController(debugProcess, model, sourceModel, this, sourceController), + DebugSourceController* sourceController, PlatformType platform, PathHelperBase* pathHelper, CompareFileDateTime comparer) + : _outputProcess(outputProcess), _vmProcess(vmConsoleProcess), _debugController(debugProcess, model, sourceModel, sourceController), _autoWatch({ nullptr, 0 }), _pathHelper(pathHelper) { _notifier = nullptr; _platform = platform; + _compareFileModifiedTime = comparer; } }; @@ -157,27 +145,26 @@ namespace elena_lang { NotifierBase* _notifier; - bool openFile(SourceViewModel* model, ProjectModel* projectModel, path_t sourceFile, NotificationStatus& status); - bool openFile(IDEModel* model, path_t sourceFile, NotificationStatus& status); - bool openProject(IDEModel* model, path_t projectFile, NotificationStatus& status); + bool openFile(SourceViewModel* model, ProjectModel* projectModel, path_t sourceFile, int& status); + bool openFile(IDEModel* model, path_t sourceFile, int& status); + int openProject(IDEModel* model, path_t projectFile); bool closeProject(FileDialogBase& dialog, MessageDialogBase& mssgDialog, IDEModel* model, - NotificationStatus& status); + int& status); bool closeFile(FileDialogBase& dialog, MessageDialogBase& mssgDialog, IDEModel* model, - int index, NotificationStatus& status); + int index, int& status); bool saveFile(FileDialogBase& dialog, IDEModel* model, int index, bool forcedMode); bool closeAll(FileDialogBase& dialog, MessageDialogBase& mssgDialog, IDEModel* model, - NotificationStatus& status); + int& status); bool closeAllButActive(FileDialogBase& dialog, MessageDialogBase& mssgDialog, IDEModel* model, - NotificationStatus& status); - bool saveAll(FileDialogBase& dialog, IDEModel* model, bool forcedMode, - NotificationStatus& status); + int& status); + bool saveAll(FileDialogBase& dialog, IDEModel* model, bool forcedMode); void displayErrors(IDEModel* model, text_str output, ErrorLogBase* log); void onCompilationStart(IDEModel* model); - void onCompilationStop(IDEModel* model); - void onCompilationBreak(IDEModel* model); + + void notifyOnModelChange(int projectStatus); public: FileEncoding defaultEncoding; @@ -195,6 +182,7 @@ namespace elena_lang _notifier = notifier; projectController.setNotifier(notifier); + sourceController.setNotifier(notifier); } path_t retrieveSingleProjectFile(IDEModel* model); @@ -202,8 +190,11 @@ namespace elena_lang //bool openFile(IDEModel* model, path_t sourceFile); bool doOpenProjectSourceByIndex(IDEModel* model, int index); + void traceStart(ProjectModel* model) override; bool selectSource(ProjectModel* model, SourceViewModel* sourceModel, - ustr_t moduleName, path_t sourcePath); + ustr_t moduleName, path_t sourcePath) override; + void traceStep(SourceViewModel* sourceModel, bool found, int row) override; + void traceFinish(SourceViewModel* sourceModel) override; void highlightError(IDEModel* model, int row, int column, path_t path); @@ -230,7 +221,7 @@ namespace elena_lang bool doCompileProject(FileDialogBase& dialog, FileDialogBase& projectDialog, IDEModel* model); void doChangeProject(ProjectSettingsBase& prjDialog, IDEModel* model); - void doDebugAction(IDEModel* model, DebugAction action); + void doDebugAction(IDEModel* model, DebugAction action, MessageDialogBase& mssgDialog); void doDebugStop(IDEModel* model); void doStartVMConsole(IDEModel* model); @@ -255,10 +246,13 @@ namespace elena_lang void onCompilationCompletion(IDEModel* model, int exitCode, text_str output, ErrorLogBase* log); - void onDebuggerHook(IDEModel* model); + void onDebuggerHook(ProjectModel* model); + void onDebuggerStep(IDEModel* model); void onDebuggerStop(IDEModel* model); - void onStatusChange(IDEModel* model, IDEStatus newStatus); void onDebuggerNoSource(MessageDialogBase& mssgDialog, IDEModel* model); + void onDocSelection(IDEModel* model, int index); + + void onIDEStop(IDEModel* model); void doInclude(IDEModel* model); @@ -266,16 +260,14 @@ namespace elena_lang bool onClose(FileDialogBase& dialog, MessageDialogBase& mssgDialog, IDEModel* model); - void init(IDEModel* model); - - void onProgramStop(IDEModel* model); + void init(IDEModel* model, int& status); IDEController(ProcessBase* outputProcess, ProcessBase* vmConsoleProcess, DebugProcessBase* process, - IDEModel* model, TextViewSettings& textViewSettings, PlatformType platform, PathHelperBase* pathHelper + IDEModel* model, TextViewSettings& textViewSettings, PlatformType platform, PathHelperBase* pathHelper, CompareFileDateTime comparer ) : sourceController(textViewSettings), projectController(outputProcess, vmConsoleProcess, process, &model->projectModel, &model->sourceViewModel, - this, platform, pathHelper) + this, platform, pathHelper, comparer) { _notifier = nullptr; defaultEncoding = FileEncoding::UTF8; diff --git a/elenasrc3/ide/ideproject.cpp b/elenasrc3/ide/ideproject.cpp index 612d6d2864..d8628304b4 100644 --- a/elenasrc3/ide/ideproject.cpp +++ b/elenasrc3/ide/ideproject.cpp @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------- // E L E N A P r o j e c t: ELENA IDE // IDE Project Model implementation File -// (C)2021-2023, by Aleksey Rakov +// (C)2021-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #include "ideproject.h" @@ -14,7 +14,7 @@ ProjectModel :: ProjectModel(IDEStatus* status) : lastOpenFiles(nullptr), lastOpenProjects(nullptr), sources(nullptr), addedSources(nullptr), - breakpoints({}), projectTypeList(nullptr) + breakpoints({}), projectTypeList(nullptr), profileList(nullptr) { this->status = status; diff --git a/elenasrc3/ide/ideproject.h b/elenasrc3/ide/ideproject.h index 052d6a872c..49766d448f 100644 --- a/elenasrc3/ide/ideproject.h +++ b/elenasrc3/ide/ideproject.h @@ -58,6 +58,7 @@ namespace elena_lang IdentifierString package; IdentifierString target; IdentifierString templateName; + IdentifierString profile; IdentifierString options; ProjectPaths sources; @@ -69,6 +70,7 @@ namespace elena_lang Breakpoints breakpoints; StringList projectTypeList; + StringList profileList; ustr_t getTarget(); ustr_t getArguments(); diff --git a/elenasrc3/ide/ideversion.h b/elenasrc3/ide/ideversion.h index b966972dc3..5798acd8db 100644 --- a/elenasrc3/ide/ideversion.h +++ b/elenasrc3/ide/ideversion.h @@ -1,2 +1,2 @@ -#define IDE_REVISION_NUMBER 111 +#define IDE_REVISION_NUMBER 120 diff --git a/elenasrc3/ide/ideview.cpp b/elenasrc3/ide/ideview.cpp index 819033468e..a7df46b03f 100644 --- a/elenasrc3/ide/ideview.cpp +++ b/elenasrc3/ide/ideview.cpp @@ -13,8 +13,6 @@ using namespace elena_lang; void IDEModel :: changeStatus(IDEStatus status) { this->status = status; - - // onIDEChange(); } //void IDEModel :: attachListener(IDEListener* listener) diff --git a/elenasrc3/ide/ideview.h b/elenasrc3/ide/ideview.h index 23f707c96e..299b3888b1 100644 --- a/elenasrc3/ide/ideview.h +++ b/elenasrc3/ide/ideview.h @@ -29,6 +29,7 @@ struct IDEScheme int vmConsoleControl; int toolBarControl; int editorContextMenu; + int textControlId; Map captions; @@ -45,6 +46,7 @@ struct IDEScheme vmConsoleControl(-1), toolBarControl(-1), editorContextMenu(-1), + textControlId(-1), captions(nullptr) { } @@ -55,6 +57,7 @@ class IDEModel { public: IDEStatus status; + bool running; SourceViewModel sourceViewModel; ProjectModel projectModel; @@ -72,6 +75,7 @@ class IDEModel : projectModel(&status) { status = IDEStatus::Empty; + running = false; appMaximized = false; } }; diff --git a/elenasrc3/ide/ideworkspace.h b/elenasrc3/ide/ideworkspace.h deleted file mode 100644 index cae7741256..0000000000 --- a/elenasrc3/ide/ideworkspace.h +++ /dev/null @@ -1,20 +0,0 @@ -//--------------------------------------------------------------------------- -// E L E N A P r o j e c t: ELENA IDE -// EditFrame container File -// (C)2005-2014, by Alexei Rakov -//--------------------------------------------------------------------------- - -#ifndef IDEWORKSPACE_H -#define IDEWORKSPACE_H - -namespace elena_lang -{ - -class IDEWorkspace -{ - -}; - -} // elena:lang - -#endif // IDEWORKSPACE_H diff --git a/elenasrc3/ide/vs/elide.vcxproj b/elenasrc3/ide/vs/elide.vcxproj index a455d835d8..0280228b33 100644 --- a/elenasrc3/ide/vs/elide.vcxproj +++ b/elenasrc3/ide/vs/elide.vcxproj @@ -208,7 +208,6 @@ - diff --git a/elenasrc3/ide/windows/Resource.h b/elenasrc3/ide/windows/Resource.h index bd49d7c431..e87cadc4ec 100644 --- a/elenasrc3/ide/windows/Resource.h +++ b/elenasrc3/ide/windows/Resource.h @@ -115,6 +115,7 @@ #define IDC_SETTINGS_OUTPUT 855 #define IDC_SETTINGS_DEBUG 856 #define IDC_SETTINGS_ARGUMENT 857 +#define IDC_SETTINGS_PROFILE 858 #define IDM_DEBUG_RUN 901 #define IDM_DEBUG_STEPOVER 902 diff --git a/elenasrc3/ide/windows/elide.rc b/elenasrc3/ide/windows/elide.rc index 9c3dcb2d59b0c54c50c76dffabdf39029bc2812e..1c00050b69b6cd5d350251b2a1f95cfd1dec0696 100644 GIT binary patch delta 244 zcmdn8lj*}ArVU=wX0Ss+|*vO%aGqv_=M(2tB}lLN!Df#lw> zwTy<7v%}vr8!;G8z8@etnXg)7vO=K9viewModel(); @@ -227,14 +227,30 @@ ControlBase* IDEFactory :: createTextControl(WindowBase* owner, NotifierBase* no // initialize UI components TextViewWindow* view = new TextViewWindow(notifier, _model->viewModel(), - &_controller->sourceController, &_styles); + &_controller->sourceController, &_styles, [](NotifierBase* notifier, int x, int y, bool hasSelection) + { + ContextMenuEvent event(EVENT_TEXT_CONTEXTMENU, x, y, hasSelection); + + notifier->notify(&event); + }, [](NotifierBase* notifier) + { + SimpleEvent event(EVENT_TEXT_MARGINLICK); + + notifier->notify(&event); + }); + TextViewFrame* frame = new TextViewFrame(notifier, _settings.withTabAboverscore, view, - _model->viewModel(), NOTIFY_TEXTFRAME_SEL); + _model->viewModel(), [](NotifierBase* notifier, int index) + { + SelectionEvent event = { EVENT_TEXTFRAME_SELECTION_CHANGED, index }; + + notifier->notify(&event); + }); view->create(_instance, szTextView, owner); frame->createControl(_instance, owner); - return frame; + return { frame, view }; } void IDEFactory :: reloadStyles(TextViewModelBase* viewModel) @@ -261,10 +277,14 @@ ControlBase* IDEFactory :: createTabBar(WindowBase* owner, NotifierBase* notifie return tabBar; } -ControlBase* IDEFactory :: createSplitter(WindowBase* owner, ControlBase* client, bool vertical, NotifierBase* notifier, - int notifyCode, NotificationStatus notifyStatus) +ControlBase* IDEFactory :: createSplitter(WindowBase* owner, ControlBase* client, bool vertical, NotifierBase* notifier) { - Splitter* splitter = new Splitter(notifier, notifyCode, notifyStatus, client, vertical); + Splitter* splitter = new Splitter(notifier, client, vertical, [](NotifierBase* notifier) + { + LayoutEvent event(STATUS_LAYOUT_CHANGED); + + notifier->notify(&event); + }); splitter->create(_instance, vertical ? szVSplitter : szHSplitter, @@ -286,7 +306,12 @@ ControlBase* IDEFactory :: createVmConsoleControl(ControlBase* owner, ProcessBas ControlBase* IDEFactory :: createCompilerOutput(ControlBase* owner, ProcessBase* outputProcess, NotifierBase* notifier) { - CompilerOutput* output = new CompilerOutput(notifier, NOTIFY_COMPILATION_RESULT); + CompilerOutput* output = new CompilerOutput(notifier, [](NotifierBase* notifier, int statusBar) + { + SelectionEvent event = { EVENT_COMPILATION_END, statusBar }; + + notifier->notify(&event); + }); output->createControl(_instance, owner); @@ -297,7 +322,12 @@ ControlBase* IDEFactory :: createCompilerOutput(ControlBase* owner, ProcessBase* ControlBase* IDEFactory :: createErrorList(ControlBase* owner, NotifierBase* notifier) { - MessageLog* log = new MessageLog(notifier, NOTIFY_ERROR_SEL); + MessageLog* log = new MessageLog(notifier, [](NotifierBase* notifier, int index) + { + SelectionEvent event = { EVENT_ERRORLIST_SELECTION, index }; + + notifier->notify(&event); + }); log->createControl(_instance, owner); return log; @@ -305,8 +335,13 @@ ControlBase* IDEFactory :: createErrorList(ControlBase* owner, NotifierBase* not ControlBase* IDEFactory :: createProjectView(ControlBase* owner, NotifierBase* notifier) { - TreeView* projectView = new TreeView(300, 50, notifier, - NOTIFY_PROJECTVIEW_SEL, true); + TreeView* projectView = new TreeView(300, 50, notifier, true, + [](NotifierBase* notifier, size_t param) + { + ParamSelectionEvent event = { EVENT_PROJECTVIEW_SELECTION_CHANGED, param }; + + notifier->notify(&event); + }); projectView->createControl(_instance, owner); return projectView; @@ -314,7 +349,13 @@ ControlBase* IDEFactory :: createProjectView(ControlBase* owner, NotifierBase* n ControlBase* IDEFactory :: createDebugBrowser(ControlBase* owner, NotifierBase* notifier) { - ContextBrowser* browser = new ContextBrowser(300, 50, notifier, NOTIFY_DEBUG_CONTEXT_EXPANDED); + ContextBrowser* browser = new ContextBrowser(300, 50, notifier, + [](NotifierBase* notifier, size_t item, size_t param) + { + BrowseEvent event = { EVENT_BROWSE_CONTEXT, item, param }; + + notifier->notify(&event); + }); browser->createControl(_instance, owner); browser->hide(); @@ -358,7 +399,7 @@ GUIControlBase* IDEFactory :: createToolbar(ControlBase* owner) void IDEFactory :: initializeScheme(int frameTextIndex, int tabBar, int compilerOutput, int errorList, int projectView, int contextBrowser, int menu, int statusBar, int debugContextMenu, int vmConsoleControl, - int toolBarControl, int contextEditor) + int toolBarControl, int contextEditor, int textIndex) { LoadStringW(_instance, IDC_COMPILER_OUTPUT, szCompilerOutput, MAX_LOADSTRING); LoadStringW(_instance, IDC_COMPILER_MESSAGES, szErrorList, MAX_LOADSTRING); @@ -377,6 +418,7 @@ void IDEFactory :: initializeScheme(int frameTextIndex, int tabBar, int compiler _model->ideScheme.vmConsoleControl = vmConsoleControl; _model->ideScheme.toolBarControl = toolBarControl; _model->ideScheme.editorContextMenu = contextEditor; + _model->ideScheme.textControlId = textIndex; _model->ideScheme.captions.add(compilerOutput, szCompilerOutput); _model->ideScheme.captions.add(errorList, szErrorList); @@ -386,7 +428,7 @@ void IDEFactory :: initializeScheme(int frameTextIndex, int tabBar, int compiler GUIApp* IDEFactory :: createApp() { - WindowApp* app = new WindowApp(_instance, MAKEINTRESOURCE(IDC_IDE)); + WindowApp* app = new WindowApp(_instance, MAKEINTRESOURCE(IDC_IDE), &IDENotificationFormatter::getInstance()); registerClasses(); @@ -396,7 +438,7 @@ GUIApp* IDEFactory :: createApp() GUIControlBase* IDEFactory :: createMainWindow(NotifierBase* notifier, ProcessBase* outputProcess, ProcessBase* vmConsoleProcess) { - GUIControlBase* children[15]; + GUIControlBase* children[16]; int counter = 0; int textIndex = counter++; @@ -414,35 +456,37 @@ GUIControlBase* IDEFactory :: createMainWindow(NotifierBase* notifier, ProcessBa int vmConsoleControl = counter++; int toolBarControl = counter++; int contextEditor = counter++; + int editIndex = counter++; SDIWindow* sdi = new IDEWindow(szTitle, _controller, _model, _instance, this); sdi->create(_instance, szSDI, nullptr); VerticalBox* vb = new VerticalBox(false, 1); - children[textIndex] = createTextControl(sdi, notifier); + auto textCtrls = createTextControl(sdi, notifier); + + children[textIndex] = textCtrls.value1; children[bottomBox] = vb; children[tabBar] = createTabBar(sdi, notifier); - children[vsplitter] = createSplitter(sdi, (ControlBase*)children[tabBar], false, notifier, - NOTIFY_IDE_CHANGE, IDE_LAYOUT_CHANGED); + children[vsplitter] = createSplitter(sdi, (ControlBase*)children[tabBar], false, notifier); children[statusBarIndex] = createStatusbar(sdi); children[compilerOutput] = createCompilerOutput((ControlBase*)children[tabBar], outputProcess, notifier); children[errorList] = createErrorList((ControlBase*)children[tabBar], notifier); children[browser] = createDebugBrowser((ControlBase*)children[tabBar], notifier); children[projectView] = createProjectView(sdi, notifier); - children[hsplitter] = createSplitter(sdi, (ControlBase*)children[projectView], true, notifier, - NOTIFY_IDE_CHANGE, IDE_LAYOUT_CHANGED); + children[hsplitter] = createSplitter(sdi, (ControlBase*)children[projectView], true, notifier); children[menu] = createMenu(sdi); children[debugContextMenu] = createDebugContextMenu(sdi); children[vmConsoleControl] = createVmConsoleControl((ControlBase*)children[tabBar], vmConsoleProcess); children[toolBarControl] = createToolbar(sdi); children[contextEditor] = createEditorContextMenu(sdi); + children[editIndex] = textCtrls.value2; vb->append(children[vsplitter]); vb->append(children[statusBarIndex]); initializeScheme(textIndex, tabBar, compilerOutput, errorList, projectView, browser, menu, statusBarIndex, - debugContextMenu, vmConsoleControl, toolBarControl, contextEditor); + debugContextMenu, vmConsoleControl, toolBarControl, contextEditor, editIndex); sdi->populate(counter, children); sdi->setLayout(textIndex, toolBarControl, bottomBox, -1, hsplitter); diff --git a/elenasrc3/ide/windows/factory.h b/elenasrc3/ide/windows/factory.h index 84de22ecd5..f72db927cf 100644 --- a/elenasrc3/ide/windows/factory.h +++ b/elenasrc3/ide/windows/factory.h @@ -16,6 +16,8 @@ namespace elena_lang { + typedef Pair ControlPair; + // --- IDEFactory --- class IDEFactory : public GUIFactoryBase, public ViewFactoryBase { @@ -33,11 +35,10 @@ namespace elena_lang void registerClasses(); - ControlBase* createTextControl(WindowBase* owner, NotifierBase* notifier); + ControlPair createTextControl(WindowBase* owner, NotifierBase* notifier); ControlBase* createStatusbar(WindowBase* owner); ControlBase* createTabBar(WindowBase* owner, NotifierBase* notifier); - ControlBase* createSplitter(WindowBase* owner, ControlBase* client, bool vertical, NotifierBase* notifier, - int notifyCode, NotificationStatus status); + ControlBase* createSplitter(WindowBase* owner, ControlBase* client, bool vertical, NotifierBase* notifier); ControlBase* createCompilerOutput(ControlBase* owner, ProcessBase* outputProcess, NotifierBase* notifier); ControlBase* createErrorList(ControlBase* owner, NotifierBase* notifier); ControlBase* createProjectView(ControlBase* owner, NotifierBase* notifier); @@ -50,7 +51,7 @@ namespace elena_lang void initializeScheme(int frameTextIndex, int tabBar, int compilerOutput, int errorList, int projectView, int contextBrowser, int menu, int statusBar, int debugContextMenu, - int vmConsoleOutput, int toolBarControl, int contextEditor); + int vmConsoleOutput, int toolBarControl, int contextEditor, int textIndex); public: void reloadStyles(TextViewModelBase* viewModel) override; diff --git a/elenasrc3/ide/windows/main.cpp b/elenasrc3/ide/windows/main.cpp index 6b38296ee8..1ed506e1fa 100644 --- a/elenasrc3/ide/windows/main.cpp +++ b/elenasrc3/ide/windows/main.cpp @@ -51,6 +51,14 @@ class PathHelper : public PathHelperBase } }; +bool compareFileModifiedTime(path_t sour, path_t dest) +{ + DateTime sourceDT = DateTime::getFileTime(sour); + DateTime moduleDT = DateTime::getFileTime(dest); + + return sourceDT > moduleDT; +} + typedef Win32DebugProcess DebugProcess; // Forward declarations of functions included in this code module: @@ -79,7 +87,7 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance, Win32Process outputProcess(50); DebugProcess debugProcess; IDEController ideController(&outputProcess, &vmConsoleProcess, &debugProcess, &ideModel, - textViewSettings, CURRENT_PLATFORM, &pathHelper); + textViewSettings, CURRENT_PLATFORM, &pathHelper, compareFileModifiedTime); IDEFactory factory(hInstance, &ideModel, &ideController, guiSettings); PathString configPath(ideModel.projectModel.paths.appPath); @@ -95,9 +103,10 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance, ideController.setNotifier(app); - int retVal = app->run(ideWindow, ideModel.appMaximized, NOTIFY_ONSTART, IDE_ONSTART); + StartUpEvent startUpEvent(STATUS_NONE); + int retVal = app->run(ideWindow, ideModel.appMaximized, &startUpEvent); - ideController.onProgramStop(&ideModel); + ideController.onIDEStop(&ideModel); delete app; diff --git a/elenasrc3/ide/windows/win32debugprocess.cpp b/elenasrc3/ide/windows/win32debugprocess.cpp index 7143ca262b..112a89d0ef 100644 --- a/elenasrc3/ide/windows/win32debugprocess.cpp +++ b/elenasrc3/ide/windows/win32debugprocess.cpp @@ -2,7 +2,7 @@ // E L E N A P r o j e c t: ELENA Engine // // This file contains the Win32 Debugger class and its helpers implementation -// (C)2021-2022, by Aleksey Rakov +// (C)2021-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #include "elena.h" @@ -190,6 +190,11 @@ unsigned char Win32ThreadContext :: setSoftwareBreakpoint(addr_t breakpoint) return code; } +void Win32ThreadContext :: clearSoftwareBreakpoint(addr_t breakpoint, unsigned char substitute) +{ + writeDump(breakpoint, (char*)&substitute, 1); +} + void Win32ThreadContext :: setHardwareBreakpoint(addr_t breakpoint) { context.ContextFlags = CONTEXT_DEBUG_REGISTERS; @@ -246,6 +251,19 @@ void Win32BreakpointContext :: addBreakpoint(addr_t address, Win32ThreadContext* else breakpoints.add(address, 0); } +void Win32BreakpointContext :: removeBreakpoint(addr_t address, Win32ThreadContext* context, bool started) +{ + if (started) { + context->clearSoftwareBreakpoint(address, breakpoints.get(address)); + if (context->breakpoint.software && context->breakpoint.next == address) { + + context->breakpoint.clearSoftware(); + context->resetTrapFlag(); + } + } + breakpoints.erase(address); +} + void Win32BreakpointContext :: setSoftwareBreakpoints(Win32ThreadContext* context) { Map::Iterator breakpoint = breakpoints.start(); @@ -624,6 +642,11 @@ void Win32DebugProcess :: addBreakpoint(addr_t address) _breakpoints.addBreakpoint(address, _current, started); } +void Win32DebugProcess :: removeBreakpoint(addr_t address) +{ + _breakpoints.removeBreakpoint(address, _current, started); +} + void Win32DebugProcess :: setStepMode() { // !! temporal diff --git a/elenasrc3/ide/windows/win32debugprocess.h b/elenasrc3/ide/windows/win32debugprocess.h index 6102392099..1df17c223d 100644 --- a/elenasrc3/ide/windows/win32debugprocess.h +++ b/elenasrc3/ide/windows/win32debugprocess.h @@ -2,7 +2,7 @@ // E L E N A P r o j e c t: ELENA Engine // // This file contains the Win32 Debugger class and its helpers header -// (C)2021-2023, by Aleksey Rakov +// (C)2021-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #ifndef WIN32DEBUGPROCESS_H @@ -85,7 +85,9 @@ namespace elena_lang void resetTrapFlag(); void setHardwareBreakpoint(addr_t breakpoint); void clearHardwareBreakpoint(); + unsigned char setSoftwareBreakpoint(addr_t breakpoint); + void clearSoftwareBreakpoint(addr_t breakpoint, unsigned char substitute); void setIP(addr_t address); @@ -98,7 +100,7 @@ namespace elena_lang Map breakpoints; void addBreakpoint(addr_t address, Win32ThreadContext* context, bool started); - //void removeBreakpoint(size_t address, Win32ThreadContext* context, bool started); + void removeBreakpoint(addr_t address, Win32ThreadContext* context, bool started); void setSoftwareBreakpoints(Win32ThreadContext* context); void setHardwareBreakpoint(addr_t address, Win32ThreadContext* context, bool withStackLevelControl); @@ -241,6 +243,7 @@ namespace elena_lang void setBreakpoint(addr_t address, bool withStackLevelControl) override; void addBreakpoint(addr_t address) override; + void removeBreakpoint(addr_t address) override; void addStep(addr_t address, void* current) override; diff --git a/elenasrc3/ide/windows/wincontextbrowser.cpp b/elenasrc3/ide/windows/wincontextbrowser.cpp index 70e0b60a14..3eabf5e552 100644 --- a/elenasrc3/ide/windows/wincontextbrowser.cpp +++ b/elenasrc3/ide/windows/wincontextbrowser.cpp @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------- // E L E N A P r o j e c t: ELENA IDE // WinAPI IDE Debug Context Browser Implementation File -// (C)2022, by Aleksey Rakov +// (C)2022-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #include "wincontextbrowser.h" @@ -17,10 +17,10 @@ typedef String CaptrionString; // --- ContextBrowser -- -ContextBrowser :: ContextBrowser(int width, int height, NotifierBase* notifier, int expandNotificationId) - : TreeView(width, height, notifier, 0, false, false), _rootItem(nullptr) +ContextBrowser :: ContextBrowser(int width, int height, NotifierBase* notifier, BrowseEventInvoker browseInvoker) + : TreeView(width, height, notifier, false, nullptr, false), _rootItem(nullptr) { - _expandNotificationId = expandNotificationId; + _browseInvoker = browseInvoker; } HWND ContextBrowser :: createControl(HINSTANCE instance, ControlBase* owner) @@ -156,7 +156,7 @@ void ContextBrowser :: removeUnused(WatchItems& refreshedItems) void ContextBrowser :: onItemExpand(TreeViewItem item) { - _notifier->notifyTreeItem(_expandNotificationId, (size_t)item, getParam(item)); + _browseInvoker(_notifier, (size_t)item, getParam(item)); } void ContextBrowser :: expandNode(size_t param) @@ -168,6 +168,6 @@ void ContextBrowser :: refreshCurrentNode() { TreeViewItem current = getCurrent(); - _notifier->notifyTreeItem(_expandNotificationId, (size_t)current, getParam(current)); + _browseInvoker(_notifier, (size_t)current, getParam(current)); } diff --git a/elenasrc3/ide/windows/wincontextbrowser.h b/elenasrc3/ide/windows/wincontextbrowser.h index 5fcfbe8fbe..34f4219aee 100644 --- a/elenasrc3/ide/windows/wincontextbrowser.h +++ b/elenasrc3/ide/windows/wincontextbrowser.h @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------- // E L E N A P r o j e c t: ELENA IDE // WinAPI IDE Debug Context Browser Header File -// (C)2022-2023, by Aleksey Rakov +// (C)2022-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #ifndef WINCONTEXTBROWSER_H @@ -14,8 +14,12 @@ namespace elena_lang { class ContextBrowser : public TreeView, public ContextBrowserBase { - TreeViewItem _rootItem; - int _expandNotificationId; + public: + typedef void(*BrowseEventInvoker)(NotifierBase*, size_t, size_t); + + private: + TreeViewItem _rootItem; + BrowseEventInvoker _browseInvoker; void* findWatchNodeStartingWith(WatchContext* root, ustr_t name) override; @@ -39,7 +43,7 @@ namespace elena_lang void removeUnused(WatchItems& refreshedItems) override; - ContextBrowser(int width, int height, NotifierBase* notifier, int expandNotificationId); + ContextBrowser(int width, int height, NotifierBase* notifier, BrowseEventInvoker browseInvoker); }; } diff --git a/elenasrc3/ide/windows/windialogs.cpp b/elenasrc3/ide/windows/windialogs.cpp index f3f3613288..993a62d947 100644 --- a/elenasrc3/ide/windows/windialogs.cpp +++ b/elenasrc3/ide/windows/windialogs.cpp @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------- // E L E N A P r o j e c t: ELENA IDE // WinAPI: Static dialog implementations -// (C)2021-2023, by Aleksey Rakov +// (C)2021-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #include @@ -302,6 +302,24 @@ void ProjectSettings :: loadTemplateList() setComboBoxIndex(IDC_SETTINGS_TEPMPLATE, selected); } +void ProjectSettings :: loadProfileList() +{ + int selected = 0; + int current = 0; + for (auto it = _model->profileList.start(); !it.eof(); ++it) { + ustr_t key = *it; + if (_model->profile.compare(key)) { + selected = current; + } + + WideMessage caption(key); + addComboBoxItem(IDC_SETTINGS_PROFILE, *caption); + current++; + } + + setComboBoxIndex(IDC_SETTINGS_PROFILE, selected); +} + void ProjectSettings :: onCreate() { setTextLimit(IDC_SETTINGS_PACKAGE, IDENTIFIER_LEN); @@ -329,6 +347,7 @@ void ProjectSettings :: onCreate() //else setComboBoxIndex(IDC_SETTINGS_DEBUG, 0); loadTemplateList(); + loadProfileList(); } void ProjectSettings :: onOK() @@ -342,6 +361,13 @@ void ProjectSettings :: onOK() _model->templateName.copy(*value); } + if (getComboBoxIndex(IDC_SETTINGS_PROFILE) != -1) { + getText(IDC_SETTINGS_PROFILE, (wchar_t**)(&name), IDENTIFIER_LEN); + + IdentifierString value(name); + _model->profile.copy(*value); + } + getText(IDC_SETTINGS_PACKAGE, (wchar_t**)(&name), IDENTIFIER_LEN); if (getlength(name) > 0) { IdentifierString value(name); diff --git a/elenasrc3/ide/windows/windialogs.h b/elenasrc3/ide/windows/windialogs.h index 5b8e243f70..ddc9916460 100644 --- a/elenasrc3/ide/windows/windialogs.h +++ b/elenasrc3/ide/windows/windialogs.h @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------- // E L E N A P r o j e c t: ELENA IDE // Win32: Static dialogs header -// (C)2021-2023, by Aleksey Rakov +// (C)2021-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #ifndef WINDIALOGS_H @@ -116,6 +116,7 @@ namespace elena_lang ProjectModel* _model; void loadTemplateList(); + void loadProfileList(); void onCreate() override; void onOK() override; diff --git a/elenasrc3/ide/windows/winide.cpp b/elenasrc3/ide/windows/winide.cpp index bb9ee62ed9..1d90589a9b 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-2023, by Aleksey Rakov +// (C)2021-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #include @@ -108,6 +108,137 @@ bool Clipboard :: isAvailable() return (::IsClipboardFormatAvailable(CF_UNICODETEXT) == TRUE); } +// --- IDENotificationFormatter --- + +void IDENotificationFormatter :: sendTextViewModelEvent(TextViewModelEvent* event, WindowApp* app) +{ + TextViewModelNMHDR nw = { }; + nw.docStatus = event->changeStatus; + nw.status = event->status; + + app->notify(EVENT_TEXTVIEW_MODEL_CHANGED, (NMHDR*)&nw); +} + +void IDENotificationFormatter :: sendTextFrameSelectionEvent(SelectionEvent* event, WindowApp* app) +{ + SelectionNMHDR nw = { }; + nw.index = event->Index(); + nw.status = event->status; + + app->notify(EVENT_TEXTFRAME_SELECTION_CHANGED, (NMHDR*)&nw); +} + +void IDENotificationFormatter :: sendCompilationEndEvent(SelectionEvent* event, WindowApp* app) +{ + SelectionNMHDR nw = { }; + nw.index = event->Index(); + nw.status = event->status; + + app->notify(EVENT_COMPILATION_END, (NMHDR*)&nw); +} + +void IDENotificationFormatter :: sendErrorListSelEvent(SelectionEvent* event, WindowApp* app) +{ + SelectionNMHDR nw = { }; + nw.index = event->Index(); + nw.status = event->status; + + app->notify(EVENT_ERRORLIST_SELECTION, (NMHDR*)&nw); +} + +void IDENotificationFormatter :: sendProjectViewSelectionEvent(ParamSelectionEvent* event, WindowApp* app) +{ + ParamSelectionNMHDR nw = { }; + nw.param = event->Param(); + nw.status = event->status; + + app->notify(EVENT_PROJECTVIEW_SELECTION_CHANGED, (NMHDR*)&nw); +} + +void IDENotificationFormatter :: sendStartUpEvent(StartUpEvent* event, WindowApp* app) +{ + ModelNMHDR nw = { }; + nw.status = event->status; + + app->notify(EVENT_STARTUP, (NMHDR*)&nw); +} + + +void IDENotificationFormatter :: sendLayoutEvent(LayoutEvent* event, WindowApp* app) +{ + ModelNMHDR nw = { }; + nw.status = event->status; + + app->notify(EVENT_LAYOUT, (NMHDR*)&nw); +} + +void IDENotificationFormatter :: sendTextContextMenuEvent(ContextMenuEvent* event, WindowApp* app) +{ + ContextMenuNMHDR nw = {}; + + nw.x = event->X(); + nw.y = event->X(); + nw.hasSelection = event->HasSelection(); + + app->notify(EVENT_TEXT_CONTEXTMENU, (NMHDR*)&nw); +} + +void IDENotificationFormatter :: sendBrowseContextMenuEvent(BrowseEvent* event, WindowApp* app) +{ + BrowseNMHDR nw = {}; + + nw.item = event->Item(); + nw.param = event->Param(); + + app->notify(EVENT_BROWSE_CONTEXT, (NMHDR*)&nw); +} + +void IDENotificationFormatter :: sendSimpleEvent(SimpleEvent* event, WindowApp* app) +{ + NMHDR nw = {}; + + app->notify(EVENT_TEXT_MARGINLICK, (NMHDR*)&nw); +} + +void IDENotificationFormatter :: sendMessage(EventBase* event, WindowApp* app) +{ + switch (event->eventId()) { + case EVENT_TEXTVIEW_MODEL_CHANGED: + sendTextViewModelEvent(dynamic_cast(event), app); + break; + case EVENT_TEXTFRAME_SELECTION_CHANGED: + sendTextFrameSelectionEvent(dynamic_cast(event), app); + break; + case EVENT_STARTUP: + sendStartUpEvent(dynamic_cast(event), app); + break; + case EVENT_LAYOUT: + sendLayoutEvent(dynamic_cast(event), app); + break; + case EVENT_PROJECTVIEW_SELECTION_CHANGED: + sendProjectViewSelectionEvent(dynamic_cast(event), app); + break; + case EVENT_COMPILATION_END: + sendCompilationEndEvent(dynamic_cast(event), app); + break; + case EVENT_ERRORLIST_SELECTION: + sendErrorListSelEvent(dynamic_cast(event), app); + break; + case EVENT_TEXT_CONTEXTMENU: + sendTextContextMenuEvent(dynamic_cast(event), app); + break; + case EVENT_BROWSE_CONTEXT: + sendBrowseContextMenuEvent(dynamic_cast(event), app); + break; + case EVENT_TEXT_MARGINLICK: + sendSimpleEvent(dynamic_cast(event), app); + break; + default: + assert(false); + break; + } +} + // --- IDEWindow --- IDEWindow :: IDEWindow(wstr_t title, IDEController* controller, IDEModel* model, HINSTANCE instance, ViewFactoryBase* viewFactory) : @@ -131,15 +262,14 @@ IDEWindow :: IDEWindow(wstr_t title, IDEController* controller, IDEModel* model, _recentFileList(controller, model, IDM_FILE_FILES), _recentProjectList(controller, model, IDM_FILE_PROJECTS), aboutDialog(instance, this), - editorSettingsDialog(instance, this, model->viewModel()) + editorSettingsDialog(instance, this, model->viewModel()), + _docViewListener(nullptr) { this->_viewFactory = viewFactory; this->_instance = instance; this->_controller = controller; this->_model = model; - - model->sourceViewModel.attachDocListener(this); } void IDEWindow :: onActivate() @@ -338,7 +468,7 @@ void IDEWindow :: openResultTab(int controlIndex) if (!resultBar->visible()) { resultBar->show(); - onLayoutChange(IDE_LAYOUT_CHANGED); + onLayoutChange(); } } @@ -352,10 +482,10 @@ void IDEWindow :: closeResultTab(int controlIndex) if (resultBar->empty()) { resultBar->hide(); + + onLayoutChange(); } else resultBar->selectTab(0); - - onLayoutChange(IDE_LAYOUT_CHANGED); } void IDEWindow :: toggleWindow(int child_id) @@ -387,6 +517,10 @@ void IDEWindow :: setChildFocus(int controlIndex) void IDEWindow :: onComilationStart() { + updateCompileMenu(false, false, true); + + openResultTab(_model->ideScheme.compilerOutputControl); + ((ControlBase*)_children[_model->ideScheme.compilerOutputControl])->clearValue(); } @@ -409,11 +543,12 @@ void IDEWindow :: onErrorHighlight(int index) _controller->highlightError(_model, messageInfo.row, messageInfo.column, messageInfo.path); } -void IDEWindow :: onProjectViewSel(int index) +void IDEWindow :: onDebugStep() { - _controller->doOpenProjectSourceByIndex(_model, index); + MenuBase* menu = dynamic_cast(_children[_model->ideScheme.menu]); + menu->enableMenuItemById(IDM_DEBUG_STOP, true); - _children[_model->ideScheme.textFrameId]->setFocus(); + _controller->onDebuggerStep(_model); } void IDEWindow :: onDebugWatch() @@ -427,11 +562,20 @@ void IDEWindow :: onDebugWatch() contextBrowser->expandRootNode(); } -void IDEWindow :: onDebugWatchBrowse(size_t item, size_t param) +void IDEWindow :: onDebugEnd() { - if (param) { + ContextBrowserBase* contextBrowser = dynamic_cast(_children[_model->ideScheme.debugWatch]); + + contextBrowser->clearRootNode(); + + _controller->onDebuggerStop(_model); +} + +void IDEWindow :: onDebugWatchBrowse(BrowseNMHDR* rec) +{ + if (rec->param) { ContextBrowserBase* contextBrowser = dynamic_cast(_children[_model->ideScheme.debugWatch]); - _controller->refreshDebugContext(contextBrowser, _model, item, param); + _controller->refreshDebugContext(contextBrowser, _model, rec->item, rec->param); } } @@ -447,6 +591,28 @@ void IDEWindow :: enableMenuItemById(int id, bool doEnable, bool toolBarItemAvai } } +void IDEWindow :: updateCompileMenu(bool compileEnable, bool debugEnable, bool stopEnable) +{ + enableMenuItemById(IDM_PROJECT_COMPILE, compileEnable, false); + enableMenuItemById(IDM_PROJECT_OPTION, compileEnable, false); + enableMenuItemById(IDM_PROJECT_INCLUDE, compileEnable, false); + + enableMenuItemById(IDM_DEBUG_RUN, debugEnable, true); + enableMenuItemById(IDM_DEBUG_STEPINTO, debugEnable, true); + enableMenuItemById(IDM_DEBUG_STEPOVER, debugEnable, true); + enableMenuItemById(IDM_DEBUG_RUNTO, debugEnable, false); + + enableMenuItemById(IDM_DEBUG_STOP, stopEnable, true); +} + +void IDEWindow :: onProjectRefresh(bool empty) +{ + updateCompileMenu(!empty, !empty, false); + + enableMenuItemById(IDM_PROJECT_CLOSE, !empty, true); + enableMenuItemById(IDM_FILE_SAVEPROJECT, !empty, false); +} + void IDEWindow :: onProjectChange(bool empty) { TreeView* projectTree = dynamic_cast(_children[_model->ideScheme.projectView]); @@ -502,125 +668,7 @@ void IDEWindow :: onProjectChange(bool empty) toggleProjectView(!empty); - enableMenuItemById(IDM_PROJECT_CLOSE, !empty, true); - enableMenuItemById(IDM_FILE_SAVEPROJECT, !empty, false); - - enableMenuItemById(IDM_PROJECT_COMPILE, !empty, false); - enableMenuItemById(IDM_PROJECT_OPTION, !empty, false); - enableMenuItemById(IDM_DEBUG_RUN, !empty, true); - enableMenuItemById(IDM_DEBUG_STEPINTO, !empty, true); - enableMenuItemById(IDM_DEBUG_STEPOVER, !empty, true); - enableMenuItemById(IDM_DEBUG_RUNTO, !empty, false); - enableMenuItemById(IDM_DEBUG_STOP, !empty, true); -} - -void IDEWindow :: onLayoutChange(NotificationStatus status) -{ - bool empty = _model->sourceViewModel.getDocumentCount() == 0; - - if (test(status, FRAME_VISIBILITY_CHANGED)) { - if (!empty) { - _children[_model->ideScheme.textFrameId]->show(); - _children[_model->ideScheme.textFrameId]->setFocus(); - } - else _children[_model->ideScheme.textFrameId]->hide(); - } - if (test(status, PROJECT_CHANGED)) { - onProjectChange(_model->projectModel.empty); - } - - MenuBase* menu = dynamic_cast(_children[_model->ideScheme.menu]); - menu->checkMenuItemById(IDM_VIEW_OUTPUT, _children[_model->ideScheme.compilerOutputControl]->visible()); - menu->checkMenuItemById(IDM_VIEW_PROJECTVIEW, _children[_model->ideScheme.projectView]->visible()); - menu->checkMenuItemById(IDM_VIEW_MESSAGES, _children[_model->ideScheme.errorListControl]->visible()); - menu->checkMenuItemById(IDM_VIEW_WATCH, _children[_model->ideScheme.debugWatch]->visible()); - menu->checkMenuItemById(IDM_VIEW_VMCONSOLE, _children[_model->ideScheme.vmConsoleControl]->visible()); - - enableMenuItemById(IDM_FILE_SAVE, !empty, true); - enableMenuItemById(IDM_FILE_SAVEALL, !empty, true); - enableMenuItemById(IDM_FILE_SAVEAS, !empty, false); - enableMenuItemById(IDM_FILE_CLOSE, !empty, true); - enableMenuItemById(IDM_FILE_CLOSEALL, !empty, false); - - if (empty) { - enableMenuItemById(IDM_EDIT_UNDO, false, true); - enableMenuItemById(IDM_EDIT_REDO, false, true); - - enableMenuItemById(IDM_EDIT_CUT, false, true); - enableMenuItemById(IDM_EDIT_COPY, false, true); - enableMenuItemById(IDM_EDIT_PASTE, false, true); - - enableMenuItemById(IDM_PROJECT_INCLUDE, false, false); - } - else { - enableMenuItemById(IDM_EDIT_PASTE, true, true); - - enableMenuItemById(IDM_PROJECT_INCLUDE, true, false); - } - - enableMenuItemById(IDM_EDIT_DELETE, !empty, false); - enableMenuItemById(IDM_EDIT_COMMENT, !empty, false); - enableMenuItemById(IDM_EDIT_UNCOMMENT, !empty, false); - - enableMenuItemById(IDM_EDIT_DUPLICATE, !empty, false); - enableMenuItemById(IDM_EDIT_SELECTALL, !empty, false); - enableMenuItemById(IDM_EDIT_ERASELINE, !empty, false); - enableMenuItemById(IDM_EDIT_INDENT, !empty, false); - enableMenuItemById(IDM_EDIT_OUTDENT, !empty, false); - enableMenuItemById(IDM_EDIT_TRIM, !empty, false); - enableMenuItemById(IDM_EDIT_UPPERCASE, !empty, false); - enableMenuItemById(IDM_EDIT_LOWERCASE, !empty, false); - - enableMenuItemById(IDM_SEARCH_FIND, !empty, false); - enableMenuItemById(IDM_SEARCH_FINDNEXT, !empty, false); - enableMenuItemById(IDM_SEARCH_REPLACE, !empty, false); - enableMenuItemById(IDM_SEARCH_GOTOLINE, !empty, false); - - enableMenuItemById(IDM_WINDOW_WINDOWS, !empty, false); - enableMenuItemById(IDM_WINDOW_NEXT, !empty, false); - enableMenuItemById(IDM_WINDOW_PREVIOUS, !empty, false); - - enableMenuItemById(IDM_DEBUG_CLEARBREAKPOINT, !empty, false); - enableMenuItemById(IDM_DEBUG_BREAKPOINT, !empty, false); - - onResize(); - - if (!empty) - _children[_model->ideScheme.textFrameId]->refresh(); -} - -void IDEWindow :: onTextFrameChange(NotificationStatus status) -{ - DocumentChangeStatus changeStatus = { test(status, FRAME_CHANGED) }; - - if (_model->sourceViewModel.DocView()) - _model->sourceViewModel.DocView()->notifyOnChange(changeStatus); -} - -void IDEWindow :: onIDEChange(NotificationStatus status) -{ - if (test(status, COLOR_SCHEME_CHANGED)) { - onColorSchemeChange(); - } - - if (test(status, IDE_LAYOUT_CHANGED)) { - onLayoutChange(status); - } - - if (test(status, FRAME_CHANGED)) { - onTextFrameChange(status); - } - - if (test(status, IDE_STATUS_CHANGED)) { - _children[_model->ideScheme.statusBar]->refresh(); - } - - if (test(status, IDE_COMPILATION_STARTED)) - onComilationStart(); - - if (test(status, FRAME_ACTIVATE)) { - onActivate(); - } + onProjectRefresh(empty); } bool IDEWindow :: onCommand(int command) @@ -733,16 +781,16 @@ bool IDEWindow :: onCommand(int command) _controller->doChangeProject(projectSettingsDialog, _model); break; case IDM_DEBUG_RUN: - _controller->doDebugAction(_model, DebugAction::Run); + _controller->doDebugAction(_model, DebugAction::Run, messageDialog); break; case IDM_DEBUG_STEPOVER: - _controller->doDebugAction(_model, DebugAction::StepOver); + _controller->doDebugAction(_model, DebugAction::StepOver, messageDialog); break; case IDM_DEBUG_STEPINTO: - _controller->doDebugAction(_model, DebugAction::StepInto); + _controller->doDebugAction(_model, DebugAction::StepInto, messageDialog); break; case IDM_DEBUG_RUNTO: - _controller->doDebugAction(_model, DebugAction::RunTo); + _controller->doDebugAction(_model, DebugAction::RunTo, messageDialog); break; case IDM_DEBUG_STOP: _controller->doDebugStop(_model); @@ -850,83 +898,6 @@ void IDEWindow :: refreshDebugNode() dynamic_cast(_children[_model->ideScheme.debugWatch])->refreshCurrentNode(); } -void IDEWindow :: onStatusChange(StatusNMHDR* rec) -{ - switch (rec->code) { - case NOTIFY_ONSTART: - _controller->init(_model); - _recentFileList.assignList(&_model->projectModel.lastOpenFiles); - _recentProjectList.assignList(&_model->projectModel.lastOpenProjects); - break; - case NOTIFY_IDE_CHANGE: - onIDEChange(rec->status); - break; - case NOTIFY_DEBUG_START: - onDebuggerStart(); - break; - case NOTIFY_DEBUG_LOAD: - onDebuggerHook(); - break; - case NOTIFY_DEBUG_CHANGE: - onDebuggerUpdate(rec); - break; - case NOTIFY_DEBUG_NOSOURCE: - onDebuggerSourceNotFound(rec); - break; - default: - break; - } -} - -//void IDEWindow :: onModelChange(ExtNMHDR* hdr) -//{ - //auto docView = _model->sourceViewModel.DocView(); - - //switch (hdr->extParam1) { - // case NOTIFY_ONSTART: - // - // break; - // case NOTIFY_SOURCEMODEL: - // docView->notifyOnChange(); - // break; - // case NOTIFY_DEBUGWATCH: - // onDebugWatch(); - // break; - // case NOTIFY_CURRENTVIEW_SHOW: - // _children[_model->ideScheme.textFrameId]->show(); - // onResize(); - // break; - // case NOTIFY_CURRENTVIEW_HIDE: - // _children[_model->ideScheme.textFrameId]->hide(); - // onResize(); - // break; - // case NOTIFY_LAYOUT_CHANGED: - // onLayoutChange(); - // break; - // default: - // break; - //} -//} - -//void IDEWindow :: onNotifyMessage(ExtNMHDR* hdr) -//{ - //auto docView = _model->sourceViewModel.DocView(); - - //switch (hdr->extParam1) { - // case NOTIFY_ACTIVATE_EDITFRAME: - // setChildFocus(_model->ideScheme.textFrameId); - // break; - // case NOTIFY_LAYOUT_CHANGED: - // onLayoutChange(); - // break; - // case NOTIFY_REFRESH: - // - // break; - // default: - // break; - //} -//} - void IDEWindow :: onTabSelChanged(HWND wnd) { for (size_t i = 0; i < _childCounter; i++) { @@ -996,40 +967,6 @@ void IDEWindow :: onRClick(NMHDR* hdr) } } -void IDEWindow :: onSelection(SelectionNMHDR* rec) -{ - switch (rec->code) { - case NOTIFY_PROJECTVIEW_SEL: - onProjectViewSel(rec->param); - break; - case NOTIFY_TEXTFRAME_SEL: - onTextFrameChange(FRAME_CHANGED); - break; - case NOTIFY_SHOW_RESULT: - openResultTab((int)rec->param); - break; - case NOTIFY_ERROR_SEL: - onErrorHighlight((int)rec->param); - break; - case NOTIFY_REFRESH: - onChildRefresh((int)rec->param); - break; - default: - break; - } -} - -void IDEWindow :: onTreeItem(TreeItemNMHDR* rec) -{ - switch (rec->code) { - case NOTIFY_DEBUG_CONTEXT_EXPANDED: - onDebugWatchBrowse(rec->item, rec->param); - break; - default: - break; - } -} - void IDEWindow :: onContextMenu(ContextMenuNMHDR* rec) { Point p(rec->x, rec->y); @@ -1043,59 +980,212 @@ void IDEWindow :: onContextMenu(ContextMenuNMHDR* rec) menu->show(_handle, p); } -void IDEWindow :: onDebugResult(int code) +void IDEWindow :: onChildRefresh(int controlId) +{ + _children[controlId]->refresh(); +} + +void IDEWindow :: onStatusBarChange() { - switch (code) { - case DEBUGGER_STOPPED: - { - _controller->onDebuggerStop(_model); + _children[_model->ideScheme.statusBar]->refresh(); +} - MenuBase* menu = dynamic_cast(_children[_model->ideScheme.menu]); - menu->enableMenuItemById(IDM_DEBUG_STOP, true); - break; +void IDEWindow :: onIDEStatusChange(ModelNMHDR* rec) +{ + if (test(rec->status, STATUS_DOC_READY)) { + _model->status = IDEStatus::Ready; + + onStatusBarChange(); + } + else if (test(rec->status, STATUS_DEBUGGER_STOPPED)) { + _model->status = IDEStatus::Stopped; + + onStatusBarChange(); + updateCompileMenu(false, true, true); + } + else if (test(rec->status, STATUS_DEBUGGER_RUNNING)) { + _model->status = IDEStatus::Running; + + onStatusBarChange(); + updateCompileMenu(false, false, true); + } + else if (test(rec->status, STATUS_DEBUGGER_FINISHED)) { + _model->status = IDEStatus::Stopped; + + onStatusBarChange(); + updateCompileMenu(true, true, false); + + onDebugEnd(); + } + else if (test(rec->status, STATUS_STATUS_CHANGED)) { + onStatusBarChange(); + } + + if (test(rec->status, STATUS_PROJECT_CHANGED)) { + onProjectChange(_model->projectModel.empty); + } + else if (test(rec->status, STATUS_PROJECT_REFRESH)) { + onProjectRefresh(_model->projectModel.empty); + } + + if (test(rec->status, STATUS_FRAME_VISIBILITY_CHANGED)) { + if (_model->sourceViewModel.isAssigned()) { + _children[_model->ideScheme.textFrameId]->show(); + _children[_model->ideScheme.textFrameId]->setFocus(); } - default: - break; + else _children[_model->ideScheme.textFrameId]->hide(); + } + + if (test(rec->status, STATUS_COMPILING)) { + onComilationStart(); + } + + if (test(rec->status, STATUS_LAYOUT_CHANGED)) { + onLayoutChange(); + } + + if (test(rec->status, STATUS_WITHERRORS)) { + openResultTab(_model->ideScheme.errorListControl); + } + + if (test(rec->status, STATUS_DEBUGGER_NOSOURCE)) { + onDebuggerSourceNotFound(); + } + else if (test(rec->status, STATUS_DEBUGGER_STEP)) { + onDebugWatch(); + onDebugStep(); + } + + if (test(rec->status, STATUS_FRAME_ACTIVATE)) { + onActivate(); } } -void IDEWindow :: onComplition(CompletionNMHDR* rec) +void IDEWindow :: onTextModelChange(TextViewModelNMHDR* rec) { - switch (rec->code) { - case NOTIFY_COMPILATION_RESULT: - onCompilationEnd(rec->param); - break; - case NOTIFY_DEBUGGER_RESULT: - onDebugResult(rec->param); - break; - default: - break; + onDocumentUpdate(rec->docStatus); + onIDEStatusChange(rec); +} + +void IDEWindow :: onTextFrameSel(SelectionNMHDR* rec) +{ + _controller->onDocSelection(_model, rec->index); +} + +void IDEWindow :: onProjectViewSel(ParamSelectionNMHDR* rec) +{ + _controller->doOpenProjectSourceByIndex(_model, (int)rec->param); + + _children[_model->ideScheme.textFrameId]->setFocus(); +} + +void IDEWindow :: onLayoutChange() +{ + bool empty = _model->sourceViewModel.getDocumentCount() == 0; + + MenuBase* menu = dynamic_cast(_children[_model->ideScheme.menu]); + menu->checkMenuItemById(IDM_VIEW_OUTPUT, _children[_model->ideScheme.compilerOutputControl]->visible()); + menu->checkMenuItemById(IDM_VIEW_PROJECTVIEW, _children[_model->ideScheme.projectView]->visible()); + menu->checkMenuItemById(IDM_VIEW_MESSAGES, _children[_model->ideScheme.errorListControl]->visible()); + menu->checkMenuItemById(IDM_VIEW_WATCH, _children[_model->ideScheme.debugWatch]->visible()); + menu->checkMenuItemById(IDM_VIEW_VMCONSOLE, _children[_model->ideScheme.vmConsoleControl]->visible()); + + enableMenuItemById(IDM_FILE_SAVE, !empty, true); + enableMenuItemById(IDM_FILE_SAVEALL, !empty, true); + enableMenuItemById(IDM_FILE_SAVEAS, !empty, false); + enableMenuItemById(IDM_FILE_CLOSE, !empty, true); + enableMenuItemById(IDM_FILE_CLOSEALL, !empty, false); + + if (empty) { + enableMenuItemById(IDM_EDIT_UNDO, false, true); + enableMenuItemById(IDM_EDIT_REDO, false, true); + + enableMenuItemById(IDM_EDIT_CUT, false, true); + enableMenuItemById(IDM_EDIT_COPY, false, true); + enableMenuItemById(IDM_EDIT_PASTE, false, true); + + enableMenuItemById(IDM_PROJECT_INCLUDE, false, false); } + else { + enableMenuItemById(IDM_EDIT_PASTE, true, true); + + enableMenuItemById(IDM_PROJECT_INCLUDE, true, false); + } + + enableMenuItemById(IDM_EDIT_DELETE, !empty, false); + enableMenuItemById(IDM_EDIT_COMMENT, !empty, false); + enableMenuItemById(IDM_EDIT_UNCOMMENT, !empty, false); + + enableMenuItemById(IDM_EDIT_DUPLICATE, !empty, false); + enableMenuItemById(IDM_EDIT_SELECTALL, !empty, false); + enableMenuItemById(IDM_EDIT_ERASELINE, !empty, false); + enableMenuItemById(IDM_EDIT_INDENT, !empty, false); + enableMenuItemById(IDM_EDIT_OUTDENT, !empty, false); + enableMenuItemById(IDM_EDIT_TRIM, !empty, false); + enableMenuItemById(IDM_EDIT_UPPERCASE, !empty, false); + enableMenuItemById(IDM_EDIT_LOWERCASE, !empty, false); + + enableMenuItemById(IDM_SEARCH_FIND, !empty, false); + enableMenuItemById(IDM_SEARCH_FINDNEXT, !empty, false); + enableMenuItemById(IDM_SEARCH_REPLACE, !empty, false); + enableMenuItemById(IDM_SEARCH_GOTOLINE, !empty, false); + + enableMenuItemById(IDM_WINDOW_WINDOWS, !empty, false); + enableMenuItemById(IDM_WINDOW_NEXT, !empty, false); + enableMenuItemById(IDM_WINDOW_PREVIOUS, !empty, false); + + enableMenuItemById(IDM_DEBUG_CLEARBREAKPOINT, !empty, false); + enableMenuItemById(IDM_DEBUG_BREAKPOINT, !empty, false); + + onResize(); + + if (!empty) + _children[_model->ideScheme.textFrameId]->refresh(); } -void IDEWindow :: onChildRefresh(int controlId) +void IDEWindow :: onStartup(ModelNMHDR* rec) { - _children[controlId]->refresh(); + _controller->init(_model, rec->status); + + _recentFileList.assignList(&_model->projectModel.lastOpenFiles); + _recentProjectList.assignList(&_model->projectModel.lastOpenProjects); + + onIDEStatusChange(rec); } void IDEWindow :: onNotify(NMHDR* hdr) { switch (hdr->code) { - case STATUS_NOTIFICATION: - onStatusChange((StatusNMHDR*)hdr); + case EVENT_TEXTVIEW_MODEL_CHANGED: + onTextModelChange((TextViewModelNMHDR*)hdr); + break; + case EVENT_TEXTFRAME_SELECTION_CHANGED: + onTextFrameSel((SelectionNMHDR*)hdr); + break; + case EVENT_PROJECTVIEW_SELECTION_CHANGED: + onProjectViewSel((ParamSelectionNMHDR*)hdr); break; - case STATUS_SELECTION: - onSelection((SelectionNMHDR*)hdr); + case EVENT_COMPILATION_END: + onCompilationEnd(((SelectionNMHDR*)hdr)->index); break; - case STATUS_TREEITEM: - onTreeItem((TreeItemNMHDR*)hdr); + case EVENT_ERRORLIST_SELECTION: + onErrorHighlight(((SelectionNMHDR*)hdr)->index); break; - case STATUS_COMPLETION: - onComplition((CompletionNMHDR*)hdr); + case EVENT_STARTUP: + onStartup((ModelNMHDR*)hdr); break; - case CONTEXT_MENU_ON: + case EVENT_LAYOUT: + onLayoutChange(); + break; + case EVENT_TEXT_CONTEXTMENU: onContextMenu((ContextMenuNMHDR*)hdr); break; + case EVENT_BROWSE_CONTEXT: + onDebugWatchBrowse((BrowseNMHDR*)hdr); + break; + case EVENT_TEXT_MARGINLICK: + _controller->toggleBreakpoint(_model, -1); + break; case TCN_SELCHANGE: onTabSelChanged(hdr->hwndFrom); break; @@ -1129,34 +1219,11 @@ void IDEWindow :: onDebuggerStart() contextBrowser->clearRootNode(); } -void IDEWindow :: onDebuggerHook() -{ - _controller->onDebuggerHook(_model); -} - -void IDEWindow :: onDebuggerUpdate(StatusNMHDR* rec) +void IDEWindow :: onDebuggerSourceNotFound() { MenuBase* menu = dynamic_cast(_children[_model->ideScheme.menu]); - menu->enableMenuItemById(IDM_DEBUG_STOP, true); - if (test(rec->status, DEBUGWATCH_CHANGED)) { - onDebugWatch(); - } - if (test(rec->status, FRAME_CHANGED)) { - onTextFrameChange(rec->status); - } -} - -void IDEWindow :: onDebuggerSourceNotFound(StatusNMHDR* rec) -{ - MenuBase* menu = dynamic_cast(_children[_model->ideScheme.menu]); - menu->enableMenuItemById(IDM_DEBUG_STOP, true); - - if (test(rec->status, FRAME_CHANGED)) { - onTextFrameChange(rec->status); - } - _controller->onDebuggerNoSource(messageDialog, _model); } @@ -1192,7 +1259,7 @@ void IDEWindow :: onDocumentUpdate(DocumentChangeStatus& changeStatus) if (changeStatus.selelectionChanged) { MenuBase* menu = dynamic_cast(_children[_model->ideScheme.menu]); - bool isSelected = docInfo->hasSelection(); + bool isSelected = docInfo ? docInfo->hasSelection() : false; menu->enableMenuItemById(IDM_EDIT_COPY, isSelected); menu->enableMenuItemById(IDM_EDIT_CUT, isSelected); @@ -1203,12 +1270,14 @@ void IDEWindow :: onDocumentUpdate(DocumentChangeStatus& changeStatus) if (changeStatus.textChanged) { MenuBase* menu = dynamic_cast(_children[_model->ideScheme.menu]); - menu->enableMenuItemById(IDM_EDIT_UNDO, docInfo->canUndo()); - menu->enableMenuItemById(IDM_EDIT_REDO, docInfo->canRedo()); + menu->enableMenuItemById(IDM_EDIT_UNDO, docInfo ? docInfo->canUndo() : false); + menu->enableMenuItemById(IDM_EDIT_REDO, docInfo ? docInfo->canRedo() : false); } - if (changeStatus.textChanged || changeStatus.caretChanged) { - _controller->onStatusChange(_model, IDEStatus::Ready); + if (docInfo) { + for (auto it = _docViewListener.start(); !it.eof(); ++it) { + (*it)->onDocumentUpdate(changeStatus); + } } } @@ -1292,6 +1361,9 @@ void IDEWindow :: populate(size_t counter, GUIControlBase** children) _windowList.assign(menu); _recentFileList.assign(menu); _recentProjectList.assign(menu); + + _docViewListener.add(dynamic_cast(_children[_model->ideScheme.textControlId])); + _docViewListener.add(dynamic_cast(_children[_model->ideScheme.statusBar])); } void IDEWindow :: onColorSchemeChange() diff --git a/elenasrc3/ide/windows/winide.h b/elenasrc3/ide/windows/winide.h index 1d32484fcf..a93dc5b9d3 100644 --- a/elenasrc3/ide/windows/winide.h +++ b/elenasrc3/ide/windows/winide.h @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------- // E L E N A P r o j e c t: ELENA IDE // WinAPI IDE Window Header File -// (C)2021-2023, by Aleksey Rakov +// (C)2021-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #ifndef WINIDE_H @@ -15,6 +15,42 @@ namespace elena_lang { + // --- ContextMenuNMHDR --- + struct ContextMenuNMHDR + { + NMHDR nmhrd; + int x, y; + bool hasSelection; + }; + + // --- Notifications --- + struct ModelNMHDR + { + NMHDR nmhrd; + int status; + }; + + struct TextViewModelNMHDR : public ModelNMHDR + { + DocumentChangeStatus docStatus; + }; + + struct SelectionNMHDR : public ModelNMHDR + { + int index; + }; + + struct BrowseNMHDR : public ModelNMHDR + { + size_t item; + size_t param; + }; + + struct ParamSelectionNMHDR : public ModelNMHDR + { + size_t param; + }; + // --- Clipboard --- class Clipboard : public ClipboardBase { @@ -39,8 +75,39 @@ namespace elena_lang Clipboard(ControlBase* owner); }; + // --- IDENotificationFormatter --- + class IDENotificationFormatter : public EventFormatterBase + { + IDENotificationFormatter() = default; + + void sendTextViewModelEvent(TextViewModelEvent* event, WindowApp* app); + void sendTextFrameSelectionEvent(SelectionEvent* event, WindowApp* app); + void sendCompilationEndEvent(SelectionEvent* event, WindowApp* app); + void sendErrorListSelEvent(SelectionEvent* event, WindowApp* app); + void sendProjectViewSelectionEvent(ParamSelectionEvent* event, WindowApp* app); + void sendLayoutEvent(LayoutEvent* event, WindowApp* app); + void sendStartUpEvent(StartUpEvent* event, WindowApp* app); + void sendTextContextMenuEvent(ContextMenuEvent* event, WindowApp* app); + void sendBrowseContextMenuEvent(BrowseEvent* event, WindowApp* app); + void sendSimpleEvent(SimpleEvent* event, WindowApp* app); + + public: + static IDENotificationFormatter& getInstance() + { + static IDENotificationFormatter instance; // Guaranteed to be destroyed. + // Instantiated on first use. + return instance; + + } + + IDENotificationFormatter(IDENotificationFormatter const&) = delete; + void operator=(IDENotificationFormatter const&) = delete; + + void sendMessage(EventBase* event, WindowApp* app) override; + }; + // --- IDEWindow --- - class IDEWindow : public SDIWindow, DocumentNotifier + class IDEWindow : public SDIWindow { FileDialog fileDialog; FileDialog projectDialog; @@ -65,21 +132,25 @@ namespace elena_lang RecentList _recentFileList; RecentList _recentProjectList; + DocumentNotifiers _docViewListener; + void enableMenuItemById(int id, bool doEnable, bool toolBarItemAvailable); - void onStatusChange(StatusNMHDR* rec); - void onSelection(SelectionNMHDR* rec); - void onTreeItem(TreeItemNMHDR* rec); - void onComplition(CompletionNMHDR* rec); - void onContextMenu(ContextMenuNMHDR* rec); - //void onModelChange(ExtNMHDR* hdr); - //void onNotifyMessage(ExtNMHDR* hdr); + void onTextModelChange(TextViewModelNMHDR* rec); + void onTextFrameSel(SelectionNMHDR* rec); + void onProjectViewSel(ParamSelectionNMHDR* rec); + void onIDEStatusChange(ModelNMHDR* rec); + void onStartup(ModelNMHDR* rec); + void onLayoutChange(); + void onDebugStep(); void onDebugWatch(); + void onDebugEnd(); void onDoubleClick(NMHDR* hdr); void onRClick(NMHDR* hdr); void onDebugWatchRClick(size_t index); + void onContextMenu(ContextMenuNMHDR* rec); void onTabSelChanged(HWND wnd); void onTreeSelChanged(HWND wnd); @@ -91,10 +162,6 @@ namespace elena_lang void onToolTip(NMTTDISPINFO* toolTip); void onTabTip(NMTTDISPINFO* toolTip); - void onLayoutChange(NotificationStatus status); - void onIDEChange(NotificationStatus status); - void onTextFrameChange(NotificationStatus status); - bool onCommand(int command) override; void onNotify(NMHDR* hdr) override; void onActivate() override; @@ -103,14 +170,18 @@ namespace elena_lang void onComilationStart(); void onCompilationEnd(int exitCode); void onErrorHighlight(int index); - void onDebugResult(int code); - void onDebugWatchBrowse(size_t item, size_t param); + void onDebugWatchBrowse(BrowseNMHDR* rec); + + void updateCompileMenu(bool compileEnable, bool debugEnable, bool stopEnable); void onProjectChange(bool empty); + void onProjectRefresh(bool empty); void onProjectViewSel(int index); void onColorSchemeChange(); + void onStatusBarChange(); + bool toggleTabBarWindow(int child_id); void toggleWindow(int child_id); @@ -159,10 +230,8 @@ namespace elena_lang void refreshDebugNode(); void onDebuggerStart(); - void onDebuggerHook(); - void onDebuggerUpdate(StatusNMHDR* rec); - void onDebuggerSourceNotFound(StatusNMHDR* rec); - void onDocumentUpdate(DocumentChangeStatus& changeStatus) override; + void onDebuggerSourceNotFound(); + void onDocumentUpdate(DocumentChangeStatus& changeStatus); public: void populate(size_t counter, GUIControlBase** children) override; diff --git a/elenasrc3/ide/windows/winidestatusbar.cpp b/elenasrc3/ide/windows/winidestatusbar.cpp index 9b1a73229f..c3fbe03814 100644 --- a/elenasrc3/ide/windows/winidestatusbar.cpp +++ b/elenasrc3/ide/windows/winidestatusbar.cpp @@ -18,8 +18,6 @@ int StatusBarWidths[5] = { 200, 120, 80, 60, 80 }; IDEStatusBar :: IDEStatusBar(IDEModel* model) : StatusBar(5, StatusBarWidths), _model(model) { - _model->sourceViewModel.attachDocListener(this); - setIDEStatus(IDEStatus::Empty); //_pendingIDESettings = true; @@ -39,6 +37,15 @@ void IDEStatusBar :: onDocumentUpdate(DocumentChangeStatus& changeStatus) setText(1, line.str()); } + if (changeStatus.readOnlyChanged) { + auto docView = _model->viewModel()->DocView(); + + String line; + line.copy(docView->isReadOnly() ? _T("Read-only") : _T("")); + + setText(2, line.str()); + } + } void IDEStatusBar :: setRectangle(Rectangle rec) @@ -66,9 +73,6 @@ void IDEStatusBar :: setIDEStatus(IDEStatus status) case IDEStatus::Compiling: setText(0, _T(" Compiling...")); break; - case IDEStatus::Busy: - setText(0, _T(" Busy")); - break; case IDEStatus::AutoRecompiling: setText(0, _T(" Recompiling...")); break; @@ -84,6 +88,12 @@ void IDEStatusBar :: setIDEStatus(IDEStatus status) case IDEStatus::Broken: setText(0, _T(" The process was broken")); break; + case IDEStatus::Running: + setText(0, _T(" Running...")); + break; + case IDEStatus::Stopped: + setText(0, _T(" Stopped")); + break; default: break; } diff --git a/elenasrc3/ide/windows/winidestatusbar.h b/elenasrc3/ide/windows/winidestatusbar.h index 40c9f50aee..0fcdd1a407 100644 --- a/elenasrc3/ide/windows/winidestatusbar.h +++ b/elenasrc3/ide/windows/winidestatusbar.h @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------- // E L E N A P r o j e c t: ELENA IDE // WinAPI IDE Status Bar Header File -// (C)2021-2022, by Aleksey Rakov +// (C)2021-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #ifndef WINIDESTATUSBAR_H @@ -14,7 +14,7 @@ namespace elena_lang { // --- IDEStatusBar --- - class IDEStatusBar : public StatusBar, DocumentNotifier + class IDEStatusBar : public StatusBar, public DocumentNotifier { IDEModel* _model; IDEStatus _status; diff --git a/elenasrc3/ide/windows/winmessagelog.cpp b/elenasrc3/ide/windows/winmessagelog.cpp index dcaa6c78ef..54f0bb54f6 100644 --- a/elenasrc3/ide/windows/winmessagelog.cpp +++ b/elenasrc3/ide/windows/winmessagelog.cpp @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------- // E L E N A P r o j e c t: ELENA IDE // WinAPI IDE Message Log Implementation File -// (C)2022-2023, by Aleksey Rakov +// (C)2022-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #include @@ -12,11 +12,11 @@ using namespace elena_lang; // --- MessageLog --- -MessageLog :: MessageLog(NotifierBase* notifier, int highlightCode) +MessageLog :: MessageLog(NotifierBase* notifier, SelectionEventInvoker invoker) : ListView(50, 50), _list({}), _paths(nullptr) { _notifier = notifier; - _highlightCode = highlightCode; + _invoker = invoker; } HWND MessageLog :: createControl(HINSTANCE instance, ControlBase* owner) @@ -62,5 +62,5 @@ void MessageLog :: clearMessages() void MessageLog :: onItemDblClick(int index) { if (index >= 0) - _notifier->notifySelection(_highlightCode, index); + _invoker(_notifier, index); } diff --git a/elenasrc3/ide/windows/winmessagelog.h b/elenasrc3/ide/windows/winmessagelog.h index 06d7b114f0..21f6cc10c9 100644 --- a/elenasrc3/ide/windows/winmessagelog.h +++ b/elenasrc3/ide/windows/winmessagelog.h @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------- // E L E N A P r o j e c t: ELENA IDE // WinAPI IDE Message Log Header File -// (C)2022, by Aleksey Rakov +// (C)2022-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #ifndef WINMESSAGELOG_H @@ -15,13 +15,17 @@ namespace elena_lang // --- MessageLog --- class MessageLog : public ListView, public ErrorLogBase { + public: + typedef void(*SelectionEventInvoker)(NotifierBase*, int); + + private: typedef Map MessageList; typedef List Paths; - MessageList _list; - Paths _paths; - NotifierBase* _notifier; - int _highlightCode; + MessageList _list; + Paths _paths; + NotifierBase* _notifier; + SelectionEventInvoker _invoker; public: HWND createControl(HINSTANCE instance, ControlBase* owner) override; @@ -34,7 +38,7 @@ namespace elena_lang void onItemDblClick(int index) override; - MessageLog(NotifierBase* notifier, int highlightCode); + MessageLog(NotifierBase* notifier, SelectionEventInvoker invoker); }; } diff --git a/elenasrc3/ide/windows/winoutput.cpp b/elenasrc3/ide/windows/winoutput.cpp index 45d41517bb..bc7610354f 100644 --- a/elenasrc3/ide/windows/winoutput.cpp +++ b/elenasrc3/ide/windows/winoutput.cpp @@ -120,17 +120,17 @@ wchar_t* ProcessOutput :: getValue() // --- CompilerOutput --- -CompilerOutput :: CompilerOutput(NotifierBase* notifier, int notificationId) +CompilerOutput :: CompilerOutput(NotifierBase* notifier, EventInvoker invoker) : ProcessOutput(nullptr, true), _notifier(notifier), - _notificationId(notificationId) + _eventInvoker(invoker) { } void CompilerOutput :: afterExecution(int exitCode) { - _notifier->notifyCompletion(_notificationId, exitCode); + _eventInvoker(_notifier, exitCode); } // --- VMConsoleInteractive --- diff --git a/elenasrc3/ide/windows/winoutput.h b/elenasrc3/ide/windows/winoutput.h index 115e16fd12..35b5a1cb03 100644 --- a/elenasrc3/ide/windows/winoutput.h +++ b/elenasrc3/ide/windows/winoutput.h @@ -42,13 +42,17 @@ namespace elena_lang // --- CompilerOutput --- class CompilerOutput : public ProcessOutput { + public: + typedef void(*EventInvoker)(NotifierBase*, int); + + private: NotifierBase* _notifier; - int _notificationId; + EventInvoker _eventInvoker; void afterExecution(int exitCode) override; public: - CompilerOutput(NotifierBase* notifier, int notificationId); + CompilerOutput(NotifierBase* notifier, EventInvoker invoker); }; // --- VMConsoleInteractive --- diff --git a/elenasrc3/tools/asmc/asmc.cpp b/elenasrc3/tools/asmc/asmc.cpp index a39554640e..868effd1a9 100644 --- a/elenasrc3/tools/asmc/asmc.cpp +++ b/elenasrc3/tools/asmc/asmc.cpp @@ -3,7 +3,7 @@ // // Asm2BinX main file // -// (C)2021-2023, by Aleksey Rakov +// (C)2021-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #include @@ -91,7 +91,7 @@ template void compileAssembly(path_t source, path_t target) } } -void compileByteCode(path_t source, path_t target, bool mode64, int rawDataAlignment) +void compileByteCode(path_t source, path_t target, bool mode64, int rawDataAlignment, bool supportStdMode) { FileNameString sourceName(source, true); NamespaceString name; @@ -106,7 +106,7 @@ void compileByteCode(path_t source, path_t target, bool mode64, int rawDataAlign throw ExceptionBase(); } - ByteCodeAssembler assembler(4, &reader, &targetModule, mode64, rawDataAlignment); + ByteCodeAssembler assembler(4, &reader, &targetModule, mode64, rawDataAlignment, supportStdMode); assembler.compile(); @@ -128,6 +128,7 @@ int main(int argc, char* argv[]) PathString source; PathString target; CompileMode mode = CompileMode::x86; + bool supportStdMode = false; for (int i = 1; i < argc; i++) { if (argv[i][0] == '-') { ustr_t arg(argv[i] + 1); @@ -148,6 +149,9 @@ int main(int argc, char* argv[]) } else if (arg.compare(BC_32_MODE)) { mode = CompileMode::bc32; +#ifdef WIN32 + supportStdMode = true; +#endif } else if (arg.compare(BC_64_MODE)) { mode = CompileMode::bc64; @@ -226,7 +230,7 @@ int main(int argc, char* argv[]) target.changeExtension("nl"); - compileByteCode(*source, *target, false, 4); + compileByteCode(*source, *target, false, 4, supportStdMode); break; } @@ -236,7 +240,7 @@ int main(int argc, char* argv[]) target.changeExtension("nl"); - compileByteCode(*source, *target, true, 16); + compileByteCode(*source, *target, true, 16, supportStdMode); break; } diff --git a/elenasrc3/tools/asmc/asmconst.h b/elenasrc3/tools/asmc/asmconst.h index e2b251099d..d73ae1acb6 100644 --- a/elenasrc3/tools/asmc/asmconst.h +++ b/elenasrc3/tools/asmc/asmconst.h @@ -3,7 +3,7 @@ // // This file contains the assembly compiler common constants // -// (C)2021-2023, by Aleksey Rakov +// (C)2021-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #ifndef CLICONST @@ -12,7 +12,7 @@ namespace elena_lang { - #define ASM_REVISION_NUMBER 0x00C9 + #define ASM_REVISION_NUMBER 0x00CB constexpr auto N_ARGUMENT1 = "__n_1"; constexpr auto N_ARGUMENT2 = "__n_2"; @@ -54,7 +54,7 @@ namespace elena_lang constexpr auto RDATA64_ARGUMENT1 = "rdata64"; constexpr auto QWORD_ARGUMENT2 = "__arg64_2"; - constexpr auto ASM_GREETING = "ELENA Assembler Compiler %d.%d.%d (C)2011-2022 by Alexei Rakov\n"; + constexpr auto ASM_GREETING = "ELENA Assembler Compiler %d.%d.%d (C)2011-2024 by Alexei Rakov\n"; constexpr auto ASM_HELP = "asmc-cli [-amd64 | -x86] \n"; constexpr auto ASM_COMPILE_X86 = "X86 Assembler : compiling %s\n"; diff --git a/elenasrc3/tools/asmc/bcassembler.cpp b/elenasrc3/tools/asmc/bcassembler.cpp index 859feede20..c94433aafb 100644 --- a/elenasrc3/tools/asmc/bcassembler.cpp +++ b/elenasrc3/tools/asmc/bcassembler.cpp @@ -3,7 +3,7 @@ // // This file contains the implementation of ELENA Byte-code assembler // classes. -// (C)2021-2023, by Aleksey Rakov +// (C)2021-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #include "bcassembler.h" @@ -68,11 +68,12 @@ void ByteCodeAssembler::ByteCodeLabelHelper :: checkAllUsedLabels(ustr_t errorMe // --- ByteCodeAssembler --- ByteCodeAssembler :: ByteCodeAssembler(int tabSize, UStrReader* reader, Module* module, - bool mode64, int rawDataAlignment) + bool mode64, int rawDataAlignment, bool supportStd) : _reader(tabSize, reader) { _module = module; _mode64 = mode64; + _supportStd = supportStd; _rawDataAlignment = rawDataAlignment; } @@ -790,7 +791,7 @@ bool ByteCodeAssembler :: compileOpenOp(ScriptToken& tokenInfo, MemoryWriter& wr } bool ByteCodeAssembler :: compileCallExt(ScriptToken& tokenInfo, MemoryWriter& writer, - ByteCommand& command, ReferenceMap& parameters, ReferenceMap& locals, ReferenceMap& dataLocals, ReferenceMap& constants) + ByteCommand& command, ReferenceMap& parameters, ReferenceMap& locals, ReferenceMap& dataLocals, ReferenceMap& constants, bool stdCall) { IdentifierString functionName; if (tokenInfo.compare(":")) { @@ -848,7 +849,7 @@ bool ByteCodeAssembler :: compileCallExt(ScriptToken& tokenInfo, MemoryWriter& w ByteCodeUtil::write(writer, command); - if (stackSize > 0) + if (stackSize > 0 && !stdCall) ByteCodeUtil::write(writer, ByteCode::FreeI, stackSize); } else if (tokenInfo.compare(",")) { @@ -968,6 +969,15 @@ bool ByteCodeAssembler :: compileByteCode(ScriptToken& tokenInfo, MemoryWriter& read(tokenInfo); + bool stdCall = false; + if (tokenInfo.compare("stdcall")) { + // NOTE : stdcall is applied only for x86 mode + if (_supportStd) + stdCall = true; + + read(tokenInfo); + } + command.append(' '); command.append(*tokenInfo.token); @@ -988,7 +998,7 @@ bool ByteCodeAssembler :: compileByteCode(ScriptToken& tokenInfo, MemoryWriter& if (!ByteCodeUtil::isSingleOp(opCommand.code)) { switch (opCommand.code) { case ByteCode::CallExtR: - return compileCallExt(tokenInfo, writer, opCommand, parameters, locals, dataLocals, constants); + return compileCallExt(tokenInfo, writer, opCommand, parameters, locals, dataLocals, constants, stdCall); case ByteCode::XOpenIN: case ByteCode::OpenIN: case ByteCode::ExtOpenIN: diff --git a/elenasrc3/tools/asmc/bcassembler.h b/elenasrc3/tools/asmc/bcassembler.h index 4de25f23ac..c2e5f37cad 100644 --- a/elenasrc3/tools/asmc/bcassembler.h +++ b/elenasrc3/tools/asmc/bcassembler.h @@ -3,7 +3,7 @@ // // This header contains Byte-code Assembler declarations // -// (C)2021-2023, by Aleksey Rakov +// (C)2021-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #ifndef BCASSEMBLER_H @@ -121,6 +121,7 @@ namespace elena_lang ScriptReader _reader; Module* _module; bool _mode64; + bool _supportStd; int _rawDataAlignment; void read(ScriptToken& tokenInfo); @@ -184,7 +185,7 @@ namespace elena_lang ReferenceMap& locals, ReferenceMap& dataLocals, ReferenceMap& constants, int& dataSize); bool compileCallExt(ScriptToken& tokenInfo, MemoryWriter& writer, ByteCommand& command, - ReferenceMap& parameters, ReferenceMap& locals, ReferenceMap& dataLocals, ReferenceMap& constants); + ReferenceMap& parameters, ReferenceMap& locals, ReferenceMap& dataLocals, ReferenceMap& constants, bool stdCall); bool compileXDispatchMR(ScriptToken& tokenInfo, MemoryWriter& writer, ByteCommand& command, ReferenceMap& constants); @@ -202,7 +203,7 @@ namespace elena_lang void compile(); ByteCodeAssembler(int tabSize, UStrReader* reader, Module* module, - bool mode64, int rawDataAlignment); + bool mode64, int rawDataAlignment, bool supportStd); }; } diff --git a/elenasrc3/tools/asmc/x86assembler.cpp b/elenasrc3/tools/asmc/x86assembler.cpp index 11b87b20f2..c307be107c 100644 --- a/elenasrc3/tools/asmc/x86assembler.cpp +++ b/elenasrc3/tools/asmc/x86assembler.cpp @@ -3,7 +3,7 @@ // // This file contains the implementation of ELENA Intel X86 Assembler // classes. -// (C)2021-2022, by Aleksey Rakov +// (C)2021-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #include "elena.h" @@ -1374,10 +1374,24 @@ void X86Assembler :: compileDQField(ScriptToken& tokenInfo, MemoryWriter& writer bool X86Assembler :: compileAdc(X86Operand source, X86Operand target, MemoryWriter& writer) { - if (source.isR32_M32() && target.isR32()) { + if (source.type == X86OperandType::EAX && target.type == X86OperandType::DD) { + writer.writeByte(0x15); + X86Helper::writeImm(writer, target); + } + else if (source.isR32_M32() && target.isR32()) { writer.writeByte(0x11); X86Helper::writeModRM(writer, target, source); } + else if (source.isR32_M32() && target.type == X86OperandType::DB) { + writer.writeByte(0x83); + X86Helper::writeModRM(writer, X86Operand(X86OperandType::R32 + 2), source); + X86Helper::writeImm(writer, target); + } + else if (source.isR8_M8() && target.type == X86OperandType::DB) { + writer.writeByte(0x80); + X86Helper::writeModRM(writer, X86Operand(X86OperandType::R8 + 2), source); + X86Helper::writeImm(writer, target); + } else return false; return true; diff --git a/elenasrc3/tools/elt/eltconst.h b/elenasrc3/tools/elt/eltconst.h index d0469e2fbf..04885d9ca9 100644 --- a/elenasrc3/tools/elt/eltconst.h +++ b/elenasrc3/tools/elt/eltconst.h @@ -3,7 +3,7 @@ // // This file contains the elt common interfaces & types // -// (C)2021-2023, by Aleksey Rakov +// (C)2021-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #ifndef ELTCONST_H @@ -11,9 +11,9 @@ namespace elena_lang { - #define ELT_REVISION_NUMBER 0x0008 + #define ELT_REVISION_NUMBER 0x0009 - constexpr auto ELT_GREETING = "ELENA command line VM terminal %d.%d.%d (C)2021-23 by Aleksey Rakov\n"; + constexpr auto ELT_GREETING = "ELENA command line VM terminal %d.%d.%d (C)2021-24 by Aleksey Rakov\n"; constexpr auto COMMAMD_TEMPLATE = "command60.es"; constexpr auto ELT_CONFIG = "~\\elt60.es"; diff --git a/elenasrc3/tools/elt/windows/elt.cpp b/elenasrc3/tools/elt/windows/elt.cpp index 0e284cbfc5..0e49ba9e78 100644 --- a/elenasrc3/tools/elt/windows/elt.cpp +++ b/elenasrc3/tools/elt/windows/elt.cpp @@ -3,7 +3,7 @@ // // This is a main file containing VM terminal // -// (C)2021-2023, by Aleksey Rakov +// (C)2021-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #include "elena.h" @@ -11,8 +11,20 @@ #include "vmsession.h" #include "windows/presenter.h" +#include + using namespace elena_lang; +void getAppPath(PathString& appPath) +{ + wchar_t path[MAX_PATH + 1]; + + ::GetModuleFileName(NULL, path, MAX_PATH); + + appPath.copySubPath(path, true); + appPath.lower(); +} + class ELTPresenter : public WinConsolePresenter { public: @@ -30,7 +42,9 @@ int main() ELTPresenter presenter; VMSession session(&presenter); - PathString commandPath(COMMAMD_TEMPLATE); + PathString commandPath; + getAppPath(commandPath); + commandPath.combine(COMMAMD_TEMPLATE); session.loadTemplate(*commandPath); session.loadScript(ELT_CONFIG); diff --git a/elenasrc3/tools/og/ogconst.h b/elenasrc3/tools/og/ogconst.h index 5b1d2a4ef5..9627bc23e7 100644 --- a/elenasrc3/tools/og/ogconst.h +++ b/elenasrc3/tools/og/ogconst.h @@ -3,7 +3,7 @@ // // This file contains the compiler common interfaces & types // -// (C)2021-2023, by Aleksey Rakov +// (C)2021-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #ifndef CLICONST @@ -11,9 +11,9 @@ namespace elena_lang { - #define SG_REVISION_NUMBER 0x0010 + #define SG_REVISION_NUMBER 0x0011 - constexpr auto OG_GREETING = "ELENA command line optimization rule set generator %d.%d.%d (C)2023 by Aleksey Rakov\n"; + constexpr auto OG_GREETING = "ELENA command line optimization rule set generator %d.%d.%d (C)2023-2024 by Aleksey Rakov\n"; constexpr auto OG_HELP = "og-cli \n"; diff --git a/examples/gui/agenda/agenda.prj b/examples/gui/agenda/agenda.prj deleted file mode 100644 index 5b31b2a356..0000000000 --- a/examples/gui/agenda/agenda.prj +++ /dev/null @@ -1,16 +0,0 @@ - - - agenda.exe - - - - agenda - - -1 - - - - form.l - - - \ No newline at end of file diff --git a/examples/gui/agenda/form.l b/examples/gui/agenda/form.l deleted file mode 100644 index 791bf22564..0000000000 --- a/examples/gui/agenda/form.l +++ /dev/null @@ -1,206 +0,0 @@ -import extensions; -import forms; -import system'io; - -import system'drawing; - -// --- Main window --- - -public class MainWindow : SDIDialog -{ - // All Text Box's - Edit Name; - Edit SurName; - Edit OtName; - Edit Email; - Edit Age; - Edit PhoneNumber; - - // All Labels - Label LabelName; - Label LabelSurName; - Label LabelOtName; - Label LabelEmail; - Label LabelAge; - Label LabelPhoneNumber; - Label LabelAbout; - Label LabelDel; - - // All Buttons - Button BtmExit; - Button BtmSave; - Button BtmDelTxt; - Button BtmInfo; - - File theSavedFile; - - constructor new() - <= new() - { - // Controls - LabelName := Label.new(); - LabelSurName := Label.new(); - LabelOtName := Label.new(); - LabelEmail := Label.new(); - LabelAge := Label.new(); - LabelPhoneNumber := Label.new(); - LabelAbout := Label.new(); - LabelDel := Label.new(); - Name := Edit.new(); - SurName := Edit.new(); - OtName := Edit.new(); - Email := Edit.new(); - Age := Edit.new(); - PhoneNumber := Edit.new(); - BtmExit := Button.new(); - BtmSave := Button.new(); - BtmDelTxt := Button.new(); - BtmInfo := Button.new(); - - self - .appendControl:LabelName - .appendControl:LabelSurName - .appendControl:LabelOtName - .appendControl:LabelEmail - .appendControl:LabelAge - .appendControl:LabelPhoneNumber - .appendControl:LabelAbout - .appendControl:LabelDel - .appendControl:Name - .appendControl:SurName - .appendControl:OtName - .appendControl:Email - .appendControl:Age - .appendControl:PhoneNumber - .appendControl:BtmExit - .appendControl:BtmSave - .appendControl:BtmDelTxt - .appendControl:BtmInfo; - - // Form - self.Caption := "Writer Account"; - self.setRegion(350, 250, 500, 265); - - // ------------------------------------ Labels ------------------------------------ - // LabelName - LabelName.Caption := "Your Name:"; - LabelName.setRegion(12, 10, 109, 30); - - // LabelSurName - LabelSurName.Caption:="Your Last Name:"; - LabelSurName.setRegion(12, 40, 109, 20); - - // LabelOtName - LabelOtName.Caption:="Other Names:"; - LabelOtName.setRegion(12, 65, 109, 20); - - // LabelEmail - LabelEmail.Caption := "Email:"; - LabelEmail.setRegion(12, 90, 109, 20); - - // LabelAge - LabelAge.Caption := "Age:"; - LabelAge.setRegion(12, 115, 109, 20); - - // LabelPhoneNumber - LabelPhoneNumber.Caption := "Phone Number:"; - LabelPhoneNumber.setRegion(12, 140, 109, 20); - - // LabelAbout - LabelAbout.Caption := emptyWideString; - LabelAbout.setRegion(12, 165, 400, 35); - - // LabelDel - LabelDel.Caption := emptyWideString; - LabelDel.setRegion(300, 185, 400, 35); - - // ------------------------------------ Text Box's ------------------------------------ - // Name - Name.Value := "Your name"; - Name.setRegion(125, 10, 200, 25); - - // SurName - SurName.Value := "Your Last Name"; - SurName.setRegion(125, 35, 200, 25); - - // OtName - OtName.Value := "Other Name"; - OtName.setRegion(125, 60, 200, 25); - - // Email - Email.Value := "Email"; - Email.setRegion(125, 85, 200, 25); - - // Age - Age.Value := "Age"; - Age.setRegion(125, 110, 200, 25); - - // PhoneNumber - PhoneNumber.Value := "Phone Number"; - PhoneNumber.setRegion(125, 135, 200, 25); - - // ------------------------------------ Buttons ------------------------------------ - // BtmSave - BtmSave.Caption:="Save"; - BtmSave.setRegion(390, 10, 82, 25); - - // BtmDelTxt - BtmDelTxt.Caption:="Del TXT"; - BtmDelTxt.setRegion(390, 50, 82, 25); - BtmDelTxt.Enabled:=false; - - // BtmInfo - BtmInfo.Caption:="About"; - BtmInfo.setRegion(390, 80, 82, 25); - - // BtmExit - BtmExit.Caption:="Exit"; - BtmExit.setRegion(390, 110, 82, 25); - - // ------------------------------------ Handlers ------------------------------------ - // Save - BtmSave.onClick := (args) - { - var dialog := SaveFileDialog.new(self); - dialog.addFilter("Text Files", "*.txt"); - dialog.Caption := "Select a file"; - - if (dialog.run()) - { - theSavedFile := File.assign(dialog.Selected); - - var writer := theSavedFile.logger(); - - writer - .printLine:"//-------------------------------------------------------------------------------" - .printLine("Name: ",Name.Value," ",SurName.Value," ",OtName.Value) - .printLine("Email: ",Email.Value) - .printLine("Age: ",Age.Value) - .printLine("PhoneNumber:",PhoneNumber.Value) - .printLine:"//-------------------------------------------------------------------------------"; - - writer.close(); - - BtmDelTxt.Enabled := true - } - }; - - // Del TXT - BtmDelTxt.onClick := (args) - { - theSavedFile.delete() - }; - - // Exit - BtmExit.onClick := (args) - { - forward program.stop() - }; - - // About - BtmInfo.onClick := (args) - { - LabelAbout.Caption := "Created by Alexandre Bencz."$10"Thanks Alex Rakov, for support." - } - } -} \ No newline at end of file diff --git a/examples/gui/graphs/graphs.l b/examples/gui/graphs/graphs.l deleted file mode 100644 index b552fd0467..0000000000 --- a/examples/gui/graphs/graphs.l +++ /dev/null @@ -1,96 +0,0 @@ -import system'math; -import forms; -import system'drawing; -import extensions; - -const int ScaleX = 15; -const int ScaleY = 15; -const real starting = 0.0r; -symbol real ending = Pi_value * 6; -const real H = 0.005r; -const real A = 5.0r; -real C = 2.0r / 3.0r; - -// --- function --- - -function(t) -{ - ^ new Point( - (A * (C * t.cos() + (C*t).cos()) * ScaleX).RoundedInt, - (A * (C * t.sin() - (C*t).sin()) * ScaleY).RoundedInt) -} - -singleton Plotter -{ - drawAxis(Dimension size, Canvas canvas) - { - var zeroX := size.Width / 2; - var zeroY := size.Height / 2 - 10; - - // X axis - canvas.setCaret(0, zeroY); - canvas.lineCaretTo(size.Width, zeroY); - - canvas.writeText("X", size.Width - 20, zeroY + 2); - - // Y axis - canvas.setCaret(zeroX, 0); - canvas.lineCaretTo(zeroX, size.Height); - - canvas.writeText("Y", zeroX + 2, 2); - - for(int i := -10, i <= 10, i += 2) - { - if(i != 0) - { - canvas.writeText(i.toString(), zeroX + (i * ScaleX) - 4, zeroY + 2); - - canvas.writeText(i.toString(), zeroX + 8, zeroY - (i * ScaleY) - 2); - } - else - { - canvas.writeText("0", zeroX + 2, zeroY + 2) - } - } - } - - drawGraph(Dimension size, Canvas canvas) - { - auto t := starting; - auto t2 := ending; - var zero := new Point(size.Width / 2, size.Height / 2 - 10); - - canvas.setCaret(zero + function(t)); - while (t <= t2) - { - canvas.lineCaretTo(zero + function(t)); - - t := t + H - } - } -} - -public class MainWindow : SDIDialog -{ - Imagebox theImagebox; - - constructor new() - <= new() - { - theImagebox := Imagebox.new(); - self.appendControl:theImagebox; - - self.Caption := "Graph sample"; - self.setRegion(50, 50, 400, 420); - - theImagebox.setRegion(0, 0, 400, 420); - theImagebox.onPaint := (object sender, Canvas canvas) - { - canvas.set(WhitePen); - canvas.set(BlackBrush); - - Plotter.drawAxis(theImagebox.Dimension, canvas); - Plotter.drawGraph(theImagebox.Dimension, canvas) - } - } -} \ No newline at end of file diff --git a/examples/gui/graphs/graphs.prj b/examples/gui/graphs/graphs.prj deleted file mode 100644 index ee51cfaf33..0000000000 --- a/examples/gui/graphs/graphs.prj +++ /dev/null @@ -1,16 +0,0 @@ - - - graphs.exe - - - - graphs - - -1 - - - - graphs.l - - - \ No newline at end of file diff --git a/examples60/console/sum/intsum.prj b/examples60/console/sum/intsum.prj deleted file mode 100644 index b4cc14951d..0000000000 --- a/examples60/console/sum/intsum.prj +++ /dev/null @@ -1,25 +0,0 @@ - - - - intsum - - - - - intsum64 - - - - sum - - - - - sum.l - - - - sum'IntSamplePrompt - extensions'Integer - - \ No newline at end of file diff --git a/examples60/console/sum/realsum.prj b/examples60/console/sum/realsum.prj deleted file mode 100644 index 28a2fbc84f..0000000000 --- a/examples60/console/sum/realsum.prj +++ /dev/null @@ -1,25 +0,0 @@ - - - - realsum - - - - - realsum64 - - - - sum - - - - - sum.l - - - - sum'RealSamplePrompt - extensions'Real - - \ No newline at end of file diff --git a/examples60/console/sum/sum.prj b/examples60/console/sum/sum.prj new file mode 100644 index 0000000000..ef6c3d4a18 --- /dev/null +++ b/examples60/console/sum/sum.prj @@ -0,0 +1,47 @@ + + + + + intsum + + + + + realsum + + + + + + + intsum64 + + + + + realsum64 + + + + + sum + + + + + sum.l + + + + + sum'IntSamplePrompt + extensions'Integer + + + + + sum'RealSamplePrompt + extensions'Real + + + \ No newline at end of file diff --git a/examples60/db/sqlite/main.l b/examples60/db/sqlite/main.l new file mode 100644 index 0000000000..00b4d4b5aa --- /dev/null +++ b/examples60/db/sqlite/main.l @@ -0,0 +1,93 @@ +import system'routines; +import system'io; +import extensions; +import sqlite; + +const DBFileName = "data.db"; + +// --- dbTestOp --- + +extension dbTestOp +{ + printTable(tableName) + { + console.printLine(tableName,":"); + var table := self.executeQuery("SELECT * FROM " + tableName); + + // Header + table.fields().forEach::(fieldName) + { + console.printPaddingRight(25, fieldName) + }; + console.printLine(); + console.printPaddingRightChar(25 * table.fieldCount(), $45, "-"); + console.printLine(); + + // Rows + table.rows().forEach::(row) + { + table.fields().forEach::(fieldName) + { + console.printPaddingRight(25, row[fieldName]) + }; + console.printLine() + }; + console.printLine(); + } +} + +// --- program --- + +public program() +{ + auto dbFile := File.assign(DBFileName); + + var cnn := DBConnection.new(dbFile); + + ifnot (dbFile.Available) + { + cnn.open(); + + using (cnn) + { + console.write("Database is being created"); + + cnn.executeNonQuery("CREATE Table Movies (Name TEXT, Director TEXT, Year INTEGER)"); + console.write("."); + + cnn.executeNonQuery("INSERT INTO Movies (Name, Director, Year) VALUES ('The Dark Knight', 'Christopher Nolan', 2008)"); + cnn.executeNonQuery("INSERT INTO Movies (Name, Director, Year) VALUES ('Cloverfield', 'Matt Reeves', 2008)"); + cnn.executeNonQuery("INSERT INTO Movies (Name, Director, Year) VALUES ('Beverly Hills Chihuahua', 'Raja Gosnell', 2008)"); + console.write("."); + + cnn.executeNonQuery("CREATE TABLE [Users] " + + "([ID] INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, " + + "[client] NVARCHAR(100) NULL, " + + "[date] DATE NULL " + + ")"); + console.write("."); + + cnn.executeNonQuery("INSERT INTO Users (client, date) VALUES ('Alexandre', '2015-01-01')"); + cnn.executeNonQuery("INSERT INTO Users (client, date) VALUES ('Alex', '2015-01-01')"); + console.write("."); + + console.writeLine("Done") + } + }; + + cnn.open(); + + using (cnn) + { + console.printLine("Number of table in DB: ",cnn.numberOfTable()); + + console.writeLine("Tables:").writeLine(); + + cnn.tables().forEach::(tableName) + { + cnn.printTable(tableName) + } + }; + + console.readChar() +} \ No newline at end of file diff --git a/examples60/db/sqlite/sqlite_test.prj b/examples60/db/sqlite/sqlite_test.prj new file mode 100644 index 0000000000..cb6ab47db6 --- /dev/null +++ b/examples60/db/sqlite/sqlite_test.prj @@ -0,0 +1,15 @@ + + + bin\sqlite_test.exe + + obj + + sqlite_test + + + + + main.l + + + diff --git a/examples60/gui/agenda/form.l b/examples60/gui/agenda/form.l index 4b81e6adce..4d0ee4da55 100644 --- a/examples60/gui/agenda/form.l +++ b/examples60/gui/agenda/form.l @@ -58,24 +58,24 @@ public class MainWindow : SDIDialog BtmInfo := Button.new(); self - .appendControl:LabelName - .appendControl:LabelSurName - .appendControl:LabelOtName - .appendControl:LabelEmail - .appendControl:LabelAge - .appendControl:LabelPhoneNumber - .appendControl:LabelAbout - .appendControl:LabelDel - .appendControl:Name - .appendControl:SurName - .appendControl:OtName - .appendControl:Email - .appendControl:Age - .appendControl:PhoneNumber - .appendControl:BtmExit - .appendControl:BtmSave - .appendControl:BtmDelTxt - .appendControl:BtmInfo; + .appendControl(LabelName) + .appendControl(LabelSurName) + .appendControl(LabelOtName) + .appendControl(LabelEmail) + .appendControl(LabelAge) + .appendControl(LabelPhoneNumber) + .appendControl(LabelAbout) + .appendControl(LabelDel) + .appendControl(Name) + .appendControl(SurName) + .appendControl(OtName) + .appendControl(Email) + .appendControl(Age) + .appendControl(PhoneNumber) + .appendControl(BtmExit) + .appendControl(BtmSave) + .appendControl(BtmDelTxt) + .appendControl(BtmInfo); // Form self.Caption := "Writer Account"; @@ -161,7 +161,7 @@ public class MainWindow : SDIDialog // Save BtmSave.onClick := (args) { - var dialog := SaveFileDialog.new(self); + var dialog := OpenFileDialog.new(self); dialog.addFilter("Text Files", "*.txt"); dialog.Caption := "Select a file"; @@ -172,12 +172,12 @@ public class MainWindow : SDIDialog var writer := _savedFile.logger(); writer - .printLine:"//-------------------------------------------------------------------------------" + .printLine("//-------------------------------------------------------------------------------") .printLine("Name: ",Name.Value," ",SurName.Value," ",OtName.Value) .printLine("Email: ",Email.Value) .printLine("Age: ",Age.Value) .printLine("PhoneNumber:",PhoneNumber.Value) - .printLine:"//-------------------------------------------------------------------------------"; + .printLine("//-------------------------------------------------------------------------------"); writer.close(); diff --git a/examples60/gui/c_a_g/anot_wind.l b/examples60/gui/c_a_g/anot_wind.l index cb0c68dbe8..4ab6652fa1 100644 --- a/examples60/gui/c_a_g/anot_wind.l +++ b/examples60/gui/c_a_g/anot_wind.l @@ -1,100 +1,96 @@ // --- default namespaces --- -import forms. +import forms; +import system'io; -class InfoForm :: ChildForm +public class InfoForm : ChildForm { - object infoLabel. - object BtmOk. - - constructor new parent:aParent - <= new parent:aParent; - [ - // Form ------------------------------------------------------------------------ - $self set x:320 y:320. - $self set width:400 height:230. - $self set caption:"About the program". - - BtmOk := Button new. - theControls append:BtmOk. + Label infoLabel; + Button BtmOk; - // Labels - infoLabel := Label new. - theControls append:infoLabel. + constructor new(parent) + <= super new(parent) + { + BtmOk := Button.new(); + infoLabel := Label.new(); - infoLabel set x:20 y:20. - infoLabel set width:320 height:20. - infoLabel set caption:"Special thanks to Alex Rakov, for the support.". - - BtmOk set x:30 y:175. - BtmOk set width:50 height:22. - BtmOk set caption:"OK". + self + .appendControl(BtmOk) + .appendControl(infoLabel); + + // Form ------------------------------------------------------------------------ + self.setRegion(320, 320, 400, 230); + self.Caption := "About the program"; - BtmOk set onClick: (:args) - [ $self close ]. - ] + // infoLabel + infoLabel.setRegion(20, 20, 320, 20); + infoLabel.Caption := "Special thanks to Alex Rakov, for the support."; + + // BtmOk + BtmOk.setRegion(30, 175, 50, 22); + BtmOk.Caption := "OK"; + + BtmOk.onClick := (args) + { self.close() }; + } } -//#class SaveBox (forms'Dialog) -//{ -// // Panels -// #field pnlFunc. -// // Button -// #field btmSalv. -// // Text Box -// #field ContTex. -// #field nomeTex. -// // Labels -// #field lblInfC. -// #field lblNomF. -// -// #method oninit : Args -// [ -// super oninit:Args. -// -// // Button -// btmSalv := controls'button::self. -// // Text Box -// nomeTex := controls'edit::self. -// // Labels -// lblNomF := controls'staticlabel::self. -// -// // Form -------------------------------------------------------------------------- -// self -// set &x:320 &y:320 set &width:180 & height:130 -// set &caption: "Save". -// -// // Buttons ----------------------------------------------------------------------- -// btmSalv -// set &x:15 &y:60 set &width:50 & height:22 -// set &caption: "Save" -// open. -// -// // Text Box ---------------------------------------------------------------------- -// nomeTex -// set &x:15 &y:30 set &width:150 & height:22 -// set &caption: "calc.txt" -// open. -// -// // Labels ------------------------------------------------------------------------ -// lblNomF -// set &x:16 &y:10 set &width:150 & height:22 -// set &caption: "Nome do arquivo" -// open. -// -// btmSalv~eevents += -// { onclick'eval = self $onClick. }. -// ] -// -// #method $onClick -// [ -// #var aValue := theParent calc_area_gui'calc_result. -// -// #var aFileName := nomeTex literal. -// #var aWriter := io'LogWriter::aFileName. -// aWriter write:"%n" write:aValue write:"%r%n". -// -// aWriter free. -// -// self set &forms'dialog_result:basic'false. -// ] -//} +public class SaveForm : ChildForm +{ + // Button + Button btmSalv; + // Text Box + Edit nomeTex; + // Labels + Label lblInfC; + Label lblNomF; + + string _result; + + constructor new(parent, result) + <= super new(parent) + { + _result := result; + + // Button + btmSalv := Button.new(); + // Text Box + nomeTex := Edit.new(); + // Labels + lblNomF := Label.new(); + + self + .appendControl(btmSalv) + .appendControl(nomeTex) + .appendControl(lblNomF); + + // Form -------------------------------------------------------------------------- + self.setRegion(320, 320, 180, 130); + self.Caption := "Save"; + + // Buttons ----------------------------------------------------------------------- + btmSalv.setRegion(15, 60, 50, 22); + btmSalv.Caption := "Save"; + + // Text Box ---------------------------------------------------------------------- + nomeTex.setRegion(15, 30, 150, 22); + nomeTex.Caption := "calc.txt"; + + // Labels ------------------------------------------------------------------------ + lblNomF.setRegion(16, 10, 150, 22); + lblNomF.Caption := "File name"; + + btmSalv.onClick := (args) + { self.onButtonClick() }; + } + + private onButtonClick() + { + var fileName := nomeTex.Caption; + var writer := File.assign(fileName).logger(); + writer.writeLine(_result); + + writer.close(); + + self.close(); + } +} diff --git a/examples60/gui/c_a_g/c_area_gui.prj b/examples60/gui/c_a_g/c_area_gui.prj index ebc35b3751..1852a801b9 100644 --- a/examples60/gui/c_a_g/c_area_gui.prj +++ b/examples60/gui/c_a_g/c_area_gui.prj @@ -11,6 +11,7 @@ calc_area_gui.l + anot_wind.l diff --git a/examples60/gui/c_a_g/calc_area_gui.l b/examples60/gui/c_a_g/calc_area_gui.l index a572e6b8ec..7cf32fc167 100644 --- a/examples60/gui/c_a_g/calc_area_gui.l +++ b/examples60/gui/c_a_g/calc_area_gui.l @@ -44,16 +44,16 @@ public class MainWindow : SDIDialog // ----------------------------------------------------------- // Panels pnlFormula := Panel.new(); - self.appendControl:pnlFormula; + self.appendControl(pnlFormula); // Text Box valUm := Edit.new(); valDois := Edit.new(); valTres := Edit.new(); self - .appendControl:valUm - .appendControl:valDois - .appendControl:valTres; + .appendControl(valUm) + .appendControl(valDois) + .appendControl(valTres); // Buttons BtmCalc := Button.new(); @@ -61,10 +61,10 @@ public class MainWindow : SDIDialog BtmSalv := Button.new(); BtmSair := Button.new(); self - .appendControl:BtmCalc - .appendControl:BtmInfo - .appendControl:BtmSalv - .appendControl:BtmSair; + .appendControl(BtmCalc) + .appendControl(BtmInfo) + .appendControl(BtmSalv) + .appendControl(BtmSair); // Labels valor := Label.new(); @@ -73,11 +73,11 @@ public class MainWindow : SDIDialog letter2 := Label.new(); letter3 := Label.new(); self - .appendControl:valor - .appendControl:info - .appendControl:letter1 - .appendControl:letter2 - .appendControl:letter3; + .appendControl(valor) + .appendControl(info) + .appendControl(letter1) + .appendControl(letter2) + .appendControl(letter3); // Radio Button Tconta := RadioButtonGroup.new(); @@ -86,18 +86,18 @@ public class MainWindow : SDIDialog Econta3 := RadioButtonGroup.new(); Econta4 := RadioButtonGroup.new(); self - .appendControl:Tconta - .appendControl:Econta1 - .appendControl:Econta2 - .appendControl:Econta3 - .appendControl:Econta4; + .appendControl(Tconta) + .appendControl(Econta1) + .appendControl(Econta2) + .appendControl(Econta3) + .appendControl(Econta4); // Images Formulas -// _paintbox := Imagebox.new(); -// _imageList := ImageList.new(); -// pnlFormula -// .appendControl:_imageList -// .appendControl:_paintbox; + _paintbox := Imagebox.new(); + _imageList := ImageList.new(); + pnlFormula + .appendControl(_imageList) + .appendControl(_paintbox); // ----------------------------------------------------------- // Form ------------------------------------------------------------------------ @@ -110,46 +110,45 @@ public class MainWindow : SDIDialog // Radio Button ---------------------------------------------------------------- Tconta.setRegion(7, 1, 150, 100); - Tconta.Caption := "Escolha do calculo"; + Tconta.Caption := "Figure"; Tconta - .appendItem:"&Paralelogramos" - .appendItem:"&Trapezio" - .appendItem:"&Circulos" - .appendItem:"&Triangulos"; + .appendItem("&Parallelogram") + .appendItem("&Trapeze") + .appendItem("&Circle") + .appendItem("&Triangle"); // Econta1 Econta1.setRegion(7, 105, 150, 100); - Econta1.Caption := " Escolha do calculo "; + Econta1.Caption := " Figure variant "; Econta1 - .appendItem:"&Retangulo" - .appendItem:"&Quadrado" - .appendItem:"&Paralelogramo" - .appendItem:"&Losango"; + .appendItem("&Rectangle") + .appendItem("&Square") + .appendItem("&Parallelogram") + .appendItem("&Diamond"); Econta2.setRegion(7, 105, 150, 100); - Econta2.Caption := " Escolha do calculo "; + Econta2.Caption := " Figure variant "; Econta2 - .appendItem:"&Retangulo" - .appendItem:"&Isosceles" - .appendItem:"&Escaleno"; + .appendItem("&Rectangle") + .appendItem("&Isosceles") + .appendItem("&Scalene"); Econta2.Visible := false; Econta3.setRegion(7, 105, 150, 100); - Econta3.Caption := " Escolha do calculo "; + Econta3.Caption := " Figure variant "; Econta3 - .appendItem:"&Circulo" - .appendItem:"&Coroa circular" - .appendItem:"&Setor circular"; + .appendItem("&Circle") + .appendItem("&Circular crown") + .appendItem("&Circular sector"); Econta3.Visible := false; Econta4.setRegion(7, 105, 150, 100); - Econta4.Caption := " Escolha do calculo "; + Econta4.Caption := " Figure variant "; Econta4 - .appendItem:"&Qualquer" - .appendItem:"&Retangulo" - .appendItem:"&Func dos lados" - .appendItem:"&Retangulo" - .appendItem:"&Func lds ang"; + .appendItem("&Common") + .appendItem("&Rectangle") + .appendItem("&Equilateral") + .appendItem("&Isosceles"); Econta4.Visible := false; Tconta.SelectedIndex := 0; @@ -164,16 +163,16 @@ public class MainWindow : SDIDialog // Buttons ----------------------------------------------------------------------- BtmCalc.setRegion(430, 10, 150, 22); - BtmCalc.Caption := "Calcular"; + BtmCalc.Caption := "Calculate"; BtmInfo.setRegion(430, 40, 150, 22); - BtmInfo.Caption := "Infos"; + BtmInfo.Caption := "About"; BtmSalv.setRegion(430, 70, 150, 22); - BtmSalv.Caption := "Salvar"; + BtmSalv.Caption := "Save"; BtmSair.setRegion(430, 100, 150, 22); - BtmSair.Caption := "Sair"; + BtmSair.Caption := "Exit"; // Labels ------------------------------------------------------------------------ valor.setRegion(170, 105, 245, 22); @@ -189,52 +188,52 @@ public class MainWindow : SDIDialog letter3.setRegion(170, 75, 14, 22); // Image Formula ----------------------------------------------------------------- -// _paintbox.setRegion(12, 22, 379, 139); + _paintbox.setRegion(12, 22, 379, 139); // Image List Formulas ----------------------------------------------------------- -/* - _imageList.assign:_paintbox; + + _imageList.assign(_paintbox); _imageList.setRegion(0, 0, 379, 139); - _imageList.appendImage:"..\formulas\Paralelogramos\bitmap1.bmp"; - _imageList.appendImage:"..\formulas\Paralelogramos\bitmap2.bmp"; - _imageList.appendImage:"..\formulas\Paralelogramos\bitmap3.bmp"; - _imageList.appendImage:"..\formulas\Paralelogramos\bitmap4.bmp"; - - _imageList.appendImage:"..\formulas\Trapezio\bitmap1.bmp"; - _imageList.appendImage:"..\formulas\Trapezio\bitmap2.bmp"; - _imageList.appendImage:"..\formulas\Trapezio\bitmap3.bmp"; - - _imageList.appendImage:"..\formulas\Circulo\bitmap1.bmp"; - _imageList.appendImage:"..\formulas\Circulo\bitmap2.bmp"; - _imageList.appendImage:"..\formulas\Circulo\bitmap3.bmp"; + _imageList.appendImage("formulas\Paralelogramos\bitmap1.bmp"); + _imageList.appendImage("formulas\Paralelogramos\bitmap2.bmp"); + _imageList.appendImage("formulas\Paralelogramos\bitmap3.bmp"); + _imageList.appendImage("formulas\Paralelogramos\bitmap4.bmp"); + + _imageList.appendImage("formulas\Trapezio\bitmap1.bmp"); + _imageList.appendImage("formulas\Trapezio\bitmap2.bmp"); + _imageList.appendImage("formulas\Trapezio\bitmap3.bmp"); + + _imageList.appendImage("formulas\Circulo\bitmap1.bmp"); + _imageList.appendImage("formulas\Circulo\bitmap2.bmp"); + _imageList.appendImage("formulas\Circulo\bitmap3.bmp"); - _imageList.appendImage:"..\formulas\Triangulos\bitmap1.bmp"; - _imageList.appendImage:"..\formulas\Triangulos\bitmap2.bmp"; - _imageList.appendImage:"..\formulas\Triangulos\bitmap3.bmp"; - _imageList.appendImage:"..\formulas\Triangulos\bitmap4.bmp"; - _imageList.appendImage:"..\formulas\Triangulos\bitmap5.bmp"; -*/ + _imageList.appendImage("formulas\Triangulos\bitmap1.bmp"); + _imageList.appendImage("formulas\Triangulos\bitmap2.bmp"); + _imageList.appendImage("formulas\Triangulos\bitmap3.bmp"); + _imageList.appendImage("formulas\Triangulos\bitmap4.bmp"); + _imageList.appendImage("formulas\Triangulos\bitmap5.bmp"); + // Events ------------------------------------------------------------------------ // Radio Buttons ----------------------------------------------------------------- Tconta.onIndexChanged := (args){ self.TipoDoCalculo(Tconta.SelectedIndex) }; Econta1.onIndexChanged := (args){ self.TipoDoObj(Econta1.SelectedIndex) }; -// Econta2.onIndexChanged := (args){ self.TipoDoObj(4 + Econta2.SelectedIndex) }; -// Econta3.onIndexChanged := (args){ self.TipoDoObj(7 + Econta3.SelectedIndex) }; -// Econta4.onIndexChanged := (args){ self.TipoDoObj(10 + Econta4.SelectedIndex) }; -// -// // Buttons ---------------------------------------------------------------------- -// BtmCalc.onClick := (args) -// { self.onButtonClick() }; -// -//// BtmInfo set onClick: (:args) -//// { $self $onButtonClickInfo:$self ]. -////// -////// BtmSalv~eevents += -////// { onclick'eval = self $onButtonClickSave. }. -// -// BtmSair.onClick := (args) -// { forward program.stop() } + Econta2.onIndexChanged := (args){ self.TipoDoObj(4 + Econta2.SelectedIndex) }; + Econta3.onIndexChanged := (args){ self.TipoDoObj(7 + Econta3.SelectedIndex) }; + Econta4.onIndexChanged := (args){ self.TipoDoObj(10 + Econta4.SelectedIndex) }; + + // Buttons ---------------------------------------------------------------------- + BtmCalc.onClick := (args) + { self.onButtonClick() }; + + BtmInfo.onClick := (args) + { self.onButtonClickInfo() }; + + BtmSalv.onClick := (args) + { self.onButtonClickSave() }; + + BtmSair.onClick := (args) + { forward program.stop() } } private TipoDoCalculo(int index) @@ -269,7 +268,7 @@ public class MainWindow : SDIDialog private TipoDoObj(int index) { -// _imageList.SelectedIndex := index; + _imageList.SelectedIndex := index; valTres.Visible := false; valDois.Visible := false; @@ -430,103 +429,108 @@ public class MainWindow : SDIDialog info.Caption := "Info: Al = Alfa ( angulo )" }; - //_paintbox.refresh() + _paintbox.refresh() } -// private onButtonClick() -// { -// var result := 0; -// -// (_imageList.SelectedIndex) => -// 0 { -// var H := valUm.Value.toReal(); -// var B := valDois.Value.toReal(); -// result := H * B -// } -// 1 { -// var B := valUm.Value.toReal(); -// result := B * B -// } -// 2 { -// var H := valUm.Value.toReal(); -// var B := valDois.Value.toReal(); -// result := H * B -// } -// 3 { -// var DM := valUm.Value.toReal(); -// var d := valDois.Value.toReal(); -// result := DM * d / 2 -// } -// 4 { -// var BM := valUm.Value.toReal(); -// var b := valDois.Value.toReal(); -// var H := valTres.Value.toReal(); -// result := (BM + b)*H / 2 -// } -// 5 { -// var BM := valUm.Value.toReal(); -// var b := valDois.Value.toReal(); -// var H := valTres.Value.toReal(); -// result := (BM + b)*H / 2 -// } -// 6 { -// var BM := valUm.Value.toReal(); -// var b := valDois.Value.toReal(); -// var H := valTres.Value.toReal(); -// result := (BM + b)*H / 2 -// } -// 7 { -// var R := valUm.Value.toReal(); -// result := Pi_value * R * R -// } -// 8 { -// var RM := valUm.Value.toReal(); -// var r := valDois.Value.toReal(); -// result := Pi_value * (RM * RM - r * r); -// } -// 9 { -// var Alfa := valUm.Value.toReal(); -// var R := valDois.Value.toReal(); -// result := Alfa * Pi_value * R * R / 360 -// } -// 10 { -// var B := valUm.Value.toReal(); -// var H := valDois.Value.toReal(); -// result := B * H / 2; -// } -// 11 { -// var B := valUm.Value.toReal(); -// var C := valDois.Value.toReal(); -// result := B * C / 2; -// } -// 12 { -// var A := valUm.Value.toReal(); -// result := ((Pi_value.sqrt()) * A * A / 4).Rounded; -// } -// 13 { -// var A := valUm.Value.toReal(); -// var B := valDois.Value.toReal(); -// var C := valTres.Value.toReal(); -// var P := A + B + C / 2; -// var val1 := P-A; -// var val2 := P-B; -// var val3 := P-C; -// result := (P * (val1 * val2 * val3)).sqrt() -// } -// 14 { -// var Alfa := valUm.Value.toReal(); -// var A := valDois.Value.toReal(); -// var B := valTres.Value.toReal(); -// var AlfaConv := (Pi_value * Alfa) / 180; -// var sinAl := AlfaConv.sin(); -// result := sinAl * A * B / 2; -// }; -// -// valor.Caption := ("Res: " + result.toString() + " m^2"); -// } -// -// private onButtonClickInfo(form) -// { -// //calc_area_gui'InfoForm new parent:aForm; run. -// } + private onButtonClick() + { + var result := 0; + + (_imageList.SelectedIndex) => + 0 { + var H := valUm.Value.toReal(); + var B := valDois.Value.toReal(); + result := H * B + } + 1 { + var B := valUm.Value.toReal(); + result := B * B + } + 2 { + var H := valUm.Value.toReal(); + var B := valDois.Value.toReal(); + result := H * B + } + 3 { + var DM := valUm.Value.toReal(); + var d := valDois.Value.toReal(); + result := DM * d / 2 + } + 4 { + var BM := valUm.Value.toReal(); + var b := valDois.Value.toReal(); + var H := valTres.Value.toReal(); + result := (BM + b)*H / 2 + } + 5 { + var BM := valUm.Value.toReal(); + var b := valDois.Value.toReal(); + var H := valTres.Value.toReal(); + result := (BM + b)*H / 2 + } + 6 { + var BM := valUm.Value.toReal(); + var b := valDois.Value.toReal(); + var H := valTres.Value.toReal(); + result := (BM + b)*H / 2 + } + 7 { + var R := valUm.Value.toReal(); + result := Pi_value * R * R + } + 8 { + var RM := valUm.Value.toReal(); + var r := valDois.Value.toReal(); + result := Pi_value * (RM * RM - r * r); + } + 9 { + var Alfa := valUm.Value.toReal(); + var R := valDois.Value.toReal(); + result := Alfa * Pi_value * R * R / 360 + } + 10 { + var B := valUm.Value.toReal(); + var H := valDois.Value.toReal(); + result := B * H / 2; + } + 11 { + var B := valUm.Value.toReal(); + var C := valDois.Value.toReal(); + result := B * C / 2; + } + 12 { + var A := valUm.Value.toReal(); + result := ((Pi_value.sqrt()) * A * A / 4).Rounded; + } + 13 { + var A := valUm.Value.toReal(); + var B := valDois.Value.toReal(); + var C := valTres.Value.toReal(); + var P := A + B + C / 2; + var val1 := P-A; + var val2 := P-B; + var val3 := P-C; + result := (P * (val1 * val2 * val3)).sqrt() + } + 14 { + var Alfa := valUm.Value.toReal(); + var A := valDois.Value.toReal(); + var B := valTres.Value.toReal(); + var AlfaConv := (Pi_value * Alfa) / 180; + var sinAl := AlfaConv.sin(); + result := sinAl * A * B / 2; + }; + + valor.Caption := ("Res: " + result.toString() + " m^2"); + } + + private onButtonClickInfo() + { + InfoForm.new(self).run() + } + + private onButtonClickSave() + { + SaveForm.new(self, valor.Caption).run() + } } \ No newline at end of file diff --git a/examples60/gui/c_a_g/formulas/Triangulos/bitmap1.bmp b/examples60/gui/c_a_g/formulas/Triangulos/bitmap1.bmp index 7aae63fedcb9387897a417a09d3aa4280f83cb35..a0a04dc2085895c61770d49bf278f110fc62f0f2 100644 GIT binary patch literal 210778 zcmeHQO^75%cCN*jJsBSiCU1uF!Ql3(y*B8S_)uPUFssXe(V-5Fpuux6jHQCYH0U5P zhlB>P1B-_(=p7I&GzksM8mXaZum?m#AqfW26bSDy+cYdfG(+K?ogHe!@5`E39hIGx zm01~)kv}h>J1a9I=^*?){rxrl{m1t@oq(?2>-;7C?{xl( z-v7^^cA~%N!Q!9teP7W}`4bF821Eu#1{x>>-~ayiqjFUZ2=n<|y?*^V`onJtbZq36i5$VU#a3`cE}u7_U#;~)PR{Xy^ZpJB)(xfBGX zE~kJauNvbou47R)LDxga!)F8Cj^D87CAdLAbiEtg>q1rJ!(B<$UDrd$!b)hQq;jW~bpzF`h&Xlg- zfA+JViC@r>NJ(9G1bj`%ihQ^$s3z!opcj`R=zCrNyF<8Ll;h>luG~v*Hz6SMu?Zo2 z@0+6Qq1R#G>j8QD^{;=eKa$^;5sb9Id7Xwk&kVWEB;+mbUl!W=LPq1TfaDBl0q5+QkT=vk#`~=?qndYAKh_MoHF}y zI8U(aC6tQ*u>bD6@5&`A)M|r(=z4cW#d^^l2j(az`EkspE-7U}0P>{oOO)jsiPIhg zMAy43>n7=XpeVBBPL>3Jx7gQ#y3|j1rPMTC4?hm(-iU4KMy8}LyTQFKR7F1Al~j{- zJ^b^?59ZcOaD#xu6Ku`P-X zk-FTLlHM+#A|Kn~X5yhQ9GJ+qq+tmGsmqptZAh{rAMOgW>bibs zFI=vX0;L7ScGQo4^rK4f=t{@Br2B&({9suoacPyh97ja%bp%8{bTrESt?PPF z#yxa?Rl<|2xr+Pi!|;=c&#Lg)7Cx}|0ow!6_vi!0gVg0XB66=IAo8K3QSR@!uIIWu zoleVTgs8=NS;qi$jL6J7bj&};x-`ZdxTo0yQZDB4Z&HdPAMQ#M*vIjQ%?2Mq*&&IS zBpz7rB)yYoW)XPu(a7q`y^hHkooz~e}1cd zN{T1XwnqSE|KlJ3IKmm%tU>B>R;1b)Pvpa0xv$f&E^PaCyu{Jramn~|xi5|YeDc5- zWdRw;8>BAhMXX)%MLyh>_d5OR!nR+>OB@~1^>IXs-@_-*{UwwG%72?6b$J`q+VhRb zhr6;))331W^7P+}<|2(3J#EqTIvT})L$9+>{-cjRDwLqq`Q z3LCV{_Qzf6*rAMZS73{BH(j=AvScSWl4_k05czOdTEKo2{&-)8Zsl>obvmA(qdkzb zNb<`}mbFm%Q(gUHlPs;qmb@tA>OugGu-7)D5F1ywi@M!ev$1Ub=fw;^-f>p!(I6S`z-iF zPry%Z)3(pbi#xRHLm57KjJE<)(?0n$6tc)t+V}FV*$9YyxGUd0`W10)+V**Pafev7 zDZ?j^@eE*zw%KNRB_RR25(I&D2#9>FL&pB|Jo?qPZJ&o1`^eOb0{i3{L#&H(5u`4= zK)pURMLyh>73+qq93Z|eJ(8D~tUNb8-e;eEwph}hUfdz)j`DAQ^PA;b zDEQ>76r?U!sWhs`i^zw>BDI@_8mUZ2O`}1e4b)=ysKQJt>-0<-Uhcp0P){l|Am7 z1rVvrSx{7Ul)V@qvP1^QZWMM{d^@54I81?Aad<8tb^Xc6rAfLUW4nWO98T*sjgd|J(*`zON zR~rG54|nAQ?2F)U(zega%S(dm?r5sQKGtZGgI)`)>&F9+p1#oDRQqRqEmRf9Lb4!O zM3%CoFLCOPfXIit^2@4U*Kuglw$I87EcxO1g&KOEn!gyYu=Xw8?GDC??Z8UJ3f;gb z&*QExd}1b{kh*LV&E}=mHu-o(Mfkz^itK4WvZ-0e;krwI-;M{R6*ALaM{uVFFM6Iy z8ZU9#A+ug}y@BfazWOxitNCoI2s+h2JXd!*p1Mw$qZ3cV)jfRjy#5&We3L>O>vEII z&vstgDj)0gy=}bp^wad~jeV?tk^Gy_Gf94%?P(e>@f2Xc_sD*qo(C!jC#pkz41AA1 z$kpVCqEm#51^DE#mk{UE*1ke6vyHq-5CqmC&}R97^?oqAP?uxa^5yF%);mdM)1^7= zN%I<$;^G<7Dq`EG@e-$5x4D)2{$%mIH0i$0b-799Xe%#mmyc(p;@{Z|o%kKn^egQ8 z#oWbgCC|1!>{r`?=i5|$ZsnI>ez`ms3cmTKhql+{rk8Kg{E2)h6<*HOz3!fRby@D( z{xn?=fBhl(MDhfr2mih8fSL3Av>`&$yi41(v!q|;{mHWMzik|;%iAK?j_*W1l;XL9 zWzQc;)Af+Pt{=Ra>yj*sAJEvS9$>p-ys-@1UZ-1?-*sOLRTM|5%S91v_V*$mixr-* zQ-?I~B|c}|X6bLz^`PDL2Wm7})#-<)Q{~Zk=;?6vIpQPDGHiR$s!HIsP&`k*u4|!+ z;wg2xD1y!YzHRb>5!i<`Y4Cb-xGY#+3+j`eOxn|H8PV_$V4ns5;CQ^8>w@@6bMBcn z%qQH&w$I87)2Yf;-=C~1Jh|c{i!9~gja-|mHze76Bd7Y6?IPGn`g6a8I`otVjIj2^ zBU&NZLCrGY6d0Gj#=>wuN(o^PnG4*@X&oFCU(hypo*^ z|M+}X-rnn6M@-|7bo0(Bw8e|*ym5MU-Jgv4w{f*mm!adYanPx*Gd z*z1&aFYEthL<>KlBe8Cq*Ks_dg&q5YL(-Xj^`O^LUyNzIYQDO6ht5V8UC*}Ph|*K@ z#oCd<(S&IFndWe0(e=FUaF296umz?+B|UU{Kx=+d_}BB2_qPrC$jgI^_>hsE{^7FS zeoXE5tE=+#Jo0Qyzw%n4Jm;C%;>C2?B2OQE^ihNz`Y&zsSEb=;t1c($dz}x~zq_=K zF3-AioOjTn^A1?{lCJUbf2OrhwAgOW)7E6s^~f8}-MQQ8s+ZG68wXu{FTAAnjo!vN z99eWd;&jONkI!X$N_y$l)fYOv#(vw94`U2AI3bp88(Bo!dHmKkc`=bc_Q^A!dGcn0 zejU;PHnsxvX+S=WS6Aai5?D*!p|#X;-IW-*;6v=uu}gb&aJvHie>j=ZGk^JP9f_>E z9{KSoKl*;I{4BmVNSsy{UC(xXne#zx%10anxnD(q_15ZBGk4I1NI$D>Z@lNk2PZ84Oa>22mmLWf&Cca9-U7xzg!^& z+Zuj!pL{ER|Hdzac?6S_QKAoe8y^mcf)?y}-G9#dc2irE)vo9K@VEfzvL1`;ZM@S% z7P}tt(RO;?-mN_Z^|Va>wjm!hysY}cDfQ=eh*h)zH|2x%W=x^W9*V|gZ(G^d+2VD{O@dAV?R9JFX^aHdtlEl z^yr0tV}Fx9+TWy4{`0HzLv=nQy-Dj)HrdHpbv>9vUg4J-QhSAY9GKIQg+^9gkM`u~ zg687Tyb#PMx~BO=!*HrbJ)acj6f77Gw&Vjgz=t%Jq3<=bZae}RiuVav_vqK8zLrri zN=}UPW|J&v)Wz=spFFou;9JIB^GOCUvmMxePO{h72d&%I+!yf3-sd*J6pu)o=g{4u zy#HJ9A^GgPiR}>6%%kg<`MK}W9p4H0`U-KHd3AmKdt3LW2fBJ!viq;=^aJ&%MNaO{~Y-A>N*adlUn)>J#E~e(J;dZB9+gN1Osm_A&XS z&JPDPwlRywXp?LL@!`agGk0G_+rEsoP^^1+d@b*~8*?R4PD(cFvhF8A`tV_#AKhN> z1A93>{{r#xSH_x9TL^PMCdp@Ii>9q~ZOBKQSIEnNeD~jk`?NperHc3Q;_=&Z&vl`U z{KB?R+t;@&UNG*;K6&tD(ioy~D@#7m zmmAVr>;8iWv>we{u1AaW)292f^eZrB+kV}7CboIuwNUJn&pH>hs652`;L!hB*WDDQ zUH127)#bADCG^Z7P^Nsa@7||&vdlfk%phex72EnX&M}{75`T_+o4lZXVI6P7C!drb zewJt54S!SDYngSqt{AnM@3Q3s>j!pe{Xo+E+_sg2P5rtKOVCWR?QQS^pFI3VNZZv~ zD7NFbS$DGz!>T?9&JqNHbqJI#AMo8jpgr=Qhcv#^@?b;1Zh~~3ZEup7`2J*@c(VO| z+jTd#`7)h;*>%}8|B{|v1ezcpsLP`@=tFL;^?9?$(*w?+%=Mts`m zg8LvGAL(C2Z53u8Y#&VO*F0Q+ZhTDC1TXN(V=rY+EAPI_dGe4qu0Ee6>$;n~G+f6A z?h*unbqF*;J}@sz-}mU8)}i$VM}_yJ=d~328W8MtI`F#c@hQ$DAFYEm({t8|nIapE zWaF$t*`Lf{0d1L76YBDoS(nc;AkYN);JLl}8Z91^3->%)zOlMbQwCU;QJ~uo{qAz@ zAoj?(OM7JSzShf#Tl{dP>%l5$$8Gy9vY_;}P-$~Iw@F*R$%jA_>T`dm(a#_MSEV4}x`ZpS{>yiO47#@`x@jqL5=QrBZX4Ccnb@3Kw6eriYqc|bZ6 z+#}G0y6hgs=5o*!`Cy%_@2`YsMbA&*y`JvTSz*}Mhy6NwA7WeSaH;FTGwA2F?e+c1 zpyTs?zb#hs-DU)uQkOU9RAOv{KvU#{&k@kijKv;AIOnU#UTdt|9}LJxKX?%B%Zl|m z`*bdje)hn&*t^7^?eZ+=nYdaDwGFOq{l=v%wH5O^<+~~J!9E-8%Y?n4U(*~MtdBIY zUp{pEqh3!PeLYb}dvvzI^@Z}O4Jo=F4A{HIAM|<8f_1!LK0fAZ;(gg`q3TqZT=TlF z{9N-T^s9kDljMWf!yk|CFV7ACz$f3!)wmGY@CEIY&;Hd_s6sl31#>&~{=>G31AEu_ z>v}%UOBwr9t`Q45oPuh$?ljOtJo^OCdmi;*7Ke%u&L}gU45SYrf;&mXC0d*uFW{QZ4bT9e3i97 zna#YlDeWfJXfhm}RSd32;M zH?K@h=1AnjB%1lsVjY+7D|4~?hv%ecJ+(vn{ga@-lJHMYr|RiZu=332&Cn~aeX*Gj zmuX8~c8PxVX^VWgDtT zRs~&;^Awqnf!|S+lN;X-BQvB!7;%m-`*v`@L-$WdH+=!mA4dIyPv7(px}CoI#ompr zj{8Ubn|q{+9+HlHb#<;@(T9&GSJ7FzL(=(rfZiQ?p8D>^SUotLsE4P= z>Oq&zZFv*+!z*=LhrFqbS(z$H#-^{Vtv9h%Fl@r_ahn{VG~Wn+v)V)v^O(#el@3aB9GL0uxL--qVz9DH#~B>O}+9`7sP1b1b=J#sY6}oJ4c$(^ zJDRG~pu0@6+YjlSFKScf)2N-f7hbAe>MJk}L`hGHPTk3KXOVwPS zL_W-6nKz}X>iTafBha&V$Y$mc*WJ+7y6%SE4xh}Nd@=~6+LcebRu6Y$_vk-F?aBO7 zar>aBxryeTU=sB|UXkwzJ}B@6UlRxTarXST__py^smqNo;zAh|`6vWmp^shadg$g| z(&f6(M9&P{_P?a@(xdQP{pw=8;!{D~xbE%^$4mb|zW1napxf2Zz4|@U@MvCtNb~t$ z�}K%*fVX_}h=jho6P!PJg5@zVKoiDjGIWK8*o$KwI&PL03H*ovMf9Q)&mA?Z210 z%q1_^Bm_i0l29qRbG~cWR`+)R50>+Dh?~ulf5s;Qo z{5LsBU2bye7SEf=M{x|dO##@u#2-Eo_-U>ux92Ca|2*j4_;I$)r~ciryXx1`-^uS{ z2)LA`Vw}s@WgsB(Q3lG%G+gU?a0MR-Y~fc|i#asRDg5o&zd#?4<#$D{vSz9Xdg!yQGJ|m>fK6KORw>>?n%Wao{^!$r_q~l}r zEwC5-Z6e&Rv_+QMRo;1XEAo*SF>~=n*PFvqQo=f7^L;VFwK)ige7Gx1(e>`IZz5%> z%S|j*b9oZ^Fo$K{ltkC(MNHzSAs}@*4IOzW^5ISfMAy5+zKN8jE;q4M&E-kt!yJ}* zQxaXD7cq&ShJe)NG<4*h$cH-_U|lcQ#e5{eL2wWm5E*E)47h7;>`}(PlOdgbqR-jy z(L9myXh3^mPVEtHamuJ85(I&D2#9>FL&pAdZolkPDxU)HbBR4HS-10gTz&83@;PfR zMXAfpEn5>g6ZtTK;&y2?RoC-g^!iyOK_D`EkRB#+F_Z?0;`>-6un@vUPa3!8q-S(@ay9|sU6x| z{?niz`Fr@hT0Je^V|m@Vi6J?NupdA6@wph&`6c7aXuo~khZGTP@IT;NcHnZ+%NV~G zXGzi_2(f@ZUr6WAd;TDj3zYFBq&@fMbkGcim-L7I@w$}8^YG@}8N6dz!8r<#$v61w zYO*}ftV7Qhd+O0ymv7F{jGt$W?{s;ftz6ZR&cwla3*b5Ed+KTu(o=A$)HAy5?1dzo zouzDYe%Hz26Ebpk`iD_^RU4mjAs-Qt^pA04Inm{V&&uF;xcc;mzCVALg!d*{(&c4D z^774;&Re4MlHxjud9-=uyxF8tByHB8;FIgoy7XArV_&n2%Q4lNGdg2@u5d2xBf|M4 z4C(Bs@vYCH@p(@)&^e;|c6xac?Wc_L9Z!zc^YLTS0rN-)B%P(j`hoeJ&T#(hDb+WR z&d%znua0lpmRk%o=mGNYBB0LUOff#ACe1&`b_C9*IS+jLa;7GvA15a#OMTC}Ixcfu z&iM8#I%oLv37uU@M<;T&L^)l)# z*094i+{(s z$Ne)X-+;>3?=S2)*hnGS@36@bpeJx%70URO&O3a3aj8xY2h{$CD`k$jtOMd_X|X&2 z%dk)NTU{-65BegXKRZ`1zd1t^jSenl={X^b^XkEaZnMP!*Xy5t{^i#sZ2vo6)v@oJf2?6NM6Q@(}6BooX3W@>*bI!@F_mGcTA%S z^ATLiM+6-G1A;##yWlC!$K$>|zYD05?sU3Ko1ULDhVgp8NtQ0=bPj57wCp4Dcp-3j z5_Hv*vuDK6H%!Lr6*Q}W|GG@-dRVUyN%1-E%{hgOdV#)yN4^!m*!Rf3obO zKmALp_uTg58&2yjl82K4oe@lD&vRfI(B)Atf3yK}^f1=Y(pfqnekABU$HXU-=1efgWFU4gU9z;#vE!*PC~Ke;W3UOvCNrn7R6 zA|LAIct~&Ok?n`R-rLl64}u4z6ZYu&Vtj|&0hSd`ALq(<=v?_dvI8#1bWZXVHeyft z)Lx9KA2}oa4PT)ycPwXkc1eBw$K=1kID&po8_TPnr*(3e)HWnNW1h>tx|R<;zq-$c z^&nq;Di7`#;hQwP(_{&f#P7My=e}2x|6k|N^l#3a>2yt|$8D-^t6-k|eLA=5<#e<{ zigDz6!SxdPmI&e zVYY!cz}aQsGGn>sYusLD9n0-BApJe~`=MBByf zP}%w=E(@;ZBhC-T#t%jp)XpA6II*wBr?S>{eHz}^gs*;Xc3hVDp39H@(tIE1$<{sB z1zYKxNLSa_%rCBSthnuszdI#|z2^_3xeQN7eQKj;(O9@1kLv=Su^rECg0Gc3#{=yt z*SF2FPB({ISf4}FV!pZ*{VnCk^Q0MA&) z7%RwVmt^#G=&R>s|ARL78+7?!`T^ebA=b$ukIC|Q1Gj-Jr%bo(EAn2o0691~7)O0{ zuHPs#UDxyTb$F-A653kUL1@o^JEOiG&BXy0T%KiM0(w=%U(Y+++^8pPm+)M*NpOdv zqNXhZ#$k_7Ce$Y%t>B1x7X1Kq&m((`>YBEemcK=u;P^xhyEN}IHg|&UFz|9lW9j|i znCf{~J*D|JnA6F19%+FGjP*k|d`x!W?)^v0ddsw$dUY*Jx?a@vDci~@d!BoPGC)86 zm*h8ryny#TvccIeN5xF?FplKmn&e@R?7yMsMdLY;0j$?xSwUKm$#6VX?@(G8^QGa{ z=p1F%*(|dj$%W1XzD0oCJR;fUxu9s5UQ@etL+i_6=sq{J-sT-#c?ek z3#4!VhwVMs57j5<&=LJxW3yT6eVQzR;yD#Ce1-4>JbbiAWqN<s`%@< zWxGVT<$>*!Ga551X&hVUM}8+G;98bYC%G@hemroh_xbAB$KrP4F0~VJzh!bsRP(88 z`A9>B`$FKciDPWYSC#SSveE0RZbS3?|E9|D9P<|_pbbEO`3~9e*VK2GP#ywRkR`SY ze3EVMhqI3q{MAv{qXf~8eL^<=^OO3@bQRf0*F$0oqx z@9WYW?f9DMP2W}hJ+QAj{%of)uj{VdXBWHPoz%IOB_2adl9Bjc2t`rizJfkKvS^x3 z|K7EHWWl!y{imdSa-B$eC(i_dya?2xF6YhDy7m)a8mm)k-$%A|LP@ zd)^>g@6Z%|FS@>!RnA(b>r$7k0U!ydB2X9k;JF}}3;*Ph_O)(+eJ{E`RW#*gP6X;w kmvd%Iq8ma$glATl5_&{P@te>^)d(*OVf literal 158514 zcmeHQO^72&cFy%_PsRs>oo8JPE?-<8ALf+!ATQgPnM=bm2OY#hf%{-+&m;)bFo#+C zkWese!{TNIH4Os`MMA-{X0{+HFbzXNGCR-=LeO}dULjb9p(zq?Z*P%Kf6`YK6`e}G zl9WFRNs-Xip^U#5-xvAv#fzW(r+@kTdw=Fku7AY8zrnx%_@3hg`2Ty(U*j*Yr+@A^ zlYiRfd7k#m1}y>>0gFH_2z>wh-_NoPMdPn&SDL1m(+dI9WHUq_Gl??#LM8H7eEHyyD@*;Etf@2^=`tSJ(m5n8dcQ9$Oq@4nmF<{R5^@M5fNYZq+tJUfOCKXb#YwPR(V03c88N;6Qr zofT>FP}yq^0tClch>R6%4xCNjw)ixS_+s^0UId&7j*^P zwwWARUIbp&t8?}`hY+CcID^m^gtSrf5U_oF9y05_Z+Q{$U!%_1>xQVE*S_O?8(Fm@ z5LFxn^ok?w-L)cMc@f|zI0~XL3_oh*djDTPa-6?Kz3S?CfAP^r|K3RDn_Y>{CeYJ= z+OQ!ASY8Ao2oC@L^rt^X;Kx7yaRblf!G|CH<=?%J>UjN?TWS%L@mW`_|hwK8{hzxK*1u-7w}vpyG>IQ0+ts6Sb~#-s3ubfwd5+&1>13*1J?~LJwOEf zb!3FFfTxhlM%9gg-pw7du~ z0-R`EtaFeHu@&k8I!I@=4evl5?a0|&!Wut;slq7Rw+mre`%TM>Kmoy-2hr5hd2dHl zfq+s~Q9x3;ZVK1O(X!15yC z3~)xNq;rrLX(};wP!29ZnC**#>jr)*v>JN55)5+??HZoB<{SId@*+?}aAb(8GIdak zT#+E>#zoO}!zN>~UrqAw4xTjuSW~f<7Xes;b1OthQ2xO|A-Du#wkGP=zy3808#J~; z*G(ZfJA!9n+fBY{c@fwlIJZKCX9sC8QV@!|H3}u*x;5EGCs=%YW+lzsdORyZsrf=I zF9PNSXAy{yrsVW4O28!uv(Zt%``z!TnPK5H){rg6voQ?osL1jnph|ESfr!U>l{9q( zNeZKa_%dj%u~6y$K~l*GbFSD4aI|OGzi1;>#%R*(ZFc4p6 zUMooAKrgfKrk-Gp;X2m%E!&(0iCeZ__Hwr^JgW95ZdUIa*&)j1eSAj`_8j=)8dW$hpy^xIjMDuHp+3*tCv zW!a^=xyC?++cPU^g@9)z<=aA5L%{MP;6`wkf@oz^2ek+lz0R_`{bAU_#MW2|Oq~W#vIF#qPD z-s|*z@2%xD!SPAk?L7alkKTFbA6D3|$cE%<(SP=bsq3`Q124;9;7qPTnz`-%8toj6 zB5T^7$p)7ETS#2VGHv$q2y7@XP&+|1e%ANZ19&=4&w>Zljxq?&EJPUQ+;iVjI64tD zb(THO3$@Hvq!$}qWG&Zkd)^m8CryUqH0vCm-*MbmZ%=0FS?UYJb<_MBzh#>vGTD(mTM3d41yKEY6amsw3hvRE0=O7FG0Z${N` z0hp(A;LkaH+ksrj2C~DqQy8_vO)SAV2*=IOQmtis<_h@CX4!(iJ=>@)xU&VkaLTxj z>6>{v2fVkuU^<1A?*botm{+>GFsFk_w+8l-?TM;%Qkxp`u4I--iY*DzzYq4 zp6lpqS1JKt&^ai-<@uN|R}~$e4qdl%+Pk@fD3nm4siW$uJHR!5Ty0D=Qz17kmd0wI08h$al|Pkq{%JUVeObuUeMG*3AoD3 zT)qSowr7@a1xhG`C(glc_o68$H-GqE!w6U1@~Z1~&yoy_zFfSdeD6gvY<0o|4+|k4 z7eWE&-kl&WoXEh_5e<{J--nPW4X?$EVN_TMZ(^tLK`SUcod89J!^HJ`6xDH^;VHHl zU#$%j3cNK6rQMpwzy#+>_Mj773`5MAKRO@d!H0t-O)5S~hTxQh2-z2zQ${je>xJ5! z?U|L}P!dn5od*x1i$R~lpr;*1<8PzM)_&@T3QcP~-B@SN)mBf(>4AUfdYy-D=c_2p z(wp5b3Kl`<@D++yH4x%aH1`tEAEA( zd#*cgl10!th;mwizKQtRIDIqzN^0-|apiegpps2ZLU77Mgc5G`iXaWH=8>Z7hPB@+ zWb@*csj(6~@%RUR|IIkcNrGkJj_d2sV=lq6Ke4xE-)U2cK?NPg$-d*w(`mBKfo!hp zt5XR0Q{OeC%O>cYnl{%|!i(O7Z3+{d@(|%!Mj^7Pg9Nx5Mo+ErTX1{kp4-9B3ngSH zIE9(na-2fPf=afoKvj5RF~(uLn;W@vwvbJeE!LO9Uz9Ip`uo6fly8T_vc^M`dUUqS?$77?28+Lpvb-lPG2Bsu9B_U$FXzE~n-MnU^ zmP#s`SH8Lrb8EHjnVxfF;i%FOxPCk9_lyWvh$n_8`>vlG=|G>jPKTxlytUj1chqsy zWUyNMv6rXYA9P%Ie13SIq^=jtvoU0ygW5Ut>v<05Suo)u6ea5%Jkdvk1dBj0oAxRh z_QGMm?ZG>}S_7G@JTG_)d=ie-rl(oI6Drb;qRFGBT{*L`Oj|0?3o%h9|CTQt(@8t&ZHAll`>ubHes zE1F7Myrq@!f}yB?5YjQu#_B%##f32~CBdl#A~cO>T&#R@X-RNUJJd0P(IQT#w2a)pOuvh2Y1$1}lV-}92Ds(K*gXLD8v$!i}5uGznjMeU!;YF{J z_8Us$rIf#(X2I}v88!aDxFkpkITlQRYcf3b&6_%EduGY1;nFPJ?t$HBc?g0ac@(Ob*m=$J*6epR?w zcNXVm@6a~OjR%)4q>l7Jtg2$ckspqphX)7YNH;jED!=)12u_6%p$RZ`u=jJeE$q6p z_gA|EM=@PDsBQ(<&AdwCLTo$U!wMN>#M6gp7qJL z%O%&r3)T_syWPS$zRiM~;M4&T%FLNMxPxnDeBin<`4bE)x2sIXGI*A$*XETGsDl?c zb{x4A4mY|1AX zmTFg3iI>H*s(NiXG6Dwjf;m35yX}0Ow*8}J&&J_`D77>TTl;;t_2d*swfAK-a~6&bdgjn;aUCi4p4@f) z73R@u)j4Pa%GXVuTN}j$YK>pvocn@>>_RdF`}Quterp>I;mIZOBqg!WM`VXbq;Dl6^ocUYI|n2Yy1|6ViQxE*|#?l$!cXblNX*c zq}({%tG?8}QRb~9}^xfWx2;jY-@{(T;_{;}uGo=GbMixJs@>%SR?{9cB#n&e!1 zY%@AXDIA@P%C~3g?b?yBj^~avc_W%>EHCAE#bSVV$B)V^hi*papr4>3UI^=J{1$Qb zY(zI(i;#eHE%n+;Wdw}nW${CY<~1<4N@rd&;Xc7>03v1TK*^vwT(~0$W}_BC05C3+ z%%*7=0h4(tf9McO=(pP|AKyxFnt=$l@Uq)8t9k^0XH`Ynaw={n@*?nJb&ddz`BAoS zo5_*oMc~Ei9045jqio+clOxNEz>C#60yySJ*}iQiN0t|X7prpwaLkXgecMcqEH45t zR_6%dm>*^PwwWARUIbpO&Jn;dKg#xPGdZ%n2)tOGBYlxZ=1=HKp+a^P_CvHj^XEi@*!O!O`#aK@=WdeTO1A z4js3Hid@I(`<@`u3Q>;hqhwsugBDjPU{kZ8$(t(rR?BU95$Gj2wL;W6Jcp*)bDYnE zj*{eOr^9DQf%;iVpyyVs$|{kn)a+_^DnaE^4xb-q3g?)KxzcW*7W7Y>mH!UUbG#K?l9qy?0W zjUs)G8u> zo6;VHV|+&E^(g#enB04K*m6HO2|i#H?3v@^t1rdx`w>ooewD^cpJSr;{qXL!Plie(y@-&ES(FWPw?8}$TFl<+g#4-(6xzLTwC}iTcvV;|a^aLS zv>F!IS$Jb{u{tHvrUY!?Hj^pKi@;0WItMyo_83E)r|LNE$+wcH7xa?SCoM0SerIqJ zp_E3NWx7s4xZl3Y3q7MghsrbUr-v?1v(G8kb^UMp?X%%UCphk2+eOHL`>N_m{!O@S z-!_va%ZtFvT67M-CwS+2o>$i=&>>2nz@AZG&%sx9Jojomh34Sn?5a_)n)s=AswS0v zUa@zAm>)l-X{3f@7+!U~cU7?)5wLyROqwh&0xxyz9O#XG$5G=QB?(QPU;6G*c>b$F zq)Zwl(Dg~X7tt4l^sduZc1X_s;<_F6X~MhC#6NQs4uxX(I(_(*E{0(^&OGPJWepwm z3%~WafBGmo?YUQOB_*(#0o%7NFJ>YjNL9DaLDldf(+<(a;J1<|u9z&t0v=3V&C@6T zQH*IOZ!$a8VR~fIhgU4N?H^&a;Ze_f_kN#6$;Ad?%r%Pmlp#uh%NkJhrd}pw^qi}) z8w)q~uhltbQe$}$cp*5oLWHplhEcELw9!IO5830 zSW_Dp2+;OJ ztlYySca|liG=rl?`H%(igeZ85%BU=%y3;#p)aZ9P^`W-!_vY%ZtE^)j0w<=11ASZ6-&S7l9Y6 za|CeAkFtH+OpYus0xwGEAYd2c_+|t?5`n=N&renvd2Yt+5vk!Q#o0dC`8A08y=a6peAL)2CyB8?fkqv&5itcd z0@D*;FZH@$e1^k>U-SUfaTsLj7ztkE)V2N)M^3*CZ$4*6f`IT7-+METX}IF6XVYD} z7d*gCKi694;sVDdX`kvC$6=PCfb2z@?RCSw>6bx3`aG7Oj?=x)A)3&n53nX)h`-K` z;)MrNDayR*5TFo~dBiD>@DY~h!w4q^>yMaDeaY|yoMb)z96s_8fE{nPA=EiIM{6*O z#_`#ClH#=F$G&$Gh8M#~PY=DrU7slJsNsR6Z-18&@&I?gr}ty4q*A>z&UBt4`(FtIE_zEsCKABbXtiv z5`W!qe;JRUB1kUv44)SejU)F}$}juvug(T2kSTct6P}A-#p7{&0=2^j%5$7i9DH>) ze4UPGS*DOYsgmz3o)1|MW;dnQ#|!I#*^jgA`fV>uhpJX84Rm95GAF@QKbdkKal{je ze;@hy*b3)s9(>@w`s!F!QAvQ{)D2Ogs7g`jol{RqaP$Ebpbm~=uQT~lFkWzB(7{U+ zS@3}1bp+{qmx5_-w$=D`4s5K6)K&B&kd*9n9mo?tuJ4kzkYtEi(zuOR^nb} z8II6L73yWGL!r8;I(YV*B>SJ}MjPbic*31jBZT8UF?nbt@S0Y35&02hq#U-o_K zeMNz6~Be>vuU;C4IV9#{u|`)9HHd zC<^*RyrA2j>qJ2(Nyiu|t6o7i@pBaU{3fG1bCP{Pi8sq~PA}zt>dmP(TsJRDS~Z?R zjq38Q?K&hY#H5h8G)sA(nx7`(tQS;Oy>b9@9!Kl(=RjsEVP%kD)y@50qU z)9~xQPnW(*$+rWa1^xZY{-gRpAPSI48I6HzxWdR_3bKj_2d`2els z;L+1`P9Y|*vQ(W?t`o;F@ucfRVXN0zGE8uqgh&@ysSyakOK&4pH14aLr{k0#F~`S$ zzs(Z3)>SO~5`NOQp+@qq!DlSW!Fi?}lu>c1Q&PW+1Df}RGibWZMupMdTII>T6x19L z9QA23K-B~ghR6SoBN&Q&eZ0(4I)dO{JB*>#y{WeU&*>oSYRZ7m0_4Zz|9lieEg%fO zKm=a|_^HfPR0QfK{^1Z`Z(Kxu1W$2QV z3r^$Xleq2oRl_kq(h1N%U3Bl<)Hb4m96^|_>u~5gOfrBCE?!+k z-TnX{E`*;A6ku%?2|`BD9Y(_s{64(UgJg1IHo<2%a2-!oK?=as3;^ z@Pk398eQnkI22e`c^jCzs+*VDJ_!@WKL|fR$D`5lG@T>#{6gYT^7%N$NEu^+M~}OX zd%tr1OmLcqNP))pjO=Ci6J0ki zg$+~-*bH||5}dU_MBLN>N*Nx!|KAtc%acCB^pf3i+}szk3Sr;1n+*`hmx6cw>QpNn z4AD7Y9E$PtLGtn>Fo*pHcqwcwM@ClX6oR8}DxIU7aInm=NDt#67~u5GfJ8OCQh9Bl zfxb=uEgdzO+Thw_eQdQ93vdv9((S()M@!|}xWol*AjyOOwD_ozo=RmDgqacIA*(Qs5eSfmX+~`DqU; zz$aU74ZN(*F_4tSMOtIuUR=l>Ou1fO;IeRCA8VP+R6ADZZ1fYc-oCxj(A6sZdU@fz w3>MftJ?t2$cC5~+weQtk_RNZrTsAF#P>lk~aic7h*^%RD2uiDs zNW1N2`?9*22&2IE!+WMiV1gmJ1|!3$=lj0zz4v|ZZh!2LqCf7B z_xb$zKF{}g-sip8q%$_@jI41jzs54gvoh#6TE5$HAdty_D1(Yv#dXlmDbF$9T?UGF zu;>t|V~)auxr#RJiv8cCYRG+==d?m8<$T(fvyOCl!AHnwDsrXdc1W}DcF0T+wvbyi z*=>q@yx`>R9Z;DbCQF5%sR3`gT&B4Hb=~(!vhP*?p%3aw6G=s~>S2J8hE#;y6u!R^ z_N9ZTc=lVm@EM!%-)cKGp;#+<<4K1;T>4WqEI;M+N>A#{pj(UdZ%VNBh~ph8qRkAx zBnDJb{gF~z4Z8cxpyWr~7eGC!Ri^OBw?O-aZ?K(Iply$qIUqyb66TV4UKbvB$^~E+C37*tmOovLo#9c33+C@R>xNGC6J00qYqq(VQ^SAbM?um0B zNagm$GUKQ>9lA1(rn&Idljb?RdNmZQeX%9={XY-eT=;P>6l-@~ixUgi6S3pV1tJa` z#9F3a_%&M%&b8}v!cX;(U~w)k7^{K;?tc^9WIs!)6NYLlQ~isbhN8DpKYWT%eGPQ| zZmuqVqXvrDU)M?c6Mfb6Hb=Td;O55eZ5ql=r9S+lVB{-nkL5c83e6S zCdRnQ5beRu4loZDqe$pk6E)itVEl#)LY5vQnIJWZ1f!-PwMPVw@V`BfjSuI+zzWNQ z;>SdM-l$7DAKN`i?nn5wop6hY>a?p4PppM5W4oK#ssdgXg-jPG6*7PXF)*YJ7~KG` zB&7JzMtI76Z77|7k&X{rAAuvbH1~*j1*g50hf`Is*9P_ouo`PN%c9R7Pb%P5!K&lL z%Ey|m&~LK{3a|kWZ<8%3pEeP1L06L;$BEV??-oG|;vd^Vwb?d^(w`8eTbZme%rY@ zy-qy)9z2$K$FSsp%)sa&+hfiL@y9#)KG8VO;<`_yx8y1h{0s_y^eMb+^>!AsMkPuo z-hBp`m01Y)eGbbOIi%kX!dGz1iuH(_cH*9IU{Q+Ecsud8bGBI1qs)oH3sNkMmo7?H zVNU->+}QFX%v)ArF&b|C?s9TW;e%eLVD+>F^oRnT`0;G~j61on|CHM{8t^#u|DCi~ zJMoH>U0R_}=`c2Dv5QvuQSmZm<3uhSw_-=J>OP6mX}ml`rF0u_7qCQULU?l(lbfes zPPdocw5&qHUg75h%#8~rEOG60lO+T^=%<$L@Yw)rt%Bc|OD;WJZ*6TQlSe=}a4G@C2~mM)qlPB&BnX}}Wa zM}{k1ZuA9hBf$`t;5O*nc9En?++1STWHV8)`-t6KAYuq3HAKwn^W6Ks&_DdoWKG)K z^ZT9iJLjHz?t2YQSwd45|KrIf_*_b1-?37USt`l=1d&N|E_u!BmM#k~U>%YA3&tN< zYXVEYf&pIn16}7hCT)UUvc0j>%ol-9b&=MsEJ(~}mHfTiIL!_7yNV&je64JQ0;%#B z@=bDum`_!R`Cdfith8CDAUa$6MJ(2&vZXzNjb`$ywMZHrRI>#-bETT$^-3|LgWH(G z^SXlM4Q*0Vo|T$8ikFtSfH$OO^@g5cF>S0c#UnngdgN(@b){gAhNc^6<0W0~VU1qP zX_O!bgkq>;m4@dVVcyU~8oHt(k4^0~7s|2>a}B=bLGdEnT^oR#2W|+s zU6@??EtR-u+f-g0*@3df(Lyu;O=$+NQ_@?%j$>x zUq|E6K$9s8aQFs09E;JgwDGTJm09zKE<(mh*giXYCl~Tqdn_qFyb=&G35qQJo>bpFu8~+@M1A zT9cvUVx*h?u?G=NqMq&H83c_fz+$5v+2JHI#51kPr8cgHIn=2RF*hO%r-KI#)e7d( z$S*(0*tm>9nrkb>Buaf-O%(HG=$!EoppN&o1ZmwC8vX!1%_o!EPO3N!e5kF` zK8DqQz2-pFpvQpO%XihQV zRIT*epH`TH=*!0ft+=IN9#*G?etsL|B<-yZ&HI1elu7Vt7%M%>c0WvSTJZNt@Dlip zHm2aKtll9JhAfp{OUDG`grSmq-n*lqu0ajE6-8*0h43C6Cql>jyppjA~(j)TrR&T~?^O+DmSE;Z) zT!VrJXM1>A^wa8pm}_daSf223ITYdFjc1Mi!pM&C3h7)EMp#rX@4vJ_unj~xv!g%{5O>a@F)NP diff --git a/examples60/gui/graphs/graphs.l b/examples60/gui/graphs/graphs.l new file mode 100644 index 0000000000..373d581c65 --- /dev/null +++ b/examples60/gui/graphs/graphs.l @@ -0,0 +1,97 @@ +//import system'math; +import forms; +import system'drawing; +import extensions; + +const int ScaleX = 15; +const int ScaleY = 15; +const real starting = 0.0r; +const real H = 0.005r; +const real A = 5.0r; +const real C = 2.0r / 3.0r; + +symbol real ending = Pi_value * 6; + +// --- function --- + +function(t) +{ + ^ new Point( + (A * (C * t.cos() + (C*t).cos()) * ScaleX).RoundedInt, + (A * (C * t.sin() - (C*t).sin()) * ScaleY).RoundedInt) +} + +singleton Plotter +{ + drawAxis(Dimension size, Canvas canvas) + { + var zeroX := size.Width / 2; + var zeroY := size.Height / 2 - 10; + + // X axis + canvas.setCaret(0, zeroY); + canvas.lineCaretTo(size.Width, zeroY); + + canvas.writeText("X", size.Width - 20, zeroY + 2); + + // Y axis + canvas.setCaret(zeroX, 0); + canvas.lineCaretTo(zeroX, size.Height); + + canvas.writeText("Y", zeroX + 2, 2); + + for(int i := -10; i <= 10; i += 2) + { + if(i != 0) + { + canvas.writeText(i.toString(), zeroX + (i * ScaleX) - 4, zeroY + 2); + + canvas.writeText(i.toString(), zeroX + 8, zeroY - (i * ScaleY) - 2); + } + else + { + canvas.writeText("0", zeroX + 2, zeroY + 2) + } + } + } + + drawGraph(Dimension size, Canvas canvas) + { + auto t := starting; + auto t2 := ending; + var zero := new Point(size.Width / 2, size.Height / 2 - 10); + + canvas.setCaret(zero + function(t)); + while (t <= t2) + { + canvas.lineCaretTo(zero + function(t)); + + t := t + H + } + } +} + +public class MainWindow : SDIDialog +{ + Imagebox _imagebox; + + constructor new() + <= super new() + { + _imagebox := Imagebox.new(); + self.appendControl(_imagebox); + + self.Caption := "Graph sample"; + self.setRegion(50, 50, 400, 420); + + _imagebox.setRegion(0, 0, 400, 420); + _imagebox.onPaint := (object sender, Canvas canvas) + { + canvas.set(WhitePen); + canvas.set(BlackBrush); + + Plotter.drawAxis(_imagebox.Region.Dimension, canvas); + Plotter.drawGraph(_imagebox.Region.Dimension, canvas) + } + } +} \ No newline at end of file diff --git a/examples60/gui/graphs/graphs.prj b/examples60/gui/graphs/graphs.prj new file mode 100644 index 0000000000..f85d88e33b --- /dev/null +++ b/examples60/gui/graphs/graphs.prj @@ -0,0 +1,17 @@ + + + + graphs.exe + + + + graphs + + + + + graphs.l + + + + diff --git a/examples60/gui/helloworld/helloworld.l b/examples60/gui/helloworld/helloworld.l new file mode 100644 index 0000000000..56e590c40b --- /dev/null +++ b/examples60/gui/helloworld/helloworld.l @@ -0,0 +1,18 @@ +import xforms; + +public class MainWindow +{ + Form; + + constructor new() + { + Form := (forward loader)(self) + } + +/* onExit(arg) + { + forward program.stop() + }*/ + + dispatch() => Form; +} \ No newline at end of file diff --git a/examples60/gui/helloworld/helloworld.xs b/examples60/gui/helloworld/helloworld.xs new file mode 100644 index 0000000000..5ac9482cbf --- /dev/null +++ b/examples60/gui/helloworld/helloworld.xs @@ -0,0 +1,4 @@ +
+ +
\ No newline at end of file diff --git a/examples60/gui/helloworld/xforms_hellowindow.prj b/examples60/gui/helloworld/xforms_hellowindow.prj new file mode 100644 index 0000000000..e54a6c1dca --- /dev/null +++ b/examples60/gui/helloworld/xforms_hellowindow.prj @@ -0,0 +1,29 @@ + + + helloworld_static.exe + + helloworld + + + + + + + + + + + + helloworld.xs + + + + helloworld'stat'loader + + + + + helloworld.l + + + \ No newline at end of file diff --git a/install/aarch64/control b/install/aarch64/control index 121e4bc075..8d30593630 100644 --- a/install/aarch64/control +++ b/install/aarch64/control @@ -1,5 +1,5 @@ Package: elena-lang -Version: 6.0.7 +Version: 6.0.8 Architecture: aarch64 Maintainer: Alex Rakov Depends: libc6 (>= 2.1) diff --git a/install/amd64/control b/install/amd64/control index de2b388a64..cda42cb504 100644 --- a/install/amd64/control +++ b/install/amd64/control @@ -1,5 +1,5 @@ Package: elena-lang -Version: 6.0.7 +Version: 6.0.8 Architecture: amd64 Maintainer: Alex Rakov Depends: libc6 (>= 2.1) diff --git a/install/build_package_x64.bat b/install/build_package_x64.bat index cdad9a7dd7..41e0f720b2 100644 --- a/install/build_package_x64.bat +++ b/install/build_package_x64.bat @@ -81,10 +81,22 @@ md %~dp0\output64\src60\extensions xcopy %~dp0\..\src60\extensions\*.l %~dp0\output64\src60\extensions /s xcopy %~dp0\..\src60\extensions\*.prj %~dp0\output64\src60\extensions /s +md %~dp0\output64\src60\algorithms +xcopy %~dp0\..\src60\algorithms\*.l %~dp0\output64\src60\algorithms /s +xcopy %~dp0\..\src60\algorithms\*.prj %~dp0\output64\src60\algorithms /s + md %~dp0\output64\src60\cellular xcopy %~dp0\..\src60\cellular\*.l %~dp0\output64\src60\cellular /s xcopy %~dp0\..\src60\cellular\*.prj %~dp0\output64\src60\cellular /s +md %~dp0\output64\src60\sqlite +xcopy %~dp0\..\src60\sqlite\*.l %~dp0\output64\src60\sqlite /s +xcopy %~dp0\..\src60\sqlite\*.prj %~dp0\output64\src60\sqlite /s + +md %~dp0\output64\src60\forms +xcopy %~dp0\..\src60\forms\*.l %~dp0\output64\src60\forms /s +xcopy %~dp0\..\src60\forms\*.prj %~dp0\output64\src60\forms /s + %~dp0\..\bin\sg64-cli.exe %~dp0\..\dat\sg\syntax60.txt @echo off if %ERRORLEVEL% EQU -2 GOTO CompilerError @@ -125,6 +137,21 @@ if %ERRORLEVEL% EQU -2 GOTO CompilerError if %ERRORLEVEL% EQU -2 GOTO CompilerError @echo on +%~dp0\output64\bin\elena64-cli %~dp0\output64\src60\algorithms\algorithms.prj +@echo off +if %ERRORLEVEL% EQU -2 GOTO CompilerError +@echo on + +%~dp0\output64\bin\elena64-cli %~dp0\output64\src60\sqlite\sqlite.prj +@echo off +if %ERRORLEVEL% EQU -2 GOTO CompilerError +@echo on + +%~dp0\output64\bin\elena64-cli %~dp0\output64\src60\forms\forms.prj +@echo off +if %ERRORLEVEL% EQU -2 GOTO CompilerError +@echo on + %~dp0\..\bin\asm64-cli -amd64 %~dp0\..\asm\amd64\core60.asm bin\amd64 @echo off if %ERRORLEVEL% EQU -2 GOTO CompilerError diff --git a/install/build_package_x86.bat b/install/build_package_x86.bat index cf511cf2ad..a3832b05da 100644 --- a/install/build_package_x86.bat +++ b/install/build_package_x86.bat @@ -19,7 +19,15 @@ md %~dp0\output32\examples60\console\datetime md %~dp0\output32\examples60\console\goods md %~dp0\output32\examples60\console\replace md %~dp0\output32\examples60\console\pi +md %~dp0\output32\examples60\console\matrix +md %~dp0\output32\examples60\console\random +md %~dp0\output32\examples60\files +md %~dp0\output32\examples60\files\textdb +md %~dp0\output32\examples60\files\textfile md %~dp0\output32\examples60\scripts\calc +md %~dp0\output32\examples60\scripts\interpreter +md %~dp0\output32\examples60\scripts\js +md %~dp0\output32\examples60\scripts\ls md %~dp0\output32\examples60\rosetta\accumulator md %~dp0\output32\examples60\rosetta\ackermann md %~dp0\output32\examples60\rosetta\addfield @@ -52,6 +60,20 @@ md %~dp0\output32\examples60\rosetta\reverse_words_in_string md %~dp0\output32\examples60\rosetta\smavg md %~dp0\output32\examples60\rosetta\string_append +md %~dp0\output32\examples60\gui\c_a_g +md %~dp0\output32\examples60\gui\c_a_g\formulas +md %~dp0\output32\examples60\gui\c_a_g\formulas\Circulo +md %~dp0\output32\examples60\gui\c_a_g\formulas\Paralelogramos +md %~dp0\output32\examples60\gui\c_a_g\formulas\Trapezio +md %~dp0\output32\examples60\gui\c_a_g\formulas\Triangulos + +md %~dp0\output32\examples60\gui\agenda +md %~dp0\output32\examples60\gui\graphs +md %~dp0\output32\examples60\gui\helloworld + +md %~dp0\output32\examples60\db +md %~dp0\output32\examples60\db\sqlite + copy %~dp0\..\bin\asm-cli.exe %~dp0\output32\bin copy %~dp0\..\bin\elena-cli.exe %~dp0\output32\bin copy %~dp0\..\bin\elena-ide.exe %~dp0\output32\bin @@ -60,6 +82,7 @@ copy %~dp0\..\bin\og-cli.exe %~dp0\output32\bin copy %~dp0\..\bin\ecv-cli.exe %~dp0\output32\bin copy %~dp0\..\bin\elt-cli.exe %~dp0\output32\bin copy %~dp0\..\bin\elenart60.dll %~dp0\output32\bin +copy %~dp0\..\bin\elenasm60.dll %~dp0\output32\bin copy %~dp0\..\bin\elenavm60.dll %~dp0\output32\bin copy %~dp0\..\bin\winstub.ex_ %~dp0\output32\bin copy %~dp0\..\bin\elc60.cfg %~dp0\output32\bin @@ -70,6 +93,8 @@ copy %~dp0\..\bin\command60.es %~dp0\output32\bin copy %~dp0\..\bin\x32\core60.bin %~dp0\output32\bin\x32\ copy %~dp0\..\bin\x32\core60_win.bin %~dp0\output32\bin\x32\ +copy %~dp0\..\bin\x32\core60_win.bin %~dp0\output32\bin\x32\ +copy %~dp0\..\bin\x32\core60_win_client.bin %~dp0\output32\bin\x32\ copy %~dp0\..\bin\x32\corex60.bin %~dp0\output32\bin\x32\ copy %~dp0\..\bin\templates\*.cfg %~dp0\output32\bin\templates\ @@ -78,6 +103,7 @@ copy %~dp0\..\bin\scripts\*.es %~dp0\output32\bin\scripts\ copy %~dp0\..\doc\license %~dp0\output32\doc\ copy %~dp0\..\doc\contributors %~dp0\output32\doc\ copy %~dp0\..\readme.md %~dp0\output32\ +copy %~dp0\..\CHANGELOG.md %~dp0\output32\ md %~dp0\output32\src60\system xcopy %~dp0\..\src60\system\*.l %~dp0\output32\src60\system /s @@ -87,10 +113,26 @@ md %~dp0\output32\src60\extensions xcopy %~dp0\..\src60\extensions\*.l %~dp0\output32\src60\extensions /s xcopy %~dp0\..\src60\extensions\*.prj %~dp0\output32\src60\extensions /s +md %~dp0\output32\src60\algorithms +xcopy %~dp0\..\src60\algorithms\*.l %~dp0\output32\src60\algorithms /s +xcopy %~dp0\..\src60\algorithms\*.prj %~dp0\output32\src60\algorithms /s + md %~dp0\output32\src60\cellular xcopy %~dp0\..\src60\cellular\*.l %~dp0\output32\src60\cellular /s xcopy %~dp0\..\src60\cellular\*.prj %~dp0\output32\src60\cellular /s +md %~dp0\output32\src60\sqlite +xcopy %~dp0\..\src60\sqlite\*.l %~dp0\output32\src60\sqlite /s +xcopy %~dp0\..\src60\sqlite\*.prj %~dp0\output32\src60\sqlite /s + +md %~dp0\output32\src60\forms +xcopy %~dp0\..\src60\forms\*.l %~dp0\output32\src60\forms /s +xcopy %~dp0\..\src60\forms\*.prj %~dp0\output32\src60\forms /s + +md %~dp0\output32\src60\xforms +xcopy %~dp0\..\src60\xforms\*.l %~dp0\output32\src60\xforms /s +xcopy %~dp0\..\src60\xforms\*.prj %~dp0\output32\src60\xforms /s + %~dp0\..\bin\sg-cli.exe %~dp0\..\dat\sg\syntax60.txt @echo off if %ERRORLEVEL% EQU -2 GOTO CompilerError @@ -131,6 +173,26 @@ if %ERRORLEVEL% EQU -2 GOTO CompilerError if %ERRORLEVEL% EQU -2 GOTO CompilerError @echo on +%~dp0\output32\bin\elena-cli %~dp0\output32\src60\algorithms\algorithms.prj +@echo off +if %ERRORLEVEL% EQU -2 GOTO CompilerError +@echo on + +%~dp0\output32\bin\elena-cli %~dp0\output32\src60\sqlite\sqlite.prj +@echo off +if %ERRORLEVEL% EQU -2 GOTO CompilerError +@echo on + +%~dp0\output32\bin\elena-cli %~dp0\output32\src60\forms\forms.prj +@echo off +if %ERRORLEVEL% EQU -2 GOTO CompilerError +@echo on + +%~dp0\output32\bin\elena-cli %~dp0\output32\src60\xforms\xforms.prj +@echo off +if %ERRORLEVEL% EQU -2 GOTO CompilerError +@echo on + %~dp0\..\bin\asm-cli -x86 %~dp0\..\asm\x32\core60.asm bin\x32 @echo off if %ERRORLEVEL% EQU -2 GOTO CompilerError @@ -156,11 +218,27 @@ copy %~dp0\..\examples60\console\goods\*.l %~dp0\output32\examples60\console\goo copy %~dp0\..\examples60\console\goods\*.txt %~dp0\output32\examples60\console\goods copy %~dp0\..\examples60\console\replace\*.l %~dp0\output32\examples60\console\replace copy %~dp0\..\examples60\console\pi\*.l %~dp0\output32\examples60\console\pi +copy %~dp0\..\examples60\console\matrix\*.l %~dp0\output32\examples60\console\matrix +copy %~dp0\..\examples60\console\matrix\*.prj %~dp0\output32\examples60\console\matrix +copy %~dp0\..\examples60\console\random\*.l %~dp0\output32\examples60\console\random copy %~dp0\..\examples60\scripts\calc\*.l %~dp0\output32\examples60\scripts\calc copy %~dp0\..\examples60\scripts\calc\*.es %~dp0\output32\examples60\scripts\calc copy %~dp0\..\examples60\scripts\calc\*.prj %~dp0\output32\examples60\scripts\calc +copy %~dp0\..\examples60\scripts\interpreter\*.l %~dp0\output32\examples60\scripts\interpreter +copy %~dp0\..\examples60\scripts\interpreter\*.es %~dp0\output32\examples60\scripts\interpreter +copy %~dp0\..\examples60\scripts\interpreter\*.prj %~dp0\output32\examples60\scripts\interpreter +copy %~dp0\..\examples60\scripts\interpreter\*.txt %~dp0\output32\examples60\scripts\interpreter + +copy %~dp0\..\examples60\scripts\js\*.l %~dp0\output32\examples60\scripts\js +copy %~dp0\..\examples60\scripts\js\*.js %~dp0\output32\examples60\scripts\js +copy %~dp0\..\examples60\scripts\js\*.prj %~dp0\output32\examples60\scripts\js + +copy %~dp0\..\examples60\scripts\ls\*.l %~dp0\output32\examples60\scripts\ls +copy %~dp0\..\examples60\scripts\ls\*.ls %~dp0\output32\examples60\scripts\ls +copy %~dp0\..\examples60\scripts\ls\*.prj %~dp0\output32\examples60\scripts\ls + copy %~dp0\..\examples60\rosetta\accumulator\*.l %~dp0\output32\examples60\rosetta\accumulator copy %~dp0\..\examples60\rosetta\ackermann\*.l %~dp0\output32\examples60\rosetta\ackermann copy %~dp0\..\examples60\rosetta\addfield\*.l %~dp0\output32\examples60\rosetta\addfield @@ -195,6 +273,34 @@ copy %~dp0\..\examples60\rosetta\smavg\*.l %~dp0\output32\examples60\rosetta\sma copy %~dp0\..\examples60\rosetta\string_append\*.l %~dp0\output32\examples60\rosetta\string_append copy %~dp0\..\examples60\rosetta\twentyfour\*.l %~dp0\output32\examples60\rosetta\twentyfour +copy %~dp0\..\examples60\gui\c_a_g\*.l %~dp0\output32\examples60\gui\c_a_g +copy %~dp0\..\examples60\gui\c_a_g\*.prj %~dp0\output32\examples60\gui\c_a_g + +copy %~dp0\..\examples60\gui\c_a_g\formulas\Circulo\*.bmp %~dp0\output32\examples60\gui\c_a_g\formulas\Circulo +copy %~dp0\..\examples60\gui\c_a_g\formulas\Paralelogramos\*.bmp %~dp0\output32\examples60\gui\c_a_g\formulas\Paralelogramos +copy %~dp0\..\examples60\gui\c_a_g\formulas\Trapezio\*.bmp %~dp0\output32\examples60\gui\c_a_g\formulas\Trapezio +copy %~dp0\..\examples60\gui\c_a_g\formulas\Triangulos\*.bmp %~dp0\output32\examples60\gui\c_a_g\formulas\Triangulos + +copy %~dp0\..\examples60\gui\agenda\*.l %~dp0\output32\examples60\gui\agenda +copy %~dp0\..\examples60\gui\agenda\*.prj %~dp0\output32\examples60\gui\agenda + +copy %~dp0\..\examples60\gui\graphs\*.l %~dp0\output32\examples60\gui\graphs +copy %~dp0\..\examples60\gui\graphs\*.prj %~dp0\output32\examples60\gui\graphs + +copy %~dp0\..\examples60\gui\helloworld\*.l %~dp0\output32\examples60\gui\helloworld +copy %~dp0\..\examples60\gui\helloworld\*.prj %~dp0\output32\examples60\gui\helloworld +copy %~dp0\..\examples60\gui\helloworld\*.xs %~dp0\output32\examples60\gui\helloworld + +copy %~dp0\..\examples60\db\sqlite\*.l %~dp0\output32\examples60\db\sqlite +copy %~dp0\..\examples60\db\sqlite\*.prj %~dp0\output32\examples60\db\sqlite + +copy %~dp0\..\examples60\files\textdb\*.l %~dp0\output32\examples60\files\textdb +copy %~dp0\..\examples60\files\textdb\*.prj %~dp0\output32\examples60\files\textdb +copy %~dp0\..\examples60\files\textdb\*.txt %~dp0\output32\examples60\files\textdb + +copy %~dp0\..\examples60\files\textfile\*.l %~dp0\output32\examples60\files\textfile +copy %~dp0\..\examples60\files\textfile\*.txt %~dp0\output32\examples60\files\textfile + 7z a %~dp0\output32\%1.zip %~dp0\output32\*.* %~dp0\output32\* -r goto:eof diff --git a/install/elena_inno.iss b/install/elena_inno.iss index cd1e1a966f..29171c46a6 100644 --- a/install/elena_inno.iss +++ b/install/elena_inno.iss @@ -18,7 +18,7 @@ DefaultGroupName=ELENA Programming Language AllowNoIcons=yes LicenseFile=..\doc\license InfoAfterFile=..\CHANGELOG.md -OutputBaseFilename=elena-setup +OutputBaseFilename=elena-lang-6.0.8.x86-setup Compression=lzma SolidCompression=yes ChangesEnvironment=yes @@ -32,26 +32,25 @@ Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{ Name: "quicklaunchicon"; Description: "{cm:CreateQuickLaunchIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked; OnlyBelowVersion: 0,6.1 [Files] -Source: "output\bin\*"; DestDir: "{app}\bin"; Flags: ignoreversion recursesubdirs createallsubdirs -Source: "output\doc\*"; DestDir: "{app}\doc"; Flags: ignoreversion recursesubdirs createallsubdirs -Source: "output\examples\*"; DestDir: "{app}\examples"; Flags: ignoreversion recursesubdirs createallsubdirs -Source: "output\lib50\*"; DestDir: "{app}\lib50"; Flags: ignoreversion recursesubdirs createallsubdirs +Source: "output32\bin\*"; DestDir: "{app}\bin"; Flags: ignoreversion recursesubdirs createallsubdirs +Source: "output32\doc\*"; DestDir: "{app}\doc"; Flags: ignoreversion recursesubdirs createallsubdirs +Source: "output32\examples60\*"; DestDir: "{app}\examples60"; Flags: ignoreversion recursesubdirs createallsubdirs +Source: "output32\lib60\*"; DestDir: "{app}\lib60"; Flags: ignoreversion recursesubdirs createallsubdirs Source: "..\doc\license"; DestDir: "{app}"; Source: "..\readme.md"; DestDir: "{app}"; Flags: isreadme Source: "..\CHANGELOG.md"; DestDir: "{app}"; -Source: "..\rebuild_lib.bat"; DestDir: "{app}"; -Source: "..\rebuild_examples.bat"; DestDir: "{app}"; +Source: "..\rebuild_lib60.bat"; DestDir: "{app}"; Source: "redist\VC_redist.x86.exe"; DestDir: "{app}"; Flags: deleteafterinstall ; NOTE: Don't use "Flags: ignoreversion" on any shared system files [Icons] -Name: "{group}\ELENA Programming Language"; Filename: "{app}\bin\elide.exe" -Name: "{commondesktop}\ELENA Programming Language"; Filename: "{app}\bin\elide.exe"; Tasks: desktopicon -Name: "{userappdata}\Microsoft\Internet Explorer\Quick Launch\ELENA Programming Language"; Filename: "{app}\bin\elide.exe"; Tasks: quicklaunchicon +Name: "{group}\ELENA Programming Language"; Filename: "{app}\bin\elena-ide.exe " +Name: "{commondesktop}\ELENA Programming Language"; Filename: "{app}\bin\elena-ide.exe"; Tasks: desktopicon +Name: "{userappdata}\Microsoft\Internet Explorer\Quick Launch\ELENA Programming Language"; Filename: "{app}\bin\elena-ide.exe"; Tasks: quicklaunchicon [Run] Filename: "{app}\redist\VC_redist.x86.exe"; Parameters: "/install /passive /norestart"; StatusMsg: Installing VC++ 2017 Redistributables...; Check: not VCinstalled -Filename: "{app}\bin\elide.exe"; Description: "{cm:LaunchProgram,ELENA Programming Language}"; Flags: nowait postinstall skipifsilent +Filename: "{app}\bin\elena-ide.exe"; Description: "{cm:LaunchProgram,ELENA Programming Language}"; Flags: nowait postinstall skipifsilent [Registry] Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; ValueType: expandsz; ValueName: "Path"; ValueData: "{olddata};{app}\bin"; Check: NeedsAddPath('{app}\bin') diff --git a/install/i386/control b/install/i386/control index a0d3b668bb..0377ed9c54 100644 --- a/install/i386/control +++ b/install/i386/control @@ -1,5 +1,5 @@ Package: elena-lang -Version: 6.0.7 +Version: 6.0.8 Architecture: i386 Maintainer: Alex Rakov Depends: libc6 (>= 2.1) diff --git a/install/ppc64le/control b/install/ppc64le/control index 51305007be..3ae595a678 100644 --- a/install/ppc64le/control +++ b/install/ppc64le/control @@ -1,5 +1,5 @@ Package: elena-lang -Version: 6.0.7 +Version: 6.0.8 Architecture: ppc64le Maintainer: Alex Rakov Depends: libc6 (>= 2.1) diff --git a/rebuild_lib60.bat b/rebuild_lib60.bat index efde7e8486..731f2a88e8 100644 --- a/rebuild_lib60.bat +++ b/rebuild_lib60.bat @@ -77,11 +77,21 @@ bin\elena-cli src60\algorithms\algorithms.prj if %ERRORLEVEL% EQU -2 GOTO CompilerError @echo on +bin\elena-cli src60\sqlite\sqlite.prj +@echo off +if %ERRORLEVEL% EQU -2 GOTO CompilerError +@echo on + bin\elena-cli src60\forms\forms.prj @echo off if %ERRORLEVEL% EQU -2 GOTO CompilerError @echo on +bin\elena-cli src60\xforms\xforms.prj +@echo off +if %ERRORLEVEL% EQU -2 GOTO CompilerError +@echo on + bin\asm-cli -bc64 src60\core\system.core_routines.esm lib60_64 @echo off if %ERRORLEVEL% EQU -1 GOTO Asm2BinError @@ -107,6 +117,21 @@ bin\elena64-cli src60\cellular\cellular.prj if %ERRORLEVEL% EQU -2 GOTO CompilerError @echo on +bin\elena64-cli src60\algorithms\algorithms.prj +@echo off +if %ERRORLEVEL% EQU -2 GOTO CompilerError +@echo on + +bin\elena64-cli src60\sqlite\sqlite.prj +@echo off +if %ERRORLEVEL% EQU -2 GOTO CompilerError +@echo on + +bin\elena64-cli src60\forms\forms.prj +@echo off +if %ERRORLEVEL% EQU -2 GOTO CompilerError +@echo on + bin\ldoc system doc\api bin\ldoc system'routines doc\api bin\ldoc system'runtime doc\api @@ -117,6 +142,8 @@ bin\ldoc extensions doc\api bin\ldoc extensions'routines doc\api bin\ldoc extensions'scripting doc\api bin\ldoc cellular doc\api +bin\ldoc algorithms doc\api +bin\ldoc sqlite doc\api bin\ldoc forms doc\api bin\elena-cli tests60\system_tests\system_tests.prj diff --git a/src60/core/system.core_routines.esm b/src60/core/system.core_routines.esm index d84ddf7f56..df88c98fe8 100644 --- a/src60/core/system.core_routines.esm +++ b/src60/core/system.core_routines.esm @@ -2602,16 +2602,16 @@ procedure func_invoker(arg) end -procedure thread_start - - system 3 +procedure thread_start(index) open [arg1],[ptr,envptr,ex_struct:ex_struct_size] - xloadarg fp:1 + xloadarg fp:index $save dp:ptr + system 3 + xhook dp:ex_struct, procedure:"system'core_routines'default_exception_handler" mov env @@ -2673,7 +2673,7 @@ symbol mta_start call extern:InitializeMTLA ( *arg1, - procedure:"system'core_routines'startUpSymbols", + symbol:"$auto'startUpSymbol", procedure:"system'core_routines'critical_exception_handler") close [] diff --git a/src60/core/system.win_core_routines.esm b/src60/core/system.win_core_routines.esm index 120460e7ec..35ceafe220 100644 --- a/src60/core/system.win_core_routines.esm +++ b/src60/core/system.win_core_routines.esm @@ -5,6 +5,7 @@ define WM_CREATE 1; define WM_DESTROY 2; define WM_SIZE 5; define WM_PAINT 15; +define WM_CLOSE 16; define WM_COMMAND 273; define GWL_USERDATA -21; @@ -48,9 +49,11 @@ procedure windProc (arg1,arg2,arg3,arg4) jeq labSize cmp n:WM_PAINT jeq labPaint + cmp n:WM_CLOSE + jeq labClose labDefault: - call extern:USER32.DefWindowProcW(*hwnd,*msg,*wparam,*lparam) + call stdcall extern:USER32.DefWindowProcW(*hwnd,*msg,*wparam,*lparam) jump labEnd2 labCreate: @@ -71,12 +74,7 @@ labCreate: jump labEnd labDestroy: - mov n:GWL_USERDATA - save sp:1 - load dp:hwnd - save sp:0 - - call extern:USER32.GetWindowLongW,2 + call stdcall extern:USER32.GetWindowLongW(*hwnd,GWL_USERDATA) cmp n:0 jeq labDefault @@ -94,12 +92,7 @@ labDestroy: jump labEnd labPaint: - mov n:GWL_USERDATA - save sp:1 - load dp:hwnd - save sp:0 - - call extern:USER32.GetWindowLongW,2 + call stdcall extern:USER32.GetWindowLongW(*hwnd,GWL_USERDATA) cmp n:0 jeq labDefault @@ -116,13 +109,26 @@ labPaint: jump labEnd -labCommand: - mov n:GWL_USERDATA - save sp:1 - load dp:hwnd - save sp:0 +labClose: + call stdcall extern:USER32.GetWindowLongW(*hwnd,GWL_USERDATA) + + cmp n:0 + jeq labDefault + save dp:ptr - call extern:USER32.GetWindowLongW,2 + set dp:hwnd + store sp:1 + + set dp:ptr + get i:0 + get i:0 + + vcall mssg:"onWMClose[2]", class:"system'winforms'WindowCallback" + + jump labEnd + +labCommand: + call stdcall extern:USER32.GetWindowLongW(*hwnd,GWL_USERDATA) cmp n:0 jeq labDefault @@ -143,12 +149,7 @@ labCommand: jump labEnd labSize: - mov n:GWL_USERDATA - save sp:1 - load dp:hwnd - save sp:0 - - call extern:USER32.GetWindowLongW,2 + call stdcall extern:USER32.GetWindowLongW(*hwnd,GWL_USERDATA) cmp n:0 jeq labDefault diff --git a/src60/extensions/console.l b/src60/extensions/console.l index 08a30ca557..f964792e13 100644 --- a/src60/extensions/console.l +++ b/src60/extensions/console.l @@ -198,3 +198,38 @@ public extension inputOp ^ self } } + +public extension outputCharFormatterOp +{ + printPaddingRightChar(int width, char ch, params object[] list) + { + auto buffer := new TextBuilder(); + + int len := list.Length; + + for(int i := 0; i < len; i += 1) + { + object obj := list[i]; + + buffer.write(obj.toString()) + }; + + self.writePaddingRight(buffer.Value, ch, width) + } + + printPaddingLeftChar(int width, char ch, params object[] list) + { + auto buffer := new TextBuilder(); + + int len := list.Length; + + for(int i := 0; i < len; i += 1) + { + object obj := list[i]; + + buffer.write(obj.toString()) + }; + + self.writePaddingLeft(buffer.Value, ch, width) + } +} diff --git a/src60/extensions/convertors.l b/src60/extensions/convertors.l index ade5e54b9e..883f6e0795 100644 --- a/src60/extensions/convertors.l +++ b/src60/extensions/convertors.l @@ -300,7 +300,7 @@ public singleton intConvertExt { generic(n) { - /*MessageName*/var mssg := __received.MessageName; + MessageName mssg := __received.MessageName; ^ mssg(new ExtensionVariable(n, extensions'intConvertOp)) } diff --git a/src60/extensions/extensions.prj b/src60/extensions/extensions.prj index bfb8b9aa77..aa729bba6e 100644 --- a/src60/extensions/extensions.prj +++ b/src60/extensions/extensions.prj @@ -47,5 +47,8 @@ dynamic\json.l dynamic\derserializer.l + + threading\threading.l + \ No newline at end of file diff --git a/src60/extensions/scripting/interpreter.l b/src60/extensions/scripting/interpreter.l index ac3e0b65ee..3cf19d7ee3 100644 --- a/src60/extensions/scripting/interpreter.l +++ b/src60/extensions/scripting/interpreter.l @@ -69,7 +69,7 @@ public sealed class ScriptEngine private buildTape(pointer tape) { var retVal := nil; - byte temp[1024]; + byte temp[1024]; int len := extern elenasm.GetLengthSMLA(tape); if (len <= 1024) { diff --git a/src60/extensions/threading/threading.l b/src60/extensions/threading/threading.l new file mode 100644 index 0000000000..7f0a9bb572 --- /dev/null +++ b/src60/extensions/threading/threading.l @@ -0,0 +1,20 @@ +import system'threading; + +// --- threadControl --- + +public singleton threadControl +{ + start(Func f) + { + var t := Thread.assign(f); + + t.start(); + + ^ t + } + + sleep (int n) + { + @system'threading'threadControl.sleep(n) + } +} diff --git a/src60/forms/controls.l b/src60/forms/controls.l index 200d534868..26c97578da 100644 --- a/src60/forms/controls.l +++ b/src60/forms/controls.l @@ -95,11 +95,44 @@ public abstract class BaseControl } } + int X + { + get() + { + int retVal := _region.X; + + ^ retVal + } + + set(int n) + { + _region.X := n + } + } + + int Y + { + get() + { + int retVal := _region.Y; + + ^ retVal + } + + set(int n) + { + _region.Y := n + } + } + setRegion(int x, int y, int width, int height) { _region.set(x, y, width, height); } + Region Region + = _region; + protected constructor new() { _visible := true; diff --git a/src60/forms/forms.prj b/src60/forms/forms.prj index 96b81861b7..e0c95b8a50 100644 --- a/src60/forms/forms.prj +++ b/src60/forms/forms.prj @@ -1,29 +1,31 @@ - - - ..\..\lib60 - - - - - ..\..\lib60_64 - - - - forms - - - - ELENA GUI Library - 6.0.0 - Aleksey Rakov - - - - controls.l - win32_controls.l - win_forms.l - win_dialogs.l - - + + + ..\..\lib60 + + + + + ..\..\lib60_64 + + + + + + forms + + + + ELENA GUI Library + 6.0.0 + Aleksey Rakov + + + + controls.l + win32_controls.l + win_forms.l + win_dialogs.l + + \ No newline at end of file diff --git a/src60/forms/win32_controls.l b/src60/forms/win32_controls.l index c21c2a2155..bb84a93c2c 100644 --- a/src60/forms/win32_controls.l +++ b/src60/forms/win32_controls.l @@ -15,6 +15,8 @@ public interface IControl abstract open(); + abstract close(); + abstract click(); } @@ -49,6 +51,10 @@ public abstract class BaseWinControl : BaseControl self.onCreate() } + close() + { + } + set Caption(string s) { _caption := s; @@ -184,6 +190,7 @@ public abstract class BaseWinControl : BaseControl public abstract class BaseWinContainer : BaseWinControl { List _controls; + Func1 onResize : event; protected constructor new() <= super new() @@ -208,6 +215,13 @@ public abstract class BaseWinContainer : BaseWinControl ^ nil } + internal resize(WindowHandle hwnd, int width, int height) + { + super.resize(hwnd, width, height); + + onResize?.(self) + } + open() { super.open(); @@ -217,6 +231,16 @@ public abstract class BaseWinContainer : BaseWinControl _controls[i].open() } } + + close() + { + super.close(); + + int len := _controls.Length; + for (int i := 0; i < len; i += 1) { + _controls[i].close() + } + } } // --- Label --- @@ -568,9 +592,9 @@ public closed class Paintbox : BaseWinControl, interface public sealed class Imagebox : Paintbox { - HBITMAP _image; - HDC _imageDC; - bool _needToRefresh; + HBITMAP _image; + HDC _imageDC; + bool _needToRefresh; constructor new() <= super new() @@ -595,13 +619,13 @@ public sealed class Imagebox : Paintbox struct.begin(_handle); - _region.readDimensionTo(ref int width, ref int height); - + int width := _region.Width; + int height := _region.Height; + HDC dc := struct.HDC; dc.copy(0, 0, width, height, _imageDC, 0, 0, SRCCOPY); -// int err := system'external'KERNEL32 GetLastError. - + struct.end(_handle) } @@ -698,25 +722,25 @@ public abstract class BasePanel : BaseWinContainer _controls.append(control) } -// int Width -// { -// set(int v) -// { -// super.Width := v; -// -// theFrame.Width := v -// } -// } -// -// int Height -// { -// set(int h) -// { -// super.Height := h; -// -// theFrame.Height := h -// } -// } + int Width + { + set(int v) + { + super.Width := v; + + _frame.Width := v + } + } + + int Height + { + set(int h) + { + super.Height := h; + + _frame.Height := h + } + } setRegion(int x, int y, int width, int height) { @@ -725,28 +749,28 @@ public abstract class BasePanel : BaseWinContainer _frame.setRegion(0, 0, width, height); } -// string Caption -// { -// set(string caption) -// { -// theFrame.Caption := caption -// } -// -// set(wide caption) -// { -// theFrame.Caption := caption -// } -// } - - set Caption(string s) - { - _frame.Caption := s - } - - set Caption(wide s) + string Caption { - _frame.Caption := s - } + set(string caption) + { + _frame.Caption := caption + } + + set(wide caption) + { + _frame.Caption := caption + } + } +// +// set Caption(string s) +// { +// _frame.Caption := s +// } +// +// set Caption(wide s) +// { +// _frame.Caption := s +// } internal resize(Handle handle, int width, int height) { diff --git a/src60/forms/win_dialogs.l b/src60/forms/win_dialogs.l index 7cec58a5db..8cb6a7702e 100644 --- a/src60/forms/win_dialogs.l +++ b/src60/forms/win_dialogs.l @@ -57,7 +57,7 @@ public sealed class OpenFileDialog : FileDialog bool run() { - var dialog := new system'winforms'OpenFileDialog(_parent, _filters, 0, 255, _title); + var dialog := new system'winforms'OpenFileDialog(_parent, _filters, 1, _title); _selectedPath := dialog.select(); @@ -74,7 +74,7 @@ public sealed class SaveFileDialog : FileDialog bool run() { - var dialog := new system'winforms'SaveFileDialog(_parent, _filters, 0, 255, _title); + var dialog := new system'winforms'SaveFileDialog(_parent, _filters, 1, _title); _selectedPath := dialog.select(); diff --git a/src60/forms/win_forms.l b/src60/forms/win_forms.l index 1a0a21dc8f..0e9a1ded0a 100644 --- a/src60/forms/win_forms.l +++ b/src60/forms/win_forms.l @@ -8,6 +8,8 @@ public abstract class BaseWinForm : BaseWinContainer protected constructor new() <= super new() { + _region.X := CW_USEDEFAULT; + _region.Y := CW_USEDEFAULT; } appendControl(BaseControl control) @@ -17,6 +19,9 @@ public abstract class BaseWinForm : BaseWinContainer _controls.append(control) } + close() + { + } } // --- SDI --- @@ -111,4 +116,95 @@ public class SDIDialog : SDIForm paramPtr); } -} \ No newline at end of file +} + +// --- Child --- + +class ChildWindowListener : ChildWindowCallback +{ + ChildForm _owner; + + constructor(ChildForm owner) + { + _owner := owner + } + + onClick(Handle handle) + { + auto control := _owner.retrieve(handle); + if(nil != control) + { control.click() }; + + super.onClick(handle) + } + + onWMDestoy(Handle hwnd) + { + super.onWMDestoy(hwnd); + + //TODO : free PermVectorTable entry to reuse it + } + + onSize(Handle control, int width, int height) + { + _owner.resize(control, width, height); + } + +// onchange(WindowHandle hwnd, ref int retVal) +// { +// auto control := theOwner.retrieve(handle); +// if(nil != control) +// { control.click() }; +// +// super.onchange(handle, ref retVal) +// } +} + +public closed class ChildForm : BaseWinForm +{ + constructor new(parent) + <= super new() + { + _parent := parent + } + + run() + { + self.open(); + _parent.Enabled := false; + + forward program.run(_handle); + + _parent.Enabled := true + } + + close() + { + self.Visible := false; + + super.close() + } + + internal createHandle() + { + int styles := WS_POPUPWINDOW | WS_DLGFRAME; + if(_visible) + { styles := styles | WS_VISIBLE }; + + _region.read(ref int x, ref int y, ref int width, ref int height); + + pointer paramPtr := PermVectorTable.allocate(new ChildWindowListener(self)); + + _handle := new WindowHandle( + WS_EX_DLGMODALFRAME | WS_EX_CONTROLPARENT, + SDIWindowClass, + cast wide(_caption), + styles, + x, y, width, height, + cast WindowHandle(_parent), + CurrentInstance, + paramPtr); + } + +} + diff --git a/src60/sqlite/common.l b/src60/sqlite/common.l new file mode 100644 index 0000000000..77b79f50c6 --- /dev/null +++ b/src60/sqlite/common.l @@ -0,0 +1,267 @@ +import system'routines; +import system'collections; +import extensions; + +const int SQLITE_OK = 0; +const int SQLITE_ROW = 100; +const int SQLITE_DONE = 101; +const int SQLITE_INTEGER = 1; +const int SQLITE_FLOAT = 2; +const int SQLITE_TEXT = 3; +const int SQLITE_BLOB = 4; +const int SQLITE_NULL = 5; + +// --- DBException --- + +public class DBException : Exception +{ + /// Creates the exception + constructor new() + <= new("The process terminated"); + + /// Creates the exception + constructor new(string message) + <= super new(message); +} + +// --- Connection --- + +public sealed class DBConnection +{ + handle _DBHandle; + string _path; + bool _open; + + constructor new(system'io'File p) + <= new(cast string(p)); + + constructor new(string path) + { + _path := path; + _open := false; + } + + handle cast() = _DBHandle; + + bool isAvailable() = _open; + + open() + { + int retVal := extern sqlite3.sqlite3_open(_path, ref handle h); + if (retVal != SQLITE_OK) { DBException.new("Could not open a database file").raise() } else { _open := true }; + + _DBHandle := h + } + + string last_error_message() + { + pointer ptr := extern sqlite3.sqlite3_errmsg(_DBHandle); + + ^ cast string(ptr) + } + + doSql(query) + <= executeNonQuery(query); + + executeNonQuery(string sqlText) + { + ifnot (_open) { DBException.new("SQLite database is not open.").raise() }; + + using(auto command := DBCommand.new(self, sqlText)) + { + command.eval() + } + } + + executeQuery(string sqlText) + { + ifnot (_open) { DBException.new("SQLite database is not open.").raise() }; + + auto command := DBCommand.new(self, sqlText); + + var table := DBTable.new(command.sql_field_names()); + using(auto reader := DBReader.new(command)) + { + auto en := reader.enumerator(); + while (en.next()) { + table.appendRow(*en) + } + }; + + ^ table + } + + numberOfTable() + { + ifnot (_open) { DBException.new("SQLite database is not open.").raise() }; + + auto command := DBCommand.new(self, "SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%';"); + + var numberOfTable := command.evalScalar(); + + command.close(); + + ^ numberOfTable + } + + tables() + { + ifnot (_open) { DBException.new("SQLite database is not open.").raise() }; + + auto command := DBCommand.new(self, "SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%';"); + + auto nameOfTables := new ArrayList(); + + while (command.evalNext()) + { + nameOfTables.append(command.at(0)) + }; + + command.close(); + + ^ nameOfTables + } + + close() + { + if (_open) + { extern sqlite3.sqlite3_close(_DBHandle) }; + + _open := false + } +} + +// --- Commnad --- + +public sealed class DBCommand +{ + DBConnection _connection; + Handle _commandHandle; + + constructor new(DBConnection connection, string text) + { + _connection := connection; + + ifnot (_connection.isAvailable()) { DBException.new("SQLite database is not open.").raise() }; + + self.prepare(text) + } + + Handle cast() = _commandHandle; + + private prepare(string text) + { + handle cnn := _connection; + int textLen := text.Length; + + int retVal := extern sqlite3.sqlite3_prepare_v2( + cnn, + text, + textLen, + ref handle h, + 0); + if (retVal != SQLITE_OK) { DBException.new(_connection.last_error_message()).raise() }; + + _commandHandle := h + } + + eval() + { + int retPrc := extern sqlite3.sqlite3_step(_commandHandle); + + if (retPrc != SQLITE_DONE) { DBException.new("Could not execute SQL statement.").raise() } + } + + bool evalNext() + { + int retPrc := extern sqlite3.sqlite3_step(_commandHandle); + + ^ (retPrc == SQLITE_ROW) + } + + evalScalar() + { + int retPrc := extern sqlite3.sqlite3_step(_commandHandle); + + if (retPrc != SQLITE_ROW) { ^ nil }; + + ^ self.at(0) + } + + DBReader reader() = DBReader.new(self); + + Enumerator enumerator() = sqlite'DBReader.new(self).enumerator(); + + at(int index) + { + int columnType := extern sqlite3.sqlite3_column_type(_commandHandle, index); + + columnType => + SQLITE_INTEGER + { + int val := extern sqlite3.sqlite3_column_int(_commandHandle, index); + + ^ val + } + SQLITE_TEXT + { + pointer columnTextPtr := extern sqlite3.sqlite3_column_text(_commandHandle, index); + + ^ cast string(columnTextPtr) + } + SQLITE_FLOAT + { + real val := extern sqlite3.sqlite3_column_double(_commandHandle, index); + + ^ val + } + SQLITE_BLOB + { + pointer blob := extern sqlite3.sqlite3_column_blob(_commandHandle, index); + int len := extern sqlite3.sqlite3_column_bytes(_commandHandle, index); + + byte[] arr := new byte[](len); + + blob.copyTo(arr, len); + + ^ arr + } + SQLITE_NULL + { + ^ nil + } + ! + { + DBException.new("Unsupported type").raise() + } + } + + int readFieldCount() + { + int ret := extern sqlite3.sqlite3_column_count(_commandHandle); + + ^ ret + } + + string[] sql_field_names() + { + int field_count := self.readFieldCount(); + + auto names := new string[](field_count); + for(int i := 0; i < field_count; i++) + { + pointer columnNamePtr := extern sqlite3.sqlite3_column_origin_name(_commandHandle, i); + + names[i] := cast string(columnNamePtr) + }; + + ^ names + } + + close() + { + int retVal := extern sqlite3.sqlite3_finalize(_commandHandle); + + if (retVal != SQLITE_OK) { DBException.new("Could not finalize SQL statement.").raise() }; + } +} diff --git a/src60/sqlite/data_table.l b/src60/sqlite/data_table.l new file mode 100644 index 0000000000..9144497d0f --- /dev/null +++ b/src60/sqlite/data_table.l @@ -0,0 +1,59 @@ +import system'routines; +import system'collections; + +// --- DBRow --- + +public sealed class DBRow +{ + object[] _row; + DBTable _table; + + internal constructor newTableRow(object[] row, DBTable table) + { + _row := row; + _table := table + } + + at(int n) + = _row.at(n); + + at(string fieldName) + { + int index := _table.indexOfField(fieldName); + + if (-1 == index) + { DBException.new("Field is unknown").raise() }; + + ^ _row[index] + } +} + +// --- DBTable --- + +public sealed class DBTable +{ + string[] _fieldNames; + List _rows; + + constructor new(string[] names) + { + _fieldNames := names; + _rows := new List() + } + + /*internal*/ appendRow(object[] row) + { + _rows.append(DBRow.newTableRow(row, self)) + } + + internal int indexOfField(string fieldName) + { + ^ _fieldNames.indexOfElement(fieldName) + } + + DBRow[] rows() = _rows.Value; + + string[] fields() = _fieldNames; + + int fieldCount() = _fieldNames.Length; +} \ No newline at end of file diff --git a/src60/sqlite/reader.l b/src60/sqlite/reader.l new file mode 100644 index 0000000000..1fe32375d1 --- /dev/null +++ b/src60/sqlite/reader.l @@ -0,0 +1,80 @@ +import system'routines; + +public sealed class DBEnumerator : Enumerator +{ + DBReader reader; + + constructor(DBReader reader) + { + this reader := reader + } + + get object[] Value() = reader.row(); + + bool next() => reader; + + enumerable() = reader; + + reset() { NotSupportedException.raise() } + + Enumerator cast() = new Enumerator{ embeddable dispatch() => self; }; +} + +public sealed class DBReader : Enumerable +{ + DBCommand _command; + Handle _commandHandle; + string[] _fieldNames; + + constructor new(DBCommand command) + { + _command := command; + + _commandHandle := cast Handle(command); + } + + int readNext() + { + int r := extern sqlite3.sqlite3_step(_commandHandle); + + ^ r + } + + bool next() + { + int result := self.readNext(); + + ^ result == SQLITE_ROW + } + + at(int n) + = _command.at(n); + + at(string fieldName) + { + if (nil == _fieldNames) + { _fieldNames := _command.sql_field_names() }; + + ^ self.at(_fieldNames.indexOfElement(fieldName)) + } + + object[] row() + { + int count := _command.readFieldCount(); + + object[] row := new object[](count); + for(int i := 0; i < count; i++) + { + row[i] := self.at(i) + }; + + ^ row + } + + Enumerator enumerator() = new DBEnumerator(self); + + close() + { + _command.close() + } +} diff --git a/src60/sqlite/sqlite.prj b/src60/sqlite/sqlite.prj new file mode 100644 index 0000000000..af5c85ea86 --- /dev/null +++ b/src60/sqlite/sqlite.prj @@ -0,0 +1,28 @@ + + + + ..\..\lib60 + + + + + ..\..\lib60_64 + + + + sqlite + + + + ELENA SQLite Provider Library + 6.0.0 + Aleksey Rakov + + + + reader.l + data_table.l + common.l + + + \ No newline at end of file diff --git a/src60/system/collections/tuples.l b/src60/system/collections/tuples.l index f0fbb40ee5..15103f558d 100644 --- a/src60/system/collections/tuples.l +++ b/src60/system/collections/tuples.l @@ -26,6 +26,21 @@ namespace collections 0 { Item1 := val } ! { OutOfRangeException.raise() } } + + Indexer indexer() = new BaseIndexer + { + this index := 0; + + this length := 1; + + get Value() + = self.at(this index); + + set Value(o) + { + self.setAt(this index, o) + } + }; } public sealed Tuple @@ -61,7 +76,21 @@ namespace collections Tuple cast() = new Tuple(Item1, Item2); -// = (); + + Indexer indexer() = new BaseIndexer + { + this index := 0; + + this length := 2; + + get Value() + = self.at(this index); + + set Value(o) + { + self.setAt(this index, o) + } + }; } public sealed VarTuple @@ -130,6 +159,21 @@ namespace collections 2 { Item3 := val } ! { OutOfRangeException.raise() } } + + Indexer indexer() = new BaseIndexer + { + this index := 0; + + this length := 3; + + get Value() + = self.at(this index); + + set Value(o) + { + self.setAt(this index, o) + } + }; } public sealed Tuple @@ -170,6 +214,21 @@ namespace collections 3 { Item4 := val } ! { OutOfRangeException.raise() } } + + Indexer indexer() = new BaseIndexer + { + this index := 0; + + this length := 4; + + get Value() + = self.at(this index); + + set Value(o) + { + self.setAt(this index, o) + } + }; } public sealed Tuple @@ -214,6 +273,21 @@ namespace collections 4 { Item5 := val } ! { OutOfRangeException.raise() } } + + Indexer indexer() = new BaseIndexer + { + this index := 0; + + this length := 5; + + get Value() + = self.at(this index); + + set Value(o) + { + self.setAt(this index, o) + } + }; } public sealed Tuple @@ -262,5 +336,20 @@ namespace collections 5 { Item6 := val } ! { OutOfRangeException.raise() } } + + Indexer indexer() = new BaseIndexer + { + this index := 0; + + this length := 6; + + get Value() + = self.at(this index); + + set Value(o) + { + self.setAt(this index, o) + } + }; } } \ No newline at end of file diff --git a/src60/system/convertors.l b/src60/system/convertors.l index abea68b994..214cc131e6 100644 --- a/src60/system/convertors.l +++ b/src60/system/convertors.l @@ -566,7 +566,7 @@ public singleton realConvertor real convert(byte b) { - real r := b + real r := b; ^ r; } diff --git a/src60/system/culture/common.l b/src60/system/culture/common.l index 840f659604..57b798a7c5 100644 --- a/src60/system/culture/common.l +++ b/src60/system/culture/common.l @@ -23,4 +23,18 @@ namespace culture string toLower() = currentLocale.toLowercase(self); } -} \ No newline at end of file + + public extension wideStringCultureOp : WideString + { + wide toUpper(ILocale locale) + = locale.toUppercase(self); + + wide toUpper() + = currentLocale.toUppercase(self); + + wide toLower(ILocale locale) + = locale.toLowercase(self); + + wide toLower() + = currentLocale.toLowercase(self); + }} \ No newline at end of file diff --git a/src60/system/drawing/win_graphics.l b/src60/system/drawing/win_graphics.l index 06624ad4c8..bd302b2d2d 100644 --- a/src60/system/drawing/win_graphics.l +++ b/src60/system/drawing/win_graphics.l @@ -127,7 +127,7 @@ public sealed struct Canvas close() { - _HDC := 0 + _HDC := HDC.Default } setCaret(int x, int y) diff --git a/src60/system/drawing/win_handles.l b/src60/system/drawing/win_handles.l index 4cf78fc8a6..653b324097 100644 --- a/src60/system/drawing/win_handles.l +++ b/src60/system/drawing/win_handles.l @@ -92,19 +92,22 @@ public sealed struct RECT public sealed const struct HDC { - embeddable __ptr _handle; + handle _handle; static HDC Default = default; - constructor(int handle) + handle Handle + = _handle; + + constructor(handle h) { - _handle := handle + _handle := h } constructor newCompatible(HDC dc) { - int newDC := extern GDI32.CreateCompatibleDC(dc); + handle newDC := extern GDI32.CreateCompatibleDC(dc.Handle); _handle := newDC } @@ -121,24 +124,22 @@ public sealed const struct HDC select(HBITMAP bitmapHandle) { - extern GDI32.SelectObject(_handle, bitmapHandle) + extern GDI32.SelectObject(_handle, bitmapHandle.Handle) } select(HPEN penHandle) { - extern GDI32.SelectObject(_handle, penHandle) + extern GDI32.SelectObject(_handle, penHandle.Handle) } select(HBRUSH brushHandle) { - extern GDI32.SelectObject(_handle, brushHandle) + extern GDI32.SelectObject(_handle, brushHandle.Handle) } copy(int destX, int destY, int width, int height, HDC dc, int sourX, int sourY, int flags) { - extern GDI32.BitBlt(_handle, destX, destY, width, height, dc, sourX, sourY, flags) - - //#var(int) err := system'external'KERNEL32 GetLastError. + extern GDI32.BitBlt(_handle, destX, destY, width, height, dc.Handle, sourX, sourY, flags); } moveTo(int x, int y) @@ -168,30 +169,29 @@ public sealed const struct HDC public sealed const struct HBITMAP { - embeddable __ptr _handle; + handle _handle; constructor create(HDC dc, int width, int height) { - pointer h := extern GDI32.CreateCompatibleBitmap(dc, width, height); - - _handle := h + _handle := extern GDI32.CreateCompatibleBitmap(dc.Handle, width, height); } constructor load(wide path, int width, int height) { - pointer h := extern USER32.LoadImageW( + _handle := extern USER32.LoadImageW( 0, path, IMAGE_BITMAP, width, height, LR_LOADFROMFILE); - - _handle := h } + + handle Handle + = _handle; select(HDC handle) { - int retVal := extern GDI32.SelectObject(handle, _handle) + int retVal := extern GDI32.SelectObject(handle.Handle, _handle) } free() @@ -204,26 +204,27 @@ public sealed const struct HBITMAP public sealed const struct HPEN { - embeddable __ptr _handle; + handle _handle; static HPEN Default = default; - constructor(int handle) + constructor(handle handle) { _handle := handle } bool IsEmpty() - = 0 == _handle; + = _handle.isUnassigned(); constructor create(int style, int width, int color) { - int h := extern GDI32.CreatePen(style, width, color); - - _handle := h + _handle := extern GDI32.CreatePen(style, width, color); } + handle Handle + = _handle; + free() { extern GDI32.DeleteObject(_handle) @@ -234,23 +235,24 @@ public sealed const struct HPEN public sealed const struct HBRUSH { - embeddable __ptr _handle; + handle _handle; static HBRUSH Default = default; - constructor(int handle) + constructor(handle handle) { _handle := handle } constructor createSolid(int color) { - int h := extern GDI32.CreateSolidBrush(color); - - _handle := h + _handle := extern GDI32.CreateSolidBrush(color); } + handle Handle + = _handle; + free() { extern GDI32.DeleteObject(_handle) diff --git a/src60/system/io/win_console.l b/src60/system/io/win_console.l index ea73354ccf..8c3beffede 100644 --- a/src60/system/io/win_console.l +++ b/src60/system/io/win_console.l @@ -221,8 +221,6 @@ namespace io char read() { - handle h := extern KERNEL32.GetStdHandle(0FFFFFFF6h); - INPUT_RECORD dump := default; KEY_EVENT_RECORD rec := default; diff --git a/src60/system/winforms/win_app.l b/src60/system/winforms/win_app.l index af035d607b..2ad00efc0f 100644 --- a/src60/system/winforms/win_app.l +++ b/src60/system/winforms/win_app.l @@ -34,6 +34,35 @@ public sealed class SDIApplication } } + run(window) + { + MSG msg := new MSG(); + int proceeded := 0; + int result := 0; + WindowHandle handleCopy := window; + + extern + { + while (handleCopy.isVisible()) + { + result := extern USER32.PeekMessageW(msg, 0, 0, 0, 1); + if (result != 0) + { + proceeded := extern USER32.IsDialogMessageW(handleCopy, msg); + if (proceeded == 0) + { + extern USER32.TranslateMessage(msg); + extern USER32.DispatchMessageW(msg) + } + } + else + { + extern USER32.WaitMessage() + } + } + } + } + error(string caption, Exception e) { messageBox.open("ELENA", /*e.Message*/e.toPrintable(), MB_ICONEXCLAMATION); diff --git a/src60/system/winforms/win_common.l b/src60/system/winforms/win_common.l index 12289acb8a..2b389ef751 100644 --- a/src60/system/winforms/win_common.l +++ b/src60/system/winforms/win_common.l @@ -1,3 +1,5 @@ +public const int CW_USEDEFAULT = 80000000h; + public const int GWL_USERDATA = -21; public const int SWP_NOSIZE = 0001h; @@ -95,6 +97,7 @@ public const int WM_SETTEXT = 0Ch; public const int WM_GETTEXT = 0Dh; public const int WM_GETTEXTLENGTH = 0Eh; public const int WM_PAINT = 0Fh; +public const int WM_CLOSE = 10h; public const int OFN_PATHMUSTEXIST = 00000800h; public const int OFN_EXPLORER = 00080000h; diff --git a/src60/system/winforms/win_controls.l b/src60/system/winforms/win_controls.l index 6655c1241f..19fb5bfe82 100644 --- a/src60/system/winforms/win_controls.l +++ b/src60/system/winforms/win_controls.l @@ -27,6 +27,7 @@ public sealed const struct WindowHandle { handle hinstance := instance.Handle; handle h := UnsafePointer.Default; + handle hParent := parent.Handle; extern { h := extern USER32.CreateWindowExW( @@ -38,7 +39,7 @@ public sealed const struct WindowHandle y, width, height, - parent.Handle, + hParent, 0, hinstance, paramPtr) @@ -108,7 +109,7 @@ public sealed const struct WindowHandle { int r := extern USER32.SendMessageW(_handle, BM_GETCHECK, 0, 0); - ^ (r == BST_CHECKED) + ^ (r == BST_CHECKED) } setVisible(int n) @@ -125,7 +126,7 @@ public sealed const struct WindowHandle get HDC HDC() { - HDC dc := extern USER32.GetDC(_handle); + handle dc := extern USER32.GetDC(_handle); ^ dc } @@ -174,14 +175,17 @@ public sealed struct PAINTSTRUCT ^ _HDC } - begin(WindowHandle handle) + begin(WindowHandle hwnd) { - extern USER32.BeginPaint(handle, self) + Handle h := hwnd.Handle; + + extern USER32.BeginPaint(h, self) } - end(WindowHandle handle) + end(WindowHandle hwnd) { - extern USER32.EndPaint(handle, self) + Handle h := hwnd.Handle; + + extern USER32.EndPaint(h, self) } } - diff --git a/src60/system/winforms/win_dialogs.l b/src60/system/winforms/win_dialogs.l index d5e3bcf878..f063a3745c 100644 --- a/src60/system/winforms/win_dialogs.l +++ b/src60/system/winforms/win_dialogs.l @@ -40,8 +40,6 @@ struct tagOFNA int lCustData : prop; pointer lpfnHook : prop; pointer lpTemplateName : prop; - pointer lpEditInfo : prop; - pointer lpstrPrompt : prop; pointer pvReserved : prop; int dwReserved : prop; int FlagsEx : prop; @@ -52,70 +50,70 @@ struct tagOFNA class BaseFileDialog { WindowHandle _parent; - short[] _filters; - short[] _fileName; + wide[] _filters; int _filterIndex; - int _maxFile; wide _caption; int _flags; - constructor create(WindowHandle parent, wide[] filters, int filterIndex, int maxFile, wide caption, int flags) + constructor create(WindowHandle parent, wide[] filters, int filterIndex, wide caption, int flags) { - int s_length := 0; - int buf_size := 0; - _parent := parent; + _filters := filters; _filterIndex := filterIndex; - _fileName := new short[](maxFile + 1); - _fileName[0] := 0; - - _maxFile := maxFile; _caption := caption; - _flags := flags; + _flags := flags; + } + + internal fillFilters(short[] buffer, int size) + { + int s_length := 0; + int buf_size := 0; // calculate the filter buffer size - int length := filters.Length; + int length := _filters.Length; for (int i := 0; i < length; i += 1) { - wide filter := filters[i]; + wide filter := _filters[i]; s_length := filter.Length; buf_size := buf_size + s_length; buf_size := buf_size + 1 }; buf_size := buf_size + 2; + if (buf_size > size) { + InvalidArgumentException.raise("Invalid argument size - filters are too long"); + }; // fill the filter buffer - _filters := new short[](buf_size); buf_size := 0; for (int i := 0; i < length; i += 1) { - wide filter := filters[i]; + wide filter := _filters[i]; s_length := filter.Length; - UTF16Encoding.toShortArray(filter, 0, s_length, _filters, buf_size); + UTF16Encoding.toShortArray(filter, 0, s_length, buffer, buf_size); buf_size := buf_size + s_length; - _filters[buf_size] := 0; + buffer[buf_size] := 0; buf_size := buf_size + 1 }; - _filters[buf_size] := 0; - _filters[buf_size + 1] := 0; - } - - internal prepare(tagOFNA struct) + buffer[buf_size] := 0; + buffer[buf_size + 1] := 0; + } + + internal prepare(tagOFNA struct, short[] filters, short[] fileName, int maxFile) { - struct.lStructSize := 76; + struct.lStructSize := 88; struct.hwndOwner := _parent.Handle; struct.hInstance := CurrentInstance.Handle; - struct.lpstrFilter := _filters; + struct.lpstrFilter := filters; struct.nFilterIndex := _filterIndex; - struct.lpstrFile := _fileName; - struct.nMaxFile := _maxFile; + struct.lpstrFile := fileName; + struct.nMaxFile := maxFile; struct.lpstrTitle := _caption; - struct.FlagsEx := _flags; + struct.Flags := _flags; } } @@ -123,17 +121,26 @@ class BaseFileDialog public sealed class OpenFileDialog : BaseFileDialog { - constructor(WindowHandle parent, wide[] filters, int filterIndex, int maxFile, wide caption) - <= super create(parent, filters, filterIndex, maxFile, caption, - OFN_PATHMUSTEXIST | OFN_EXPLORER | OFN_LONGNAMES | DS_CENTER | OFN_HIDEREADONLY); + constructor(WindowHandle parent, wide[] filters, int filterIndex, wide caption) + <= super create(parent, filters, filterIndex, caption, + OFN_PATHMUSTEXIST | OFN_EXPLORER | OFN_LONGNAMES | OFN_HIDEREADONLY); select() { + short filters[1024]; + self.fillFilters(filters, 1024); + + short fileName[1024]; + fileName[0] := 0; + tagOFNA struct := default; + self.prepare(struct, filters, fileName, 1024); - self.prepare(struct); - // NOTE: !! it should be any object creation between two lines - int retVal := extern Comdlg32.GetOpenFileNameW(struct); + int retVal := 0; + extern + { + retVal := extern Comdlg32.GetOpenFileNameW(struct); + }; if (retVal == 0) { @@ -141,9 +148,9 @@ public sealed class OpenFileDialog : BaseFileDialog } else { - int length := extern KERNEL32.lstrlenW(_fileName); + int length := extern KERNEL32.lstrlenW(fileName); - var s := UTF16Encoding.toWideString(0, length, _fileName); + var s := UTF16Encoding.toWideString(0, length, fileName); ^ s } @@ -154,17 +161,26 @@ public sealed class OpenFileDialog : BaseFileDialog public sealed class SaveFileDialog : BaseFileDialog { - constructor(WindowHandle parent, wide[] filters, int filterIndex, int maxFile, wide caption) - <= super create(parent, filters, filterIndex, maxFile, caption, - OFN_PATHMUSTEXIST | OFN_EXPLORER | OFN_LONGNAMES | DS_CENTER | OFN_HIDEREADONLY); + constructor(WindowHandle parent, wide[] filters, int filterIndex, wide caption) + <= super create(parent, filters, filterIndex, caption, + OFN_PATHMUSTEXIST | OFN_EXPLORER | OFN_LONGNAMES | OFN_HIDEREADONLY); select() { + short filters[1024]; + self.fillFilters(filters, 1024); + + short fileName[1024]; + fileName[0] := 0; + tagOFNA struct := default; + self.prepare(struct, filters, fileName, 1024); - self.prepare(struct); - // NOTE: !! it should be any object creation between two lines - int retVal := extern Comdlg32.GetSaveFileNameW(struct); + int retVal := 0; + extern + { + retVal := extern Comdlg32.GetSaveFileNameW(struct); + }; if (retVal == 0) { @@ -172,9 +188,9 @@ public sealed class SaveFileDialog : BaseFileDialog } else { - int length := extern KERNEL32.lstrlenW(_fileName); + int length := extern KERNEL32.lstrlenW(fileName); - var s := UTF16Encoding.toWideString(0, length, _fileName); + var s := UTF16Encoding.toWideString(0, length, fileName); ^ s } diff --git a/src60/system/winforms/win_windows.l b/src60/system/winforms/win_windows.l index 6a8e2022b3..5424ff09f0 100644 --- a/src60/system/winforms/win_windows.l +++ b/src60/system/winforms/win_windows.l @@ -69,12 +69,16 @@ public closed class WindowCallback onWMDestoy(Handle hwnd) { - extern USER32.DefWindowProcW(hwnd, WM_DESTROY, 0, 0); + extern { + extern USER32.DefWindowProcW(hwnd, WM_DESTROY, 0, 0); + } } onWMPaint(Handle hwnd) { - extern USER32.DefWindowProcW(hwnd, WM_PAINT, 0, 0); + extern { + extern USER32.DefWindowProcW(hwnd, WM_PAINT, 0, 0); + } } onWMSize(Handle hwnd, int lParam) @@ -95,6 +99,13 @@ public closed class WindowCallback if (command == BN_CLICKED) { self.onClick(control); ^ self }; } + + onWMClose(Handle hwnd) + { + extern { + extern USER32.DefWindowProcW(hwnd, WM_CLOSE, 0, 0); + } + } } // --- SDIWindowCallback --- @@ -108,6 +119,11 @@ public class SDIWindowCallback : WindowCallback } } +// --- ChildWindowCallback --- +public class ChildWindowCallback : WindowCallback +{ +} + // --- SDIWindowClass --- public static wide SDIWindowClass = windowClassControl.createClass("ELENA.SDIWINDOW.6.0", CurrentInstance, WS_ELENAWINDOW, COLOR_BACKGROUND); diff --git a/src60/xforms/xforms.l b/src60/xforms/xforms.l new file mode 100644 index 0000000000..372bfd9081 --- /dev/null +++ b/src60/xforms/xforms.l @@ -0,0 +1,12 @@ +import extensions'scripting; + +static ScriptEngine xformsEngine + = new ScriptEngine() + .loadScript("[[ #grammar build ]]") + .loadPath("~\scripts\grammar60.es") + .loadPath("~\scripts\xforms60.es"); + +public singleton xforms +{ + +} \ No newline at end of file diff --git a/src60/xforms/xforms.prj b/src60/xforms/xforms.prj new file mode 100644 index 0000000000..7cb40fa6d1 --- /dev/null +++ b/src60/xforms/xforms.prj @@ -0,0 +1,26 @@ + + + + ..\..\lib60 + + + + + ..\..\lib60_64 + + + + xforms + + + + ELENA GUI Script Library + 6.0.0 + Aleksey Rakov + + + + xforms.l + + + \ No newline at end of file diff --git a/tests60/sandbox/sandbox.l b/tests60/sandbox/sandbox.l index 19aeedd5d8..b5f6ae488e 100644 --- a/tests60/sandbox/sandbox.l +++ b/tests60/sandbox/sandbox.l @@ -1,58 +1,16 @@ -import extensions; - -singleton VariadicFunctionDispatchTester -{ - function(params int[] args) +public singleton convertor +{ + generic(n) { - console.write("."); - int l := args.Length; -/* console.writeLine(l); - int sum := 0; - for (int i := 0; i < l; i += 1) { - sum := sum + args[i] - }; - console.write("."); + MessageName mssg := __received.MessageName; - ^ sum*/ + ^ mssg(new ExtensionVariable(n, extensions'intConvertOp)) } } -/* -singleton VariadicDispatchTester -{ - product(params int[] args) - { - int l := args.Length; - console.writeLine(l); - int prod := 1; - for (int i := 0; i < l; i += 1) { - prod := prod * args[i] - }; - console.write("."); - ^ prod - } -} -*/ public program() { -// console.write("vardispatcherTest:"); - - var r1 := VariadicFunctionDispatchTester(1,2,3); -// Assert.ifTrue(r1 == 6); - console.write("."); -/* - var r2 := VariadicDispatchTester.product(1,2,3,4); - Assert.ifTrue(r2 == 24); - console.write("."); - - var o := VariadicFunctionDispatchTester; - var o2 := VariadicDispatchTester; - var r3 := o(1,2,3); - Assert.ifTrue(r3 == 6); - console.write("."); - var r4 := o2.product(1,2,3,4); - Assert.ifTrue(r4 == 24); - console.write("."); + var n := convertor.toInt("2"); - console.writeLine(".");*/ + console.writeLine(n) } diff --git a/tests60/system_tests/basic.l b/tests60/system_tests/basic.l index 99d9beb248..ac356d3bdf 100644 --- a/tests60/system_tests/basic.l +++ b/tests60/system_tests/basic.l @@ -215,7 +215,12 @@ longTests() i *= 2l; i /= 2l; Assert.ifTrue(i == 1l); + console.write("."); + + var tester := (long l, long control1, long control2) { long r1 := -l; long r2 := -r1; Assert.ifTrue(r1 == control1); Assert.ifTrue(r2 == control2); }; + tester(-1l,1l,-1l); + tester(-5000000000l,5000000000l,-5000000000l); console.writeLine("."); }