diff --git a/.github/workflows/msbuild.yml b/.github/workflows/msbuild.yml index 83ee851d11..fe9473405f 100644 --- a/.github/workflows/msbuild.yml +++ b/.github/workflows/msbuild.yml @@ -20,7 +20,7 @@ env: # https://docs.github.com/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix BUILD_CONFIGURATION: Release - BUILD_TAG: 6.0.9 + BUILD_TAG: 6.1.0 permissions: contents: read diff --git a/VERSION b/VERSION index c5a1e4c436..358e78e607 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -6.0.10 \ No newline at end of file +6.1.0 \ No newline at end of file diff --git a/asm/amd64/core60_win_client.asm b/asm/amd64/core60_win_client.asm new file mode 100644 index 0000000000..6a42dc6a18 --- /dev/null +++ b/asm/amd64/core60_win_client.asm @@ -0,0 +1,53 @@ +define INVOKER 10001h + +define CORE_SINGLE_CONTENT 2000Bh + +define tt_stack_root 0028h + +// INVOKER(function, arg) +// INVOKER(function, arg) +procedure % INVOKER + + // ; RCX - function + // ; RDX - arg + + // ; save registers + push 0 + push rsi + push rdi + push rbx + push rbp + push r12 + push r13 + push r14 + push r15 + + // ; declare new frame + xor rdi, rdi + mov rax, rcx + push 0 // ; FrameHeader.previousFrame + push 0 // ; FrameHeader.reserved + mov rbp, rsp // ; FrameHeader + + mov [data : %CORE_SINGLE_CONTENT + tt_stack_root], rsp + + push 0 + push r8 // ; arg + + call rax + add rsp, 32 // ; clear FrameHeader+arg + mov rax, rbx + + // ; restore registers + pop r15 + pop r14 + pop r13 + pop r12 + pop rbp + pop rbx + pop rdi + pop rsi + add rsp, 8 + ret + +end diff --git a/bin/templates/vm_win_client60.cfg b/bin/templates/vm_win_client60.cfg index 472b06a866..0654a57f05 100644 --- a/bin/templates/vm_win_client60.cfg +++ b/bin/templates/vm_win_client60.cfg @@ -5,6 +5,9 @@ + + ..\amd64\core60_win_client.bin + 4352 diff --git a/build/aarch64/build_package_arm64.script b/build/aarch64/build_package_arm64.script index 48306bda60..682ef49492 100755 --- a/build/aarch64/build_package_arm64.script +++ b/build/aarch64/build_package_arm64.script @@ -1,5 +1,5 @@ #!/bin/bash -RELEASE=elena-6.0.10.aarch64-linux +RELEASE=elena-6.1.0.aarch64-linux mkdir -p /usr/share/elena mkdir -p /etc/elena/ diff --git a/build/aarch64/control b/build/aarch64/control index 5e44b3d3e5..ae3e1baea4 100644 --- a/build/aarch64/control +++ b/build/aarch64/control @@ -1,5 +1,5 @@ Package: elena-lang -Version: 6.0.10 +Version: 6.1.0 Architecture: aarch64 Maintainer: Alex Rakov Depends: libc6 (>= 2.1) diff --git a/build/amd64/build_package_amd64.script b/build/amd64/build_package_amd64.script index 306d5497ab..963e447613 100755 --- a/build/amd64/build_package_amd64.script +++ b/build/amd64/build_package_amd64.script @@ -1,5 +1,5 @@ #!/bin/bash -RELEASE=elena-6.0.10.amd64-linux +RELEASE=elena-6.1.0.amd64-linux mkdir -p /usr/share/elena mkdir -p /etc/elena/ diff --git a/build/amd64/control b/build/amd64/control index be7a3c4175..1bc9c25d0d 100644 --- a/build/amd64/control +++ b/build/amd64/control @@ -1,5 +1,5 @@ Package: elena-lang -Version: 6.0.10 +Version: 6.1.0 Architecture: amd64 Maintainer: Alex Rakov Depends: libc6 (>= 2.1) diff --git a/build/create_package_x64.bat b/build/create_package_x64.bat index b82079f98e..4e8f63243d 100644 --- a/build/create_package_x64.bat +++ b/build/create_package_x64.bat @@ -65,6 +65,7 @@ copy %~dp0\..\bin\elenavm60.cfg %~dp0\x64\bin copy %~dp0\..\bin\amd64\core60.bin %~dp0\x64\bin\amd64 copy %~dp0\..\bin\amd64\core60_win.bin %~dp0\x64\bin\amd64 copy %~dp0\..\bin\amd64\corex60.bin %~dp0\x64\bin\amd64 +copy %~dp0\..\bin\amd64\core60_win_client.bin %~dp0\x64\bin\amd64 copy %~dp0\..\bin\templates\*.cfg %~dp0\x64\bin\templates\ copy %~dp0\..\bin\scripts\*.es %~dp0\x64\bin\scripts\ diff --git a/build/create_package_x86.bat b/build/create_package_x86.bat index ed8ae77976..271764110b 100644 --- a/build/create_package_x86.bat +++ b/build/create_package_x86.bat @@ -104,6 +104,7 @@ copy %~dp0\..\doc\license %~dp0\x86\doc\ copy %~dp0\..\doc\contributors %~dp0\x86\doc\ copy %~dp0\..\readme.md %~dp0\x86\ copy %~dp0\..\CHANGELOG.md %~dp0\x86\ +copy %~dp0\..\VERSION %~dp0\x86\ md %~dp0\x86\src60\system xcopy %~dp0\..\src60\system\*.l %~dp0\x86\src60\system /s @@ -137,6 +138,10 @@ md %~dp0\x86\src60\ltests xcopy %~dp0\..\src60\ltests\*.l %~dp0\x86\src60\ltests /s xcopy %~dp0\..\src60\ltests\*.prj %~dp0\x86\src60\ltests /s +md %~dp0\x86\src60\net +xcopy %~dp0\..\src60\net\*.l %~dp0\x86\src60\net /s +xcopy %~dp0\..\src60\net\*.prj %~dp0\x86\src60\net /s + %~dp0\..\bin\sg-cli.exe %~dp0\..\dat\sg\syntax60.txt @echo off if %ERRORLEVEL% EQU -2 GOTO CompilerError @@ -202,12 +207,27 @@ if %ERRORLEVEL% EQU -2 GOTO CompilerError if %ERRORLEVEL% EQU -2 GOTO CompilerError @echo on -%~dp0\..\bin\asm-cli -x86 %~dp0\..\asm\x86\core60.asm bin\x32 +%~dp0\x86\bin\elena-cli %~dp0\x86\src60\net\net.prj +@echo off +if %ERRORLEVEL% EQU -2 GOTO CompilerError +@echo on + +%~dp0\..\bin\asm-cli -x86 %~dp0\..\asm\x32\core60.asm %~dp0\x86\bin\x32 +@echo off +if %ERRORLEVEL% EQU -2 GOTO CompilerError +@echo on + +%~dp0\..\bin\asm-cli -x86 %~dp0\..\asm\x32\core60_win.asm %~dp0\x86\bin\x32 +@echo off +if %ERRORLEVEL% EQU -2 GOTO CompilerError +@echo on + +%~dp0\..\bin\asm-cli -x86 %~dp0\..\asm\x32\corex60.asm %~dp0\x86\bin\x32 @echo off if %ERRORLEVEL% EQU -2 GOTO CompilerError @echo on -%~dp0\..\bin\asm-cli -x86 %~dp0\..\asm\x86\core60_win.asm bin\x32 +%~dp0\..\bin\asm-cli -x86 %~dp0\..\asm\x32\core60_win_client.asm %~dp0\x86\bin\x32 @echo off if %ERRORLEVEL% EQU -2 GOTO CompilerError @echo on diff --git a/build/elena_inno.iss b/build/elena_inno.iss index cfeac38450..68ec03d385 100644 --- a/build/elena_inno.iss +++ b/build/elena_inno.iss @@ -7,7 +7,7 @@ ; (To generate a new GUID, click Tools | Generate GUID inside the IDE.) AppId={{3CAA69D3-0F98-44B1-A73E-E864BA51D5BD} AppName=ELENA Programming Language -AppVersion=6.0.10 +AppVersion=6.1.0 ;AppVerName=ELENA Programming Language 6.0.10 AppPublisher=Alexey Rakov AppPublisherURL=http://github.com/ELENA-LANG/elena-lang @@ -18,7 +18,7 @@ DefaultGroupName=ELENA Programming Language AllowNoIcons=yes LicenseFile=..\doc\license InfoAfterFile=..\CHANGELOG.md -OutputBaseFilename=elena-lang-6.0.10.x86-setup +OutputBaseFilename=elena-lang-6.1.0.x86-setup Compression=lzma SolidCompression=yes ChangesEnvironment=yes diff --git a/build/i386/build_package_i386.script b/build/i386/build_package_i386.script index 6e6c38857f..c566a998c9 100755 --- a/build/i386/build_package_i386.script +++ b/build/i386/build_package_i386.script @@ -1,5 +1,5 @@ #!/bin/bash -RELEASE=elena-6.0.10.i386-linux +RELEASE=elena-6.1.0.i386-linux mkdir -p /usr/share/elena mkdir -p /etc/elena/ diff --git a/build/i386/control b/build/i386/control index c19e19d45a..d50d8a9c49 100644 --- a/build/i386/control +++ b/build/i386/control @@ -1,5 +1,5 @@ Package: elena-lang -Version: 6.0.10 +Version: 6.1.0 Architecture: i386 Maintainer: Alex Rakov Depends: libc6 (>= 2.1) diff --git a/build/ppc64le/build_package_ppc64le.script b/build/ppc64le/build_package_ppc64le.script index bcd49a0d64..94fdcbbafa 100755 --- a/build/ppc64le/build_package_ppc64le.script +++ b/build/ppc64le/build_package_ppc64le.script @@ -1,5 +1,5 @@ #!/bin/bash -RELEASE=elena-6.0.10.ppc64le-linux +RELEASE=elena-6.1.0.ppc64le-linux mkdir -p /usr/share/elena mkdir -p /etc/elena/ diff --git a/build/ppc64le/control b/build/ppc64le/control index c029b9d762..37660f3e31 100644 --- a/build/ppc64le/control +++ b/build/ppc64le/control @@ -1,5 +1,5 @@ Package: elena-lang -Version: 6.0.10 +Version: 6.1.0 Architecture: ppc64le Maintainer: Alex Rakov Depends: libc6 (>= 2.1) diff --git a/build/rebuild_lib60_x64.bat b/build/rebuild_lib60_x64.bat index 5135d4883a..87c7f890ce 100644 --- a/build/rebuild_lib60_x64.bat +++ b/build/rebuild_lib60_x64.bat @@ -29,6 +29,11 @@ bin\asm64-cli -amd64 asm\amd64\core60_win.asm bin\amd64 if %ERRORLEVEL% EQU -1 GOTO Asm2BinError @echo on +bin\asm64-cli -amd64 asm\amd64\core60_win_client.asm bin\amd64 +@echo off +if %ERRORLEVEL% EQU -1 GOTO Asm2BinError +@echo on + bin\asm64-cli -bc64 src60\core\system.core_routines.esm lib60_64 @echo off if %ERRORLEVEL% EQU -1 GOTO Asm2BinError diff --git a/dat/sg/syntax60.txt b/dat/sg/syntax60.txt index 3bed66c20b..548b7dcb39 100644 --- a/dat/sg/syntax60.txt +++ b/dat/sg/syntax60.txt @@ -139,7 +139,12 @@ DECLARATION ::= | "::" "(" TUPLE_TYPE ")" identifier SUB_IR_DECLARATION; IR_DECLARATION ::= - { TEMPLATE_BRACKETS identifier? | { DYNAMIC_DIMENSION ^ARRAY_TYPE }+ identifier } { POSTFIXES NESTED_SCOPE | SCOPE } + { TEMPLATE_BRACKETS { + DYNAMIC_DIMENSION ^TEMPLATE_TYPE ^ARRAY_TYPE { DYNAMIC_DIMENSION ^ARRAY_TYPE }* identifier + | identifier + | eps} + | { DYNAMIC_DIMENSION ^ARRAY_TYPE }+ identifier + } { POSTFIXES NESTED_SCOPE | SCOPE } | "::" { COMPLEX_NAME { "::" COMPLEX_NAME }* TEMPLATE_BRACKETS? METHOD_SCOPE | "(" TUPLE_TYPE ")" identifier SCOPE @@ -447,6 +452,7 @@ EXPRESSION ::= | L9_OOP | LESS ^OBJECT TEMPLATE_ARG { "," TEMPLATE_ARG }* ">" ^TEMPLATE_TYPE { "{" NESTED_EXPRESSION ^NESTED OL_F + | { DYNAMIC_DIMENSION ^ARRAY_TYPE }+ ^OBJECT BRACKET FUNCTION_R L3_OP* L4_OP* L5_OP* L6_OP? L7_OP* L8_OP? L9_OP? | SBRACKET ^OBJECT INDEXER_R OL_F | BRACKET ^OBJECT FUNCTION_R OL_F | L3_OOP L3_OP* L4_OP* L5_OP* L6_OP? L7_OP* L8_OP? L9_OP? @@ -933,6 +939,7 @@ L0_F ::= L2_F ::= L2_OP L2_F | DOT MESSAGE { L3_F | eps ^PROPERTY_OPERATION } + | ":" ^EXPRESSION identifier TEMPLATE_ARG ^ TEMPLATE_EXPR_BLOCK | L4_OP+ L5_OP* L6_OP? L7_OP* L8_OP? L9_OP? | L5_OP+ L6_OP? L7_OP* L8_OP? L9_OP? | L6_OP L7_OP* L8_OP? L9_OP? @@ -946,6 +953,7 @@ L3_F ::= | ASSIGN EXPRESSION ^PROPERTY_OPERATION | BRACKET MESSAGE_R { DOT MESSAGE { L3_F | eps ^PROPERTY_OPERATION } + | ":" ^EXPRESSION identifier TEMPLATE_ARG ^ TEMPLATE_EXPR_BLOCK | L4_OP+ L5_OP* L6_OP? L7_OP* L8_OP? L9_OP? | L5_OP+ L6_OP? L7_OP* L8_OP? L9_OP? | L6_OP L7_OP* L8_OP? L9_OP? @@ -953,7 +961,7 @@ L3_F ::= | L8_OP | L9_OP | 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 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? diff --git a/doc/api/forms.html b/doc/api/forms.html index 6668693982..3fdc2c8842 100644 --- a/doc/api/forms.html +++ b/doc/api/forms.html @@ -713,16 +713,7 @@

Method Summary

internal   -appendControlInternal(BaseControl control) - - - - - - -internal   - -appendControlInternal(ImageList control) +appendControlInternal(control) @@ -904,7 +895,7 @@

Method Summary

-IControl +
retrieve(Handle handle) @@ -1195,7 +1186,7 @@

Method Summary

-IControl + retrieve(Handle handle) @@ -1219,6 +1210,15 @@

Method Summary

+ + + + + +click() + + + @@ -1396,7 +1396,7 @@

Method Summary

-appendControl(BaseControl control) +appendControl(control) @@ -2607,6 +2607,15 @@

Method Summary

+ + + + + +close() + + + diff --git a/doc/api/system-collections-summary.html b/doc/api/system-collections-summary.html index b3f729b7f1..ebca025bed 100644 --- a/doc/api/system-collections-summary.html +++ b/doc/api/system-collections-summary.html @@ -116,6 +116,51 @@

+SortedArrayList + + +
+public class SortedArrayList
+ + + + +SortedList + + +
+public class SortedList
+ + + + +SortedList<T1,T2> + + +
+public template SortedList<T1,T2>
+ + + + +SortedListEnumerator + + +
+public class SortedListEnumerator
+ + + + +SortedListIndexer + + +
+public class SortedListIndexer
+ + + + Stack @@ -123,7 +168,7 @@

public class Stack - + Stack<T1> @@ -132,7 +177,7 @@

public template Stack<T1> - + StackEnumerator @@ -141,7 +186,7 @@

public class StackEnumerator - + Tuple<T1> @@ -150,7 +195,7 @@

public template Tuple<T1> - + Tuple<T1,T2> @@ -159,7 +204,7 @@

public template Tuple<T1,T2> - + Tuple<T1,T2,T3> @@ -168,7 +213,7 @@

public template Tuple<T1,T2,T3> - + Tuple<T1,T2,T3,T4> @@ -177,7 +222,7 @@

public template Tuple<T1,T2,T3,T4> - + Tuple<T1,T2,T3,T4,T5> @@ -186,7 +231,7 @@

public template Tuple<T1,T2,T3,T4,T5> - + Tuple<T1,T2,T3,T4,T5,T6> @@ -195,7 +240,7 @@

public template Tuple<T1,T2,T3,T4,T5,T6> - + VarTuple<T1,T2> diff --git a/doc/api/system-collections.html b/doc/api/system-collections.html index 5649566ceb..ac719ab1a5 100644 --- a/doc/api/system-collections.html +++ b/doc/api/system-collections.html @@ -1937,6 +1937,1003 @@

Method Summary


+ + + +
+
+system'collections'
+

SortedArrayList

+
+
+
+
+
+
+public class SortedArrayList
+
+
+ + + + + + +
    +
  • +

    Property Summary

    + + + + + + + + + +
    Modifier and TypeProperty
    + +get  IntNumber +Length() +
    +
  • +
+ +
    +
  • +

    Method Summary

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Modifier and TypeMethod
    + +Indexer +indexer() + +
    + + +append(Object key, Object item) + +
    + + +at(IntNumber index) + +
    + + +setAt(IntNumber index, Object o) + +
    + + +remove(IntNumber index) + +
    + + +clear() + +
    + + +trim(IntNumber pos) + +
    + +Enumerator +enumerator() + +
    +
  • +
+
+
+ + + +
+
+system'collections'
+

SortedList

+
+
+
+
+
+
+public class SortedList
+
+
+ + + + + + +
    +
  • +

    Property Summary

    + + + + + + + + + + + + + +
    Modifier and TypeProperty
    + +get  IntNumber +Length() +
    + +get internal  SortedListItem +FirstItem() +
    +
  • +
+ + +
+
+ + + +
+
+system'
+

SortedList<T1,T2>

+
+
+
+
+
+
+public template SortedList<T1,T2>
+
+
+ + + + + + +
    +
  • +

    Property Summary

    + + + + + + + + + +
    Modifier and TypeProperty
    + +get  IntNumber +Length() +
    +
  • +
+ +
    +
  • +

    Method Summary

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Modifier and TypeMethod
    + +Enumerator<T2> +enumerator() + +
    + + +append(T1 key, T2 item) + +
    + +T2 +at(IntNumber index) + +
    + + +setAt(IntNumber index, T2 o) + +
    + + +remove(IntNumber index) + +
    + + +clear() + +
    + + +trim(IntNumber pos) + +
    + +Indexer<T2> +indexer() + +
    +
  • +
+
+
+ + + +
+
+system'collections'
+

SortedListEnumerator

+
+
+
+
+
+
+public class SortedListEnumerator
+
+
+ + + + +
    +
  • +

    Constructor / Static Method Summary

    + + + + + + + + + +
    Modifier and TypeConstructor / Static Method
    + +SortedListEnumerator +constructor(SortedList list) + +
    +
  • +
+ +
    +
  • +

    Property Summary

    + + + + + + + + + +
    Modifier and TypeProperty
    + +get   +Value() +
    +
  • +
+ +
    +
  • +

    Method Summary

    + + + + + + + + + + + + + + + + + +
    Modifier and TypeMethod
    + +BoolValue +next() + +
    + + +reset() + +
    + + +enumerable() + +
    +
  • +
+
+
+ + + +
+
+system'collections'
+

SortedListIndexer

+
+
+
+
+
+
+public class SortedListIndexer
+
+
+ + + + +
    +
  • +

    Constructor / Static Method Summary

    + + + + + + + + + +
    Modifier and TypeConstructor / Static Method
    + +SortedListIndexer +constructor(SortedList list) + +
    +
  • +
+ +
    +
  • +

    Property Summary

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Modifier and TypeProperty
    + +get  BoolValue +Available() +
    + +get   +Value() +
    + +set   +Value(value) + +
    + +get  IntNumber +Index() +
    + +set   +Index(IntNumber value) + +
    + +get  IntNumber +Length() +
    +
  • +
+ +
    +
  • +

    Method Summary

    + + + + + + + + + +
    Modifier and TypeMethod
    + + +appendIndex(IntNumber index) + +
    +
  • +
+
+
diff --git a/doc/api/system-dynamic-summary.html b/doc/api/system-dynamic-summary.html index 5c6fe2d6ca..1b1ae6138b 100644 --- a/doc/api/system-dynamic-summary.html +++ b/doc/api/system-dynamic-summary.html @@ -244,6 +244,15 @@

+Message + + +
+public class Message
+ + + + Object diff --git a/doc/api/system-dynamic.html b/doc/api/system-dynamic.html index 664ca114c6..fcb2081807 100644 --- a/doc/api/system-dynamic.html +++ b/doc/api/system-dynamic.html @@ -2293,6 +2293,54 @@

Method Summary


+ + + +
+
+system'
+

Message

+
+
+
+
+
+
+public class Message
+
+
+ +
    +
  • +

    Extension Summary

    + + + + + + + + + + + + + +
    Modifier and TypeExtension Method
    + +IntNumber +__loadSignature(system'Object[] output, IntNumber maximalLength) + +
    + + +__getFirstSignatureMember() + +
    +
  • +
+
+
@@ -2350,6 +2398,15 @@

Extension Summary

+__injectInferface(Object type) + + + + + + + + mixInto(Object role) diff --git a/doc/api/system-io-summary.html b/doc/api/system-io-summary.html index a51f991b7b..afe5f1f568 100644 --- a/doc/api/system-io-summary.html +++ b/doc/api/system-io-summary.html @@ -44,6 +44,24 @@

+BaseTextReader + + +
+abstract public class BaseTextReader
+ + + + +BaseTextWriter + + +
+abstract public class BaseTextWriter
+ + + + BinaryReader diff --git a/doc/api/system-io.html b/doc/api/system-io.html index 6e0241d232..f382e0663e 100644 --- a/doc/api/system-io.html +++ b/doc/api/system-io.html @@ -23,6 +23,224 @@ + + + +
+
+system'io'
+

BaseTextReader

+
+
+
+
+
+
+abstract public class BaseTextReader
+
+
+ + +
    +
  • +

    Field Summary

    + + + + + + + + + + + + + + + + + +
    Modifier and TypeField
    + +TextBuilder +_output +
    + +String +_newLineConstant +
    + +IntNumber +_newLineLength +
    +
  • +
+ +
    +
  • +

    Method Summary

    + + + + + + + + + + + + + +
    Modifier and TypeMethod
    + +String +readLine() + +
    + +WideString +readWideLine() + +
    +
  • +
+
+
+ + + +
+
+system'io'
+

BaseTextWriter

+
+
+
+
+
+
+abstract public class BaseTextWriter
+
+
+ + +
    +
  • +

    Field Summary

    + + + + + + + + + + + + + + + + + +
    Modifier and TypeField
    + +TextBuilder +_buffer +
    + +String +_newLineConstant +
    + +IntNumber +_newLineLength +
    +
  • +
+ +
    +
  • +

    Method Summary

    + + + + + + + + + + + + + + + + + + + + + +
    Modifier and TypeMethod
    + + +write(String line) + +
    + + +write(WideString line) + +
    + + +writeLine(line) + +
    + + +writeLine() + +
    +
  • +
+
+
@@ -2254,12 +2472,18 @@

StreamWriter

  • + +
    • @@ -2437,42 +2661,6 @@

      TextReader

    - -
      -
    • -

      Field Summary

      - - - - - - - - - - - - - - - - - -
      Modifier and TypeField
      - -TextBuilder -_output -
      - -String -_newLineConstant -
      - -IntNumber -_newLineLength -
      -
    • -
    + +
    • @@ -2784,42 +2978,6 @@

      TextWriter

    - -
      -
    • -

      Field Summary

      - - - - - - - - - - - - - - - - - -
      Modifier and TypeField
      - -TextBuilder -_buffer -
      - -String -_newLineConstant -
      - -IntNumber -_newLineLength -
      -
    • -
    • @@ -2887,34 +3045,34 @@

      Method Summary

      - +abstract   -writeLine(line) +write(String line) - +abstract   -write(String line) +write(WideString line) - +abstract   -write(WideString line) +writeLine(line) - +abstract   writeLine() diff --git a/doc/api/system-summary.html b/doc/api/system-summary.html index 42e64f56b2..d87eb28191 100644 --- a/doc/api/system-summary.html +++ b/doc/api/system-summary.html @@ -90,6 +90,15 @@

      +BaseEnumerator + + +
      +abstract public class BaseEnumerator
      + + + + BaseEnumerator<T1> @@ -97,7 +106,7 @@

      abstract public template BaseEnumerator<T1> - + BaseExtender @@ -106,7 +115,7 @@

      public class BaseExtender - + BaseIndexer @@ -115,7 +124,7 @@

      abstract public class BaseIndexer - + BaseIndexer<T1> @@ -124,7 +133,7 @@

      abstract public template BaseIndexer<T1> - + BaseLazyExpression @@ -133,7 +142,7 @@

      abstract public class BaseLazyExpression - + BaseNumber @@ -143,7 +152,7 @@

      a base numeric value - + BaseValue @@ -153,7 +162,7 @@

      a base value - + BaseVariable @@ -163,7 +172,7 @@

      variable base class - + BitArray @@ -172,7 +181,7 @@

      public class BitArray - + BitArray32 @@ -181,7 +190,7 @@

      public class BitArray32 - + BoolValue @@ -191,7 +200,7 @@

      a common boolean value - + BoolValue#false @@ -200,7 +209,7 @@

      public singleton BoolValue#false - + BoolValue#true @@ -209,7 +218,7 @@

      public singleton BoolValue#true - + byteArrayConvertor @@ -218,7 +227,7 @@

      public singleton byteArrayConvertor - + byteConvertor @@ -227,7 +236,7 @@

      public singleton byteConvertor - + ByteNumber @@ -237,7 +246,7 @@

      an unsigned 8 bit integer - + CallStack @@ -247,7 +256,7 @@

      A call stack - + charConvertor @@ -256,7 +265,7 @@

      public singleton charConvertor - + CharValue @@ -266,7 +275,7 @@

      An UTF-32 character symbol - + ClassReference @@ -275,7 +284,7 @@

      public class ClassReference - + Console @@ -284,7 +293,7 @@

      public class Console - + COORD @@ -293,7 +302,7 @@

      public class COORD - + CriticalException @@ -302,7 +311,7 @@

      public class CriticalException - + DivisionByZeroException @@ -311,7 +320,7 @@

      public class DivisionByZeroException - + Enumerable @@ -320,7 +329,7 @@

      abstract public class Enumerable - + Enumerable<T1> @@ -329,7 +338,7 @@

      abstract public template Enumerable<T1> - + Enumerator @@ -339,7 +348,7 @@

      An enumerator prototype - + Enumerator<T1> @@ -348,7 +357,7 @@

      abstract public template Enumerator<T1> - + Exception @@ -358,7 +367,7 @@

      A basic exception - + Extension @@ -367,7 +376,7 @@

      public class Extension - + ExtensionMessage @@ -377,7 +386,7 @@

      An extended message constant - + ExtensionVariable @@ -386,7 +395,7 @@

      public class ExtensionVariable - + FormatException @@ -395,7 +404,7 @@

      public class FormatException - + Func @@ -405,6 +414,15 @@

      A base action + + +Func<T1,T1,system'IntNumber> + + +
      +abstract public template Func<T1,T1,system'IntNumber>
      + + Func<T1,T2> diff --git a/doc/api/system-text-summary.html b/doc/api/system-text-summary.html index 3de4a3e16b..7c2c149a85 100644 --- a/doc/api/system-text-summary.html +++ b/doc/api/system-text-summary.html @@ -53,6 +53,15 @@

      +StringBuilder + + +
      +public class StringBuilder
      + + + + TextBuilder @@ -60,7 +69,7 @@

      public class TextBuilder - + UTF16Encoder @@ -69,7 +78,7 @@

      public singleton UTF16Encoder - + UTF16Encoding @@ -78,7 +87,7 @@

      public singleton UTF16Encoding - + UTF8Encoder @@ -87,7 +96,7 @@

      public singleton UTF8Encoder - + UTF8Encoding @@ -96,6 +105,15 @@

      public singleton UTF8Encoding + + +WideStringBuilder + + +
      +public class WideStringBuilder
      + + WinEncoder diff --git a/doc/api/system-text.html b/doc/api/system-text.html index 0f188f1373..2a8ecec81d 100644 --- a/doc/api/system-text.html +++ b/doc/api/system-text.html @@ -126,6 +126,186 @@

      Method Summary


    + + + +
    +
    +system'text'
    +

    StringBuilder

    +
    +
    +
    +
    +
    +
    +public class StringBuilder
    +
    +
    + + + + +
      +
    • +

      Constructor / Static Method Summary

      + + + + + + + + + +
      Modifier and TypeConstructor / Static Method
      + +StringBuilder +constructor() + +
      +
    • +
    + +
      +
    • +

      Property Summary

      + + + + + + + + + + + + + +
      Modifier and TypeProperty
      + +get  IntNumber +Length() +
      + +get  String +Value() +
      +
    • +
    + +
      +
    • +

      Method Summary

      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      Modifier and TypeMethod
      + + +insert(index, o) + +
      + + +write(CharValue ch) + +
      + + +write(String s) + +
      + + +wide(o) + +
      + + +insert(IntNumber index, CharValue ch) + +
      + + +insert(IntNumber index, String s) + +
      + + +delete(IntNumber index, IntNumber length) + +
      +
    • +
    +
    +
    @@ -669,6 +849,15 @@

    Method Summary

    + + +toShortArray(CharValue ch, system'ShortNumber[] output, IntNumber outputIndex, ref IntNumber len) + + + + + + IntNumber getCharCount(WideString s) @@ -811,6 +1000,186 @@

    Method Summary


    + + + +
    +
    +system'text'
    +

    WideStringBuilder

    +
    +
    +
    +
    +
    +
    +public class WideStringBuilder
    +
    +
    + + + + +
      +
    • +

      Constructor / Static Method Summary

      + + + + + + + + + +
      Modifier and TypeConstructor / Static Method
      + +WideStringBuilder +constructor() + +
      +
    • +
    + +
      +
    • +

      Property Summary

      + + + + + + + + + + + + + +
      Modifier and TypeProperty
      + +get  IntNumber +Length() +
      + +get  String +Value() +
      +
    • +
    + + +
    +
    diff --git a/doc/api/system.html b/doc/api/system.html index 1613f9e3b3..0ae92c1e94 100644 --- a/doc/api/system.html +++ b/doc/api/system.html @@ -373,6 +373,8 @@

    Constructor / Static Method Summary

    copy(T1[] target, T1[] source, IntNumber index, IntNumber length) +
    +Copies a subarray from source starting at index to target
    @@ -382,6 +384,8 @@

    Constructor / Static Method Summary

    copyTo(T1[] target, T1[] source, IntNumber index, IntNumber length) +
    +Copies a source array to target at index
    @@ -885,6 +889,89 @@

    Method Summary


    + + + +
    +
    +system'
    +

    BaseEnumerator

    +
    +
    +
    +
    +
    +
    +abstract public class BaseEnumerator
    +
    +
    + + + + +
      +
    • +

      Method Summary

      + + + + + + + + + +
      Modifier and TypeMethod
      + +BoolValue +next() + +
      +
    • +
    +
    +
    @@ -5884,6 +5971,75 @@

    Method Summary


    + + + +
    +
    +system'
    +

    Func<T1,T1,system'IntNumber>

    +
    +
    +
    +
    +
    +
    +abstract public template Func<T1,T1,system'IntNumber>
    +
    +
    +
      +
    • +system'Object
    • +
    • +
        +
      • +system'Func<T1,T1,system'IntNumber>
      • +
      +
    • +
    + +
      +
    • +

      Conversion Summary

      + + + + + + + + + +
      Modifier and TypeConversion Method
      + +Func2 +cast() +
      +
    • +
    + +
      +
    • +

      Method Summary

      + + + + + + + + + +
      Modifier and TypeMethod
      + +abstract  IntNumber +function(T1 arg1, T1 arg2) + +
      +
    • +
    +
    +
    diff --git a/doc/tech/bytecode60.txt b/doc/tech/bytecode60.txt index 7b4e83649a..072cb73f1d 100644 --- a/doc/tech/bytecode60.txt +++ b/doc/tech/bytecode60.txt @@ -132,7 +132,7 @@ ELENA byte codes (or ecodes) xassign i - acc[i] := sp[0]; direct operation - xfsave - double:[acc] := double:index + xfsave - double:[acc] := double:index xget - acc[index] => acc @@ -140,7 +140,7 @@ ELENA byte codes (or ecodes) xlload - long:index := long:acc[index] - xpeekne - acc <= COMP.EQ ? sp[0] : acc + xpeekeq - acc <= COMP.EQ ? sp[0] : acc xset fp:i - fp[index + i] => acc diff --git a/doc/todo.txt b/doc/todo.txt index 2bc0e16c05..0e10f1b094 100644 --- a/doc/todo.txt +++ b/doc/todo.txt @@ -3,28 +3,106 @@ In development: ------ [development] - ### EPIC: elena 6.0 - redux ### + ### EPIC: elena 6.2 ### - === Iteration 23 === + === Iteration 24 === -------------------------------------- - dev: #574,#265,#619,#637(bt tests (>=4), all bc tests) + dev: #574,#265,#619,#580 op: github action - create a draft release - opt:pi under 6 sec - maint:#620, #486, #506 + opt:pi under 6 sec, #611, #602, #601, #586 + maint:#486, #506, #650 exp: generate code templates - e.g. simple console app - ide:linux simplest gui, vm debugger - tools:elt64-cli - prom:#635 on reddit;elena in nutshell every 1 week; post an article describing how to use distributed dictionary for test - port:chat sample, elenavm / elt for linux, helloworld gui sample (button) + ide:vm debugger, #617, linux ide, linux debugger + tools:#618, #620 + prom:#635 on reddit;elena in nutshell every 1 week; post an article about attributes (decorate a class, defining which operation is allowed) + port:elenavm / elt for linux, helloworld gui sample (button) + -------------------------------------- + - #590 : functional test + - #620 : add out argument (a special case of Reference template), to indicate the variable must be assigned before the method exit + * #590 : vm : InjectProxyTypeLA + - #590 : implementing interface injection : strong interface + - #184 : linux simplest gui + - elt : nested call must not stop / start vm + - elt : fails after executing several times + - #99 + - #98 + - #97 + - #79 + - #637(bt tests (>=4), all bc tests) + - #69 + - chat sample + -------------------------------------- - === Iteration 24 === + === Iteration 25 === -------------------------------------- dev: async programming (instant messagange sample (chat) ) op: opt: - maint: + maint:#620 exp: ide: tools: prom: port:upndown + + === Iteration 26 === + -------------------------------------- + dev: + op: + opt: + maint: + exp: + ide: + tools: + prom: + port: + + ### EPIC: elena 6.3 ### + + === Iteration 27 === + -------------------------------------- + dev: + op: + opt: + maint: + exp: + ide: + tools: + prom: + port: + + === Iteration 28 === + -------------------------------------- + dev: + op: + opt: + maint: + exp: + ide: + tools: + prom: + port: + + === Iteration 29 === + -------------------------------------- + dev: + op: + opt: + maint: + exp: + ide: + tools: + prom: + port: + + === Iteration 30 === + -------------------------------------- + dev: + op: + opt: + maint: + exp: + ide: + tools: + prom: + port: diff --git a/elenasrc3/common/streams.h b/elenasrc3/common/streams.h index 815fb6adc6..2bf5a1b1d9 100644 --- a/elenasrc3/common/streams.h +++ b/elenasrc3/common/streams.h @@ -3,7 +3,7 @@ // // This header contains the declaration of abstract stream reader // and writer classes -// (C)2021-2023, by Aleksey Rakov +// (C)2021-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #ifndef STREAMS_H @@ -37,6 +37,13 @@ namespace elena_lang return value; } + static unsigned long long getQWord(MemoryBase* source, pos_t position) + { + unsigned long long value = 0; + source->read(position, &value, sizeof(value)); + + return value; + } static void maskDWord(MemoryBase* source, pos_t position, ref_t mask) { diff --git a/elenasrc3/elc/cliconst.h b/elenasrc3/elc/cliconst.h index 70105d76ca..76b30ef11c 100644 --- a/elenasrc3/elc/cliconst.h +++ b/elenasrc3/elc/cliconst.h @@ -13,7 +13,7 @@ namespace elena_lang { - #define ELC_REVISION_NUMBER 0x026F + #define ELC_REVISION_NUMBER 0x0008 #if defined _M_IX86 || _M_X64 diff --git a/elenasrc3/elc/compiler.cpp b/elenasrc3/elc/compiler.cpp index c5bfe3cd2b..88a5c12f8c 100644 --- a/elenasrc3/elc/compiler.cpp +++ b/elenasrc3/elc/compiler.cpp @@ -167,6 +167,56 @@ inline bool isConstant(ObjectKind kind) } } +inline bool isSingleObject(ObjectKind kind) +{ + switch (kind) + { + case ObjectKind::CharacterLiteral: + case ObjectKind::ConstantLiteral: + case ObjectKind::MssgNameLiteral: + case ObjectKind::MssgLiteral: + case ObjectKind::ExtMssgLiteral: + case ObjectKind::Nil: + case ObjectKind::Class: + case ObjectKind::ClassSelf: + case ObjectKind::ConstructorSelf: + case ObjectKind::Param: + case ObjectKind::ParamReference: + case ObjectKind::ParamAddress: + case ObjectKind::ByRefParam: + case ObjectKind::ByRefParamAddress: + case ObjectKind::Local: + case ObjectKind::LocalReference: + case ObjectKind::RefLocal: + case ObjectKind::TempLocal: + case ObjectKind::SelfLocal: + case ObjectKind::SuperLocal: + case ObjectKind::ReadOnlySelfLocal: + case ObjectKind::LocalAddress: + case ObjectKind::TempLocalAddress: + case ObjectKind::ReadOnlyFieldAddress: + case ObjectKind::FieldAddress: + case ObjectKind::ReadOnlyField: + case ObjectKind::Field: + case ObjectKind::Outer: + case ObjectKind::OuterField: + case ObjectKind::OuterSelf: + case ObjectKind::Closure: + case ObjectKind::ClassConstant: + case ObjectKind::Constant: + case ObjectKind::ConstArray: + case ObjectKind::StaticField: + case ObjectKind::StaticConstField: + case ObjectKind::ClassStaticConstField: + case ObjectKind::LocalField: + return true; + default: + return isConstant(kind); + } + + return false; +} + inline bool areConstants(ArgumentsInfo& args) { for (size_t i = 0; i < args.count(); i++) { @@ -2935,6 +2985,11 @@ inline bool checkPreviousDeclaration(SyntaxNode node, ustr_t name) return false; } +inline bool isInterface(int flagMask) +{ + return flagMask == elInterface || flagMask == elWeakInterface; +} + bool Compiler :: generateClassField(ClassScope& scope, FieldAttributes& attrs, ustr_t name, int sizeHint, TypeInfo typeInfo, bool singleField) { @@ -2943,8 +2998,8 @@ bool Compiler :: generateClassField(ClassScope& scope, FieldAttributes& attrs, u bool readOnly = attrs.isReadonly; ref_t flags = scope.info.header.flags; - // a role cannot have fields - if (test(flags, elStateless)) + // a role / interface cannot have fields + if (test(flags, elStateless) || isInterface(flags & elDebugMask)) return false; SizeInfo sizeInfo = {}; @@ -4216,7 +4271,6 @@ ref_t Compiler :: resolvePrimitiveType(ModuleScopeBase& moduleScope, ustr_t ns, } } - void Compiler :: declareClassAttributes(ClassScope& scope, SyntaxNode node, ref_t& flags) { SyntaxNode current = node.firstChild(); @@ -4240,6 +4294,10 @@ void Compiler :: declareClassAttributes(ClassScope& scope, SyntaxNode node, ref_ // handle the abstract flag if (test(scope.info.header.flags, elAbstract)) { + // clear the interface flag by inheriting + if (isInterface(scope.info.header.flags & elDebugMask)) + scope.info.header.flags &= ~elDebugMask; + if (!test(flags, elAbstract)) { scope.abstractBasedMode = true; scope.info.header.flags &= ~elAbstract; @@ -5136,6 +5194,9 @@ TypeInfo Compiler :: resolveTypeScope(Scope& scope, SyntaxNode node, TypeAttribu case SyntaxKey::Type: elementRef = resolveStrongTypeAttribute(scope, current, declarationMode, false); break; + case SyntaxKey::TemplateType: + elementRef = resolveTypeAttribute(scope, current, attributes, declarationMode, allowRole).typeRef; + break; case SyntaxKey::identifier: case SyntaxKey::reference: elementRef = resolveTypeIdentifier(scope, current.identifier(), node.key, declarationMode, allowRole); @@ -6670,6 +6731,9 @@ ObjectInfo Compiler :: mapTerminal(Scope& scope, SyntaxNode node, TypeInfo decla break; } } + else if (node == SyntaxKey::Type && variableMode) { + return { ObjectKind::Class, {}, declaredTypeInfo.typeRef }; + } else retVal = defineTerminalInfo(scope, node, declaredTypeInfo, variableMode, forwardMode, refOp, mssgOp, memberMode, invalid, attrs); @@ -6726,7 +6790,6 @@ ObjectInfo Compiler :: mapObject(Scope& scope, SyntaxNode node, EAttrs mode) } return {}; } - if (terminalNode.nextNode() == SyntaxKey::TemplateArg && !EAttrs::test(mode.attrs, ExpressionAttribute::NewOp)) { scope.raiseError(errInvalidSyntax, node); } @@ -7344,7 +7407,7 @@ void Compiler :: compileMethodCode(BuildTreeWriter& writer, ClassScope* classSco } break; case SyntaxKey::Redirect: - retVal = compileRedirect(writer, codeScope, bodyNode); + retVal = compileRedirect(writer, codeScope, bodyNode, scope.info.outputRef); break; default: break; @@ -7538,7 +7601,7 @@ void Compiler :: compileMultidispatch(BuildTreeWriter& writer, CodeScope& scope, } } -ObjectInfo Compiler :: compileRedirect(BuildTreeWriter& writer, CodeScope& codeScope, SyntaxNode node) +ObjectInfo Compiler :: compileRedirect(BuildTreeWriter& writer, CodeScope& codeScope, SyntaxNode node, ref_t outputRef) { Expression expression(this, codeScope, writer); ArgumentsInfo arguments; @@ -7563,7 +7626,11 @@ ObjectInfo Compiler :: compileRedirect(BuildTreeWriter& writer, CodeScope& codeS _logic->setSignatureStacksafe(*codeScope.moduleScope, signRef, resolution.stackSafeAttr); ObjectInfo retVal = expression.compileMessageOperation({}, target, resolution, - signRef, arguments, EAttr::None, & updatedOuterArgs); + signRef, arguments, EAttr::None, &updatedOuterArgs); + + if (outputRef) { + expression.convertObject(node, expression.saveToTempLocal(retVal), outputRef, true, false); + } expression.scope.syncStack(); @@ -8412,6 +8479,31 @@ void Compiler :: initializeMethod(ClassScope& scope, MethodScope& methodScope, S } } +void Compiler :: compileProxyDispatcher(BuildTreeWriter& writer, CodeScope& codeScope, SyntaxNode node) +{ + SyntaxNode objNode = node.firstChild(SyntaxKey::DeclarationMask).firstChild(); + + // NOTE : the redirect target must be a simple variable + assert(objNode == SyntaxKey::Object); + + Expression expression(this, codeScope, writer); + + ObjectInfo target = expression.compile(objNode, 0, EAttr::None, nullptr); + switch (target.kind) { + // NOTE : the redirect operation must be done without creating a new frame + case ObjectKind::OuterSelf: + case ObjectKind::Outer: + writer.appendNode(BuildKey::Argument); + writer.appendNode(BuildKey::Field, target.reference); + break; + default: + codeScope.raiseError(errInvalidOperation, node); + break; + } + + writer.appendNode(BuildKey::RedirectOp); +} + void Compiler :: compileRedirectDispatcher(BuildTreeWriter& writer, MethodScope& scope, CodeScope& codeScope, SyntaxNode node, bool withGenerics) { @@ -8487,6 +8579,8 @@ inline bool hasVariadicFunctionDispatcher(Compiler::ClassScope* classScope, bool void Compiler :: compileDispatcherMethod(BuildTreeWriter& writer, MethodScope& scope, SyntaxNode node, bool withGenerics, bool withOpenArgGenerics) { + ClassScope* classScope = Scope::getScope(scope, Scope::ScopeLevel::Class); + CodeScope codeScope(&scope); beginMethod(writer, scope, node, BuildKey::Method, false); @@ -8499,7 +8593,10 @@ void Compiler :: compileDispatcherMethod(BuildTreeWriter& writer, MethodScope& s writer.appendNode(BuildKey::Import, current.arg.reference); break; case SyntaxKey::Redirect: - compileRedirectDispatcher(writer, scope, codeScope, current, withGenerics); + if (node.existChild(SyntaxKey::ProxyDispatcher)) { + compileProxyDispatcher(writer, codeScope, current); + } + else compileRedirectDispatcher(writer, scope, codeScope, current, withGenerics); break; default: scope.raiseError(errInvalidOperation, node); @@ -8509,8 +8606,6 @@ void Compiler :: compileDispatcherMethod(BuildTreeWriter& writer, MethodScope& s else { // if it is an implicit dispatcher if (withGenerics) { - ClassScope* classScope = Scope::getScope(scope, Scope::ScopeLevel::Class); - // !! temporally if (withOpenArgGenerics) scope.raiseError(errInvalidOperation, node); @@ -8529,8 +8624,6 @@ void Compiler :: compileDispatcherMethod(BuildTreeWriter& writer, MethodScope& s else if (withOpenArgGenerics) { Expression expression(this, codeScope, writer); - ClassScope* classScope = Scope::getScope(scope, Scope::ScopeLevel::Class); - ref_t mask = VARIADIC_MESSAGE; bool mixedDispatcher = false; bool variadicFunction = hasVariadicFunctionDispatcher(classScope, mixedDispatcher); @@ -8923,6 +9016,31 @@ void Compiler :: injectInterfaceDispatch(Scope& scope, SyntaxNode node, ref_t pa } } +bool Compiler :: isProxy(Scope& scope, SyntaxNode node) +{ + SyntaxNode current = node.firstChild(); + while (current != SyntaxKey::None) { + switch (current.key) { + case SyntaxKey::Method: + if (current.arg.reference == scope.moduleScope->buildins.dispatch_message) { + SyntaxNode exprNode = current.findChild(SyntaxKey::Redirect).firstChild(); + if (exprNode.firstChild() != SyntaxKey::Object || exprNode.firstChild().nextNode() != SyntaxKey::None) { + return false; + } + else current.appendChild(SyntaxKey::ProxyDispatcher); + } + else return false; + break; + default: + return false; + } + + current = current.nextNode(); + } + + return true; +} + void Compiler :: compileNestedClass(BuildTreeWriter& writer, ClassScope& scope, SyntaxNode node, ref_t parentRef) { NamespaceScope* ns = Scope::getScope(scope, Scope::ScopeLevel::Namespace); @@ -8967,6 +9085,9 @@ void Compiler :: compileNestedClass(BuildTreeWriter& writer, ClassScope& scope, generateClassDeclaration(scope, node, elNestedClass | elSealed); + // check if the nested class is a proxy class, and inject the required attribute + bool proxy = scope.info.header.parentRef == scope.moduleScope->buildins.superReference && isProxy(scope, node); + scope.save(); BuildNode buildNode = writer.CurrentNode(); @@ -8985,6 +9106,11 @@ void Compiler :: compileNestedClass(BuildTreeWriter& writer, ClassScope& scope, // NOTE : it should be called after the code compilation to take into consideration outer fields _logic->tweakClassFlags(*scope.moduleScope, scope.reference, scope.info, scope.isClassClass()); + // validate the proxy class and set the flag + if (proxy && !_logic->validateDispatcherType(scope.info)) { + scope.raiseError(errInvalidOperation, node); + } + // NOTE : compile once again only auto generated methods compileVMT(nestedWriter, scope, node, true, false); @@ -10241,7 +10367,7 @@ bool Compiler::Class :: isParentDeclared(SyntaxNode node) void Compiler::Class :: declare(SyntaxNode node) { bool extensionDeclaration = isExtensionDeclaration(node); - resolveClassPostfixes(node, extensionDeclaration/*, lxParent*/); + resolveClassPostfixes(node, extensionDeclaration); ref_t declaredFlags = 0; compiler->declareClassAttributes(scope, node, declaredFlags); @@ -10540,9 +10666,12 @@ ObjectInfo Compiler::Expression :: compileReturning(SyntaxNode node, EAttr mode, bool dynamicRequired = EAttrs::testAndExclude(mode, EAttr::DynamicObject); CodeScope* codeScope = Scope::getScope(scope, Scope::ScopeLevel::Code); - if (codeScope == nullptr) + if (codeScope == nullptr) { scope.raiseError(errInvalidOperation, node); + return {}; + } + if (compiler->_withDebugInfo) { writer->appendNode(BuildKey::OpenStatement); addBreakpoint(*writer, findObjectNode(node), BuildKey::Breakpoint); @@ -13134,7 +13263,11 @@ ObjectInfo Compiler::Expression :: compileBranchingOperation(SyntaxNode node, Ob writer->newNode(op, operatorId); writer->appendNode(BuildKey::Const, scope.moduleScope->branchingInfo.trueRef); - retVal = compileBranchingOperands(rnode, r2node, retValExpected, withoutDebugInfo); + if (retValExpected && argLen == 3 && (roperand.kind == ObjectKind::Object) && (roperand2.kind == ObjectKind::Object)) { + BuildNode opNode = writer->CurrentNode(); + retVal = compileTernaryOperands(rnode, r2node, opNode, withoutDebugInfo); + } + else retVal = compileBranchingOperands(rnode, r2node, retValExpected, withoutDebugInfo); } else { mssg_t message = 0; @@ -13177,8 +13310,8 @@ ObjectInfo Compiler::Expression :: compileBranchingOperands(SyntaxNode rnode, Sy ObjectInfo subRetCode = {}; bool oldWithRet = codeScope->withRetStatement; + EAttr mode = retValExpected ? EAttr::RetValExpected : EAttr::None; if (rnode == SyntaxKey::ClosureBlock || rnode == SyntaxKey::SwitchCode) { - EAttr mode = retValExpected ? EAttr::RetValExpected : EAttr::None; if (withoutDebugInfo) mode = mode | EAttr::NoDebugInfo; @@ -13186,7 +13319,7 @@ ObjectInfo Compiler::Expression :: compileBranchingOperands(SyntaxNode rnode, Sy subRetCode = compileSubCode(rnode.firstChild(), mode); } - else subRetCode = compile(rnode, 0, EAttr::None, nullptr); + else subRetCode = compile(rnode, 0, mode, nullptr); if (retValExpected) { writeObjectInfo(subRetCode); @@ -13202,7 +13335,6 @@ ObjectInfo Compiler::Expression :: compileBranchingOperands(SyntaxNode rnode, Sy bool withRet = codeScope->withRetStatement; codeScope->withRetStatement = false; - EAttr mode = retValExpected ? EAttr::RetValExpected : EAttr::None; if (withoutDebugInfo) mode = mode | EAttr::NoDebugInfo; @@ -13212,7 +13344,7 @@ ObjectInfo Compiler::Expression :: compileBranchingOperands(SyntaxNode rnode, Sy codeScope->withRetStatement = oldWithRet; } } - else elseSubRetCode = compile(r2node, 0, EAttr::None, nullptr); + else elseSubRetCode = compile(r2node, 0, mode, nullptr); if (retValExpected) { writeObjectInfo(elseSubRetCode, r2node); @@ -13234,6 +13366,41 @@ ObjectInfo Compiler::Expression :: compileBranchingOperands(SyntaxNode rnode, Sy return retVal; } +ObjectInfo Compiler::Expression :: compileTernaryOperands(SyntaxNode rnode, SyntaxNode r2node, BuildNode& opNode, bool withoutDebugInfo) +{ + CodeScope* codeScope = Scope::getScope(scope, Scope::ScopeLevel::Code); + + writer->newNode(BuildKey::Tape); + + bool oldWithRet = codeScope->withRetStatement; + ObjectInfo lexpr = compile(rnode, 0, EAttr::RetValExpected, nullptr); + + writeObjectInfo(lexpr); + + writer->closeNode(); + + TypeInfo retType = {}; + + // NOTE : it should immediately follow if-block + writer->newNode(BuildKey::Tape); + ObjectInfo rexpr = compile(r2node, 0, EAttr::RetValExpected, nullptr); + + writeObjectInfo(rexpr, r2node); + + if (lexpr.typeInfo == rexpr.typeInfo) + retType = rexpr.typeInfo; + + writer->closeNode(); + + if (isSingleObject(lexpr.kind) && isSingleObject(rexpr.kind)) { + opNode.setKey(BuildKey::TernaryOp); + } + + writer->closeNode(); + + return { ObjectKind::Object, retType, 0 }; +} + ObjectInfo Compiler::Expression :: compileMessageOperationR(ObjectInfo target, SyntaxNode messageNode, bool propertyMode) { ArgumentsInfo arguments; diff --git a/elenasrc3/elc/compiler.h b/elenasrc3/elc/compiler.h index 7817a77b2e..40db9b5e81 100644 --- a/elenasrc3/elc/compiler.h +++ b/elenasrc3/elc/compiler.h @@ -1258,6 +1258,7 @@ namespace elena_lang ObjectInfo saveToTempLocal(ObjectInfo object); ObjectInfo compileBranchingOperands(SyntaxNode rnode, SyntaxNode r2node, bool retValExpected, bool withoutDebugInfo); + ObjectInfo compileTernaryOperands(SyntaxNode rnode, SyntaxNode r2node, BuildNode& opNode, bool withoutDebugInfo); ObjectInfo compileNativeConversion(SyntaxNode node, ObjectInfo source, ref_t operationKey); @@ -1410,6 +1411,8 @@ namespace elena_lang static bool isClassClassOperation(Scope& scope, ObjectInfo target); + static bool isProxy(Scope& scope, SyntaxNode node); + ref_t declareMultiType(Scope& scope, SyntaxNode& node, ref_t elementRef); void declareClassAttributes(ClassScope& scope, SyntaxNode node, ref_t& fldeclaredFlagsags); @@ -1576,9 +1579,10 @@ namespace elena_lang void compileRedirectDispatcher(BuildTreeWriter& writer, MethodScope& scope, CodeScope& codeScope, SyntaxNode node, bool withGenerics); + void compileProxyDispatcher(BuildTreeWriter& writer, CodeScope& codeScope, SyntaxNode node); ObjectInfo compileResendCode(BuildTreeWriter& writer, CodeScope& codeScope, ObjectInfo source, SyntaxNode node); - ObjectInfo compileRedirect(BuildTreeWriter& writer, CodeScope& codeScope, SyntaxNode node); + ObjectInfo compileRedirect(BuildTreeWriter& writer, CodeScope& codeScope, SyntaxNode node, ref_t outputRef); ObjectInfo compileCode(BuildTreeWriter& writer, CodeScope& codeScope, SyntaxNode node, bool closureMode, bool noDebugInfoMode = false); void beginMethod(BuildTreeWriter& writer, MethodScope& scope, SyntaxNode node, BuildKey scopeKey, diff --git a/elenasrc3/elc/compilerlogic.cpp b/elenasrc3/elc/compilerlogic.cpp index 2bc3f7071a..3b181f50fa 100644 --- a/elenasrc3/elc/compilerlogic.cpp +++ b/elenasrc3/elc/compilerlogic.cpp @@ -809,8 +809,12 @@ bool CompilerLogic :: validateClassAttribute(ref_t attribute, ref_t& flags, Visi case V_SINGLETON: flags |= elRole | elSealed | elStateless; break; - case V_LIMITED: - flags |= (elClosed | elAbstract | elNoCustomDispatcher); + case V_INTERFACE: + if (!(flags & elDebugMask)) { + flags |= (elClosed | elAbstract | elNoCustomDispatcher); + flags |= elInterface; + } + else return false; break; case V_ABSTRACT: flags |= elAbstract; @@ -1474,6 +1478,22 @@ void CompilerLogic :: tweakClassFlags(ModuleScopeBase& scope, ref_t classRef, Cl break; } } + else if ((info.header.flags & elDebugMask) == elInterface) { + // verify if it is a weak interface (an interface without output type specified) + bool isWeakInterface = true; + for (auto it = info.methods.start(); !it.eof(); ++it) { + auto methodInfo = *it; + + if (!methodInfo.inherited && methodInfo.outputRef && methodInfo.outputRef != classRef) { + isWeakInterface = false; + break; + } + } + if (isWeakInterface) { + info.header.flags &= ~elDebugMask; + info.header.flags |= elWeakInterface; + } + } } void CompilerLogic :: tweakPrimitiveClassFlags(ClassInfo& info, ref_t classRef) @@ -2946,4 +2966,18 @@ pos_t CompilerLogic :: definePadding(ModuleScopeBase& scope, pos_t offset, pos_t default: return align(offset, scope.ptrSize) - offset; } -} \ No newline at end of file +} + +bool CompilerLogic :: validateDispatcherType(ClassInfo& classInfo) +{ + bool isProxy = classInfo.fields.count() == 1 && test(classInfo.header.flags, elWithCustomDispatcher | elNestedClass | elSealed) + && !testany(classInfo.header.flags, elWithGenerics | elWithVariadics | elWithYieldable | elStructure); + + if (isProxy && (classInfo.header.flags & elDebugMask) == 0) { + classInfo.header.flags |= elProxy; + + return true; + } + + return false; +} diff --git a/elenasrc3/elc/compilerlogic.h b/elenasrc3/elc/compilerlogic.h index 860c3ef3a3..a6344a5156 100644 --- a/elenasrc3/elc/compilerlogic.h +++ b/elenasrc3/elc/compilerlogic.h @@ -203,6 +203,8 @@ namespace elena_lang bool isNeedVerification(ClassInfo& info, VirtualMethodList& implicitMultimethods); bool verifyMultimethod(ModuleScopeBase& scope, ClassInfo& info, mssg_t message); + bool validateDispatcherType(ClassInfo& classInfo); + mssg_t resolveMultimethod(ModuleScopeBase& scope, mssg_t weakMessage, ref_t targetRef, ref_t implicitSignatureRef, int& stackSafeAttr, bool selfCall); diff --git a/elenasrc3/elc/derivation.cpp b/elenasrc3/elc/derivation.cpp index 4c3459028d..3c66371ab3 100644 --- a/elenasrc3/elc/derivation.cpp +++ b/elenasrc3/elc/derivation.cpp @@ -365,14 +365,28 @@ void SyntaxTreeBuilder :: flushTemplateType(SyntaxTreeWriter& writer, Scope& sco } } -void SyntaxTreeBuilder :: flushArrayType(SyntaxTreeWriter& writer, Scope& scope, SyntaxNode node, int nestLevel) +void SyntaxTreeBuilder :: flushArrayType(SyntaxTreeWriter& writer, Scope& scope, SyntaxNode node, bool exprMode, int nestLevel) { SyntaxNode current = node.firstChild(); ref_t attributeCategory = V_CATEGORY_MAX; while (current != SyntaxKey::None) { if (current == SyntaxKey::ArrayType) { - flushArrayType(writer, scope, current, nestLevel + 1); + flushArrayType(writer, scope, current, exprMode, nestLevel + 1); + } + else if (current == SyntaxKey::TemplateType) { + for (int i = 0; i < nestLevel; i++) + writer.newNode(SyntaxKey::ArrayType); + + if (exprMode) { + writer.newNode(SyntaxKey::TemplateType); + flushTemplateType(writer, scope, current); + writer.closeNode(); + } + else flushTemplateType(writer, scope, current, false); + + for (int i = 0; i < nestLevel; i++) + writer.closeNode(); } else { bool allowType = current.nextNode() == SyntaxKey::None; @@ -451,11 +465,11 @@ void SyntaxTreeBuilder :: flushObject(SyntaxTreeWriter& writer, Scope& scope, Sy if (current.nextNode() == SyntaxKey::identifier) { SyntaxNode identNode = node.lastChild(SyntaxKey::TerminalMask); - flushArrayType(writer, scope, current); + flushArrayType(writer, scope, current, true); flushNode(writer, scope, identNode); } - else flushArrayType(writer, scope, current); + else flushArrayType(writer, scope, current, true); } else if (current == SyntaxKey::Expression) { //HOTFIX : expression cannot be inside an object @@ -746,7 +760,7 @@ void SyntaxTreeBuilder :: flushDescriptor(SyntaxTreeWriter& writer, Scope& scope bool allowType = nameNode.key == SyntaxKey::None || nextNode == nameNode; if (current == SyntaxKey::ArrayType) { //flushAttribute(writer, scope, current, attributeCategory, allowType, true); - flushArrayType(writer, scope, current); + flushArrayType(writer, scope, current, false); } else if (current == SyntaxKey::TemplateType) { flushTemplateType(writer, scope, current, false); @@ -774,8 +788,6 @@ void SyntaxTreeBuilder :: flushDescriptor(SyntaxTreeWriter& writer, Scope& scope writer.newNode(key, attrRef); flushNode(writer, scope, current); writer.closeNode(); - - } else flushNode(writer, scope, current); } @@ -1608,7 +1620,7 @@ SyntaxTreeBuilder::ScopeType SyntaxTreeBuilder :: defineTemplateType(SyntaxNode void SyntaxTreeBuilder :: flushDeclaration(SyntaxTreeWriter& writer, SyntaxNode node) { - Scope scope; + Scope scope(_noDebugInfo); writer.newNode(node.key); diff --git a/elenasrc3/elc/derivation.h b/elenasrc3/elc/derivation.h index 318bea59c6..c07811c7d1 100644 --- a/elenasrc3/elc/derivation.h +++ b/elenasrc3/elc/derivation.h @@ -99,11 +99,15 @@ namespace elena_lang } Scope() + : Scope(false) + { + } + Scope(bool ignoreTerminalInfo) : arguments(0), parameters(0) { - type = ScopeType::Unknown; - ignoreTerminalInfo = false; - nestedLevel = 0; + this->type = ScopeType::Unknown; + this->ignoreTerminalInfo = ignoreTerminalInfo; + this->nestedLevel = 0; } }; @@ -117,6 +121,8 @@ namespace elena_lang ModuleScopeBase* _moduleScope; TemplateProssesorBase* _templateProcessor; + bool _noDebugInfo; + ScopeType defineTemplateType(SyntaxNode node); ref_t mapAttribute(SyntaxNode node, bool allowType, ref_t& previusCategory); @@ -141,7 +147,7 @@ namespace elena_lang void flushTemplateArg(SyntaxTreeWriter& writer, Scope& scope, SyntaxNode node, bool allowType); void flushTemplageExpression(SyntaxTreeWriter& writer, Scope& scope, SyntaxNode node, SyntaxKey type, bool allowType); void flushTemplateType(SyntaxTreeWriter& writer, Scope& scope, SyntaxNode node, bool exprMode = true); - void flushArrayType(SyntaxTreeWriter& writer, Scope& scope, SyntaxNode node, int nestLevel = 1); + void flushArrayType(SyntaxTreeWriter& writer, Scope& scope, SyntaxNode node, bool exprMode, int nestLevel = 1); void flushMessage(SyntaxTreeWriter& writer, Scope& scope, SyntaxNode node); void flushResend(SyntaxTreeWriter& writer, Scope& scope, SyntaxNode node); void flushObject(SyntaxTreeWriter& writer, Scope& scope, SyntaxNode node); @@ -220,6 +226,17 @@ namespace elena_lang _writer.clear(); _writer.newNode(SyntaxKey::Root); + clear(); + } + SyntaxTreeBuilder(SyntaxNode rootNode, ErrorProcessor* errorProcessor, + ModuleScopeBase* moduleScope, TemplateProssesorBase* templateProcessor, bool noDebugInfo) + : _writer(rootNode), _cacheWriter(_cache) + { + _errorProcessor = errorProcessor; + _moduleScope = moduleScope; + _templateProcessor = templateProcessor; + _noDebugInfo = noDebugInfo; + clear(); } }; diff --git a/elenasrc3/elena-tests/bt_optimization.cpp b/elenasrc3/elena-tests/bt_optimization.cpp index 1f3dbf645b..e557ceae13 100644 --- a/elenasrc3/elena-tests/bt_optimization.cpp +++ b/elenasrc3/elena-tests/bt_optimization.cpp @@ -9,22 +9,10 @@ #include "serializer.h" #include "bcwriter.h" -#include - using namespace elena_lang; constexpr auto BT_RULES_FILE = "bt_rules60.dat"; -inline void getAppPath(PathString& appPath) -{ - wchar_t path[MAX_PATH + 1]; - - ::GetModuleFileName(nullptr, path, MAX_PATH); - - appPath.copySubPath(path, false); - appPath.lower(); -} - // --- BTOptimization1 --- constexpr auto Declaration1_1 = "namespace (class ( nameattr (identifier \"Object\" ())) class (attribute -2147467263 () attribute -2147475455 () attribute -2147479550 () nameattr (identifier \"Struct\" ()) field (attribute -2147475454 () attribute -2147481597 () nameattr (identifier \"_value\" ())dimension (integer \"4\" ()))) class ( attribute -2147471359 () nameattr (identifier \"TestReference\" ()) field (attribute -2147475454 () type (identifier \"Struct\" ()) nameattr (identifier \"_value\" ())) ) class (attribute -2147467263 ()attribute -2147479546 () nameattr (identifier \"Tester\" ()) method (type (identifier \"Struct\" ()) nameattr (identifier \"getValue\" ())code ())))"; @@ -384,83 +372,6 @@ void PrimitiveStructAlignment:: SetUp() expectedSize = 2; } -// --- Scenario1Test --- - -void Scenario1Test:: LoadDeclarationScenario(ustr_t common, ustr_t descr1, ustr_t descr2) -{ - IdentifierString descr(descr1, " ", descr2); - - DynamicUStr syntax(common); - - size_t index = common.findStr("$1"); - if (index != NOTFOUND_POS) { - syntax.cut(index, 2); - syntax.insert(*descr, index); - } - - SyntaxTreeSerializer::load(syntax.str(), declarationNode); -} - -void Scenario1Test :: LoadDeclarationScenario(ustr_t common, ustr_t descr1, ustr_t descr2, ustr_t descr3) -{ - DynamicUStr syntax(common); - - size_t index = common.findStr("$1"); - if (index != NOTFOUND_POS) { - syntax.cut(index, 2); - - syntax.insert(descr3, index); - syntax.insert(" ", index); - syntax.insert(descr2, index); - syntax.insert(" ", index); - syntax.insert(descr1, index); - } - - SyntaxTreeSerializer::load(syntax.str(), declarationNode); -} - -void Scenario1Test :: LoadDeclarationScenario(ustr_t common, ustr_t descr1, ustr_t descr2, ustr_t descr3, ustr_t descr4) -{ - DynamicUStr syntax(common); - - size_t index = common.findStr("$1"); - if (index != NOTFOUND_POS) { - syntax.cut(index, 2); - - syntax.insert(descr4, index); - syntax.insert(" ", index); - syntax.insert(descr3, index); - syntax.insert(" ", index); - syntax.insert(descr2, index); - syntax.insert(" ", index); - syntax.insert(descr1, index); - } - - SyntaxTreeSerializer::load(syntax.str(), declarationNode); -} - -void Scenario1Test :: LoadDeclarationScenario(ustr_t common, ustr_t descr1, ustr_t descr2, ustr_t descr3, ustr_t descr4, ustr_t descr5) -{ - DynamicUStr syntax(common); - - size_t index = common.findStr("$1"); - if (index != NOTFOUND_POS) { - syntax.cut(index, 2); - - syntax.insert(descr5, index); - syntax.insert(" ", index); - syntax.insert(descr4, index); - syntax.insert(" ", index); - syntax.insert(descr3, index); - syntax.insert(" ", index); - syntax.insert(descr2, index); - syntax.insert(" ", index); - syntax.insert(descr1, index); - } - - SyntaxTreeSerializer::load(syntax.str(), declarationNode); -} - // --- DispatchTest --- void DispatchTest :: SetUp() diff --git a/elenasrc3/elena-tests/bt_optimization.h b/elenasrc3/elena-tests/bt_optimization.h index b4e52db6ce..aa68e87373 100644 --- a/elenasrc3/elena-tests/bt_optimization.h +++ b/elenasrc3/elena-tests/bt_optimization.h @@ -8,7 +8,6 @@ #ifndef BTOPTIMIZATION_H #define BTOPTIMIZATION_H -#include "pch.h" #include "tests_common.h" namespace elena_lang @@ -63,22 +62,12 @@ namespace elena_lang } }; - class Scenario1Test : public testing::Test + class Scenario1Test : public BaseFixture { protected: - SyntaxTree syntaxTree; BuildTree buildTree; - SyntaxNode declarationNode; - BuildNode controlOutputNode; - - CompilerEnvironment env; - - void LoadDeclarationScenario(ustr_t common, ustr_t descr1, ustr_t descr2); - void LoadDeclarationScenario(ustr_t common, ustr_t descr1, ustr_t descr2, ustr_t descr3); - void LoadDeclarationScenario(ustr_t common, ustr_t descr1, ustr_t descr2, ustr_t descr3, ustr_t descr4); - void LoadDeclarationScenario(ustr_t common, ustr_t descr1, ustr_t descr2, ustr_t descr3, ustr_t descr4, ustr_t descr5); }; class DispatchTest : public Scenario1Test diff --git a/elenasrc3/elena-tests/declaration.cpp b/elenasrc3/elena-tests/declaration.cpp new file mode 100644 index 0000000000..a5e9a0f1cd --- /dev/null +++ b/elenasrc3/elena-tests/declaration.cpp @@ -0,0 +1,95 @@ +//--------------------------------------------------------------------------- +// E L E N A P r o j e c t: ELENA Compiler +// +// This header contains ELENA Test Optimization Fixture implementation +// (C)2024, by Aleksey Rakov +//--------------------------------------------------------------------------- + +#include "declaration.h" +#include "serializer.h" +#include "bcwriter.h" + +#include "parser.h" +#include "cliconst.h" +#include "derivation.h" + +using namespace elena_lang; + +constexpr auto Field_TemplateBasedArray = "namespace (class (nameattr (identifier \"A\" ())field (array_type (template_type (identifier \"VarTuple\" () template_arg (type(identifier \"object\" ())) template_arg (type(identifier \"object\" ()))))nameattr (identifier \"_array\" ())))"; +constexpr auto New_TemplateBasedArray = "namespace (class (attribute -2147467263 (identifier \"public\" ())nameattr (identifier \"program\" ())attribute -2147479546 ()method (attribute -2147479540 ()code (expression (assign_operation (object (attribute -2147479539 (identifier \"var\" ())identifier \"array\" ())expression (message_operation (object (array_type (template_type (attribute -2147479534 (identifier \"new\" ())identifier \"VarTuple\" ()template_arg (type (identifier \"object\" ()))template_arg (type (identifier \"object\" ())))))expression (object (integer \"10\" ()))))))EOP (eop \"}\" ())))))"; + +constexpr auto Src_Field_TemplateBasedArray = "A { VarTuple[] _array; }"; +constexpr auto Src_New_TemplateBasedArray = "public program() { var array := new VarTuple[](10); }"; + +// --- DeclarationFixture --- + +void DeclarationFixture :: SetUp() +{ + SyntaxTreeWriter writer(syntaxTree); + writer.appendNode(SyntaxKey::Root); + + declarationNode = syntaxTree.readRoot().appendChild(SyntaxKey::Idle, 1); + sourceNode = syntaxTree.readRoot().appendChild(SyntaxKey::Idle, 1); +} + +void DeclarationFixture :: runTest() +{ + // Arrange + TerminalMap terminals( + SyntaxTree::toParseKey(SyntaxKey::eof), + SyntaxTree::toParseKey(SyntaxKey::identifier), + SyntaxTree::toParseKey(SyntaxKey::reference), + SyntaxTree::toParseKey(SyntaxKey::globalreference), + SyntaxTree::toParseKey(SyntaxKey::string), + SyntaxTree::toParseKey(SyntaxKey::character), + SyntaxTree::toParseKey(SyntaxKey::wide), + SyntaxTree::toParseKey(SyntaxKey::integer), + SyntaxTree::toParseKey(SyntaxKey::hexinteger), + SyntaxTree::toParseKey(SyntaxKey::longinteger), + SyntaxTree::toParseKey(SyntaxKey::real), + SyntaxTree::toParseKey(SyntaxKey::constant)); + + PathString appPath; + getAppPath(appPath); + StringTextReader reader(_src); + + PathString syntaxPath(*appPath, SYNTAX_FILE); + FileReader syntax(*syntaxPath, FileRBMode, FileEncoding::Raw, false); + + auto parser = new Parser(&syntax, terminals, nullptr); + + ModuleScopeBase* moduleScope = env.createModuleScope(true, false, true); + + SyntaxTreeBuilder builder(sourceNode, nullptr, moduleScope, nullptr, true); + + // Act + builder.newNode(SyntaxTree::toParseKey(SyntaxKey::Namespace)); + parser->parse(&reader, &builder); + builder.closeNode(); + + // Assess + bool matched = SyntaxTree::compare(sourceNode, declarationNode, true); + EXPECT_TRUE(matched); +} + +// --- TemplateArrayFixture --- + +void TemplateArrayFixture :: SetUp() +{ + DeclarationFixture::SetUp(); + + LoadDeclarationScenario("$1", Field_TemplateBasedArray); + + _src = Src_Field_TemplateBasedArray; +} + +// --- NewTemplateArrayFixture --- + +void NewTemplateArrayFixture :: SetUp() +{ + DeclarationFixture::SetUp(); + + LoadDeclarationScenario("$1", New_TemplateBasedArray); + + _src = Src_New_TemplateBasedArray; +} \ No newline at end of file diff --git a/elenasrc3/elena-tests/declaration.h b/elenasrc3/elena-tests/declaration.h new file mode 100644 index 0000000000..1dcb09eb94 --- /dev/null +++ b/elenasrc3/elena-tests/declaration.h @@ -0,0 +1,47 @@ +//--------------------------------------------------------------------------- +// E L E N A P r o j e c t: ELENA Compiler +// +// This header contains ELENA Test Declaration Fixture declarations +// (C)2024, by Aleksey Rakov +//--------------------------------------------------------------------------- + +#ifndef TEST_DECLARATION_H +#define TEST_DECLARATION_H + +#include "pch.h" +#include "tests_common.h" + +namespace elena_lang +{ + // --- DeclarationFixture --- + class DeclarationFixture : public BaseFixture + { + protected: + ustr_t _src; + + CompilerEnvironment env; + + SyntaxNode sourceNode; + + void SetUp() override; + + public: + void runTest(); + }; + + // --- TemplateArrayFixture --- + class TemplateArrayFixture : public DeclarationFixture + { + protected: + void SetUp() override; + }; + + // --- NewTemplateArrayFixture --- + class NewTemplateArrayFixture : public DeclarationFixture + { + protected: + void SetUp() override; + }; +} + +#endif diff --git a/elenasrc3/elena-tests/declare_tests.cpp b/elenasrc3/elena-tests/declare_tests.cpp new file mode 100644 index 0000000000..b36c8e4939 --- /dev/null +++ b/elenasrc3/elena-tests/declare_tests.cpp @@ -0,0 +1,17 @@ +#include "pch.h" +// ------------------------------------------------ +#include "declaration.h" + +#include "compiler.h" + +using namespace elena_lang; + +TEST_F(TemplateArrayFixture, DeclarationTest) +{ + runTest(); +} + +TEST_F(NewTemplateArrayFixture, DeclarationTest) +{ + runTest(); +} diff --git a/elenasrc3/elena-tests/elena-tests.vcxproj b/elenasrc3/elena-tests/elena-tests.vcxproj index d0dc84bb48..e63128ac3c 100644 --- a/elenasrc3/elena-tests/elena-tests.vcxproj +++ b/elenasrc3/elena-tests/elena-tests.vcxproj @@ -125,7 +125,12 @@ + + + + + @@ -137,15 +142,21 @@ + + + + + + diff --git a/elenasrc3/elena-tests/tests_common.cpp b/elenasrc3/elena-tests/tests_common.cpp index 94e163d87e..6110704cfd 100644 --- a/elenasrc3/elena-tests/tests_common.cpp +++ b/elenasrc3/elena-tests/tests_common.cpp @@ -5,12 +5,15 @@ // (C)2024, by Aleksey Rakov //--------------------------------------------------------------------------- - #include "pch.h" // -------------------------------------------------------------------------- #include "tests_common.h" #include "module.h" +#include "serializer.h" + +#include + using namespace elena_lang; #ifdef _M_IX86 @@ -230,6 +233,9 @@ ModuleScopeBase* CompilerEnvironment :: createModuleScope(bool tapeOptMode, bool if (withAttributes) { scope->attributes.add("dispatch", V_DISPATCHER); + scope->attributes.add("public", V_PUBLIC); + scope->attributes.add("var", V_VARIABLE); + scope->attributes.add("new", V_NEWOP); } return scope; @@ -258,4 +264,105 @@ Compiler* CompilerEnvironment :: createCompiler() compiler->setDebugMode(false); return compiler; -} \ No newline at end of file +} + +// --- BaseFixture --- + +void BaseFixture :: LoadDeclarationScenario(ustr_t common, ustr_t descr) +{ + DynamicUStr syntax(common); + + size_t index = common.findStr("$1"); + if (index != NOTFOUND_POS) { + syntax.cut(index, 2); + syntax.insert(descr, index); + } + + SyntaxTreeSerializer::load(syntax.str(), declarationNode); +} + +void BaseFixture :: LoadDeclarationScenario(ustr_t common, ustr_t descr1, ustr_t descr2) +{ + IdentifierString descr(descr1, " ", descr2); + + DynamicUStr syntax(common); + + size_t index = common.findStr("$1"); + if (index != NOTFOUND_POS) { + syntax.cut(index, 2); + syntax.insert(*descr, index); + } + + SyntaxTreeSerializer::load(syntax.str(), declarationNode); +} + +void BaseFixture :: LoadDeclarationScenario(ustr_t common, ustr_t descr1, ustr_t descr2, ustr_t descr3) +{ + DynamicUStr syntax(common); + + size_t index = common.findStr("$1"); + if (index != NOTFOUND_POS) { + syntax.cut(index, 2); + + syntax.insert(descr3, index); + syntax.insert(" ", index); + syntax.insert(descr2, index); + syntax.insert(" ", index); + syntax.insert(descr1, index); + } + + SyntaxTreeSerializer::load(syntax.str(), declarationNode); +} + +void BaseFixture :: LoadDeclarationScenario(ustr_t common, ustr_t descr1, ustr_t descr2, ustr_t descr3, ustr_t descr4) +{ + DynamicUStr syntax(common); + + size_t index = common.findStr("$1"); + if (index != NOTFOUND_POS) { + syntax.cut(index, 2); + + syntax.insert(descr4, index); + syntax.insert(" ", index); + syntax.insert(descr3, index); + syntax.insert(" ", index); + syntax.insert(descr2, index); + syntax.insert(" ", index); + syntax.insert(descr1, index); + } + + SyntaxTreeSerializer::load(syntax.str(), declarationNode); +} + +void BaseFixture :: LoadDeclarationScenario(ustr_t common, ustr_t descr1, ustr_t descr2, ustr_t descr3, ustr_t descr4, ustr_t descr5) +{ + DynamicUStr syntax(common); + + size_t index = common.findStr("$1"); + if (index != NOTFOUND_POS) { + syntax.cut(index, 2); + + syntax.insert(descr5, index); + syntax.insert(" ", index); + syntax.insert(descr4, index); + syntax.insert(" ", index); + syntax.insert(descr3, index); + syntax.insert(" ", index); + syntax.insert(descr2, index); + syntax.insert(" ", index); + syntax.insert(descr1, index); + } + + SyntaxTreeSerializer::load(syntax.str(), declarationNode); +} + +void elena_lang::getAppPath(PathString& appPath) +{ + wchar_t path[MAX_PATH + 1]; + + ::GetModuleFileName(nullptr, path, MAX_PATH); + + appPath.copySubPath(path, false); + appPath.lower(); +} + diff --git a/elenasrc3/elena-tests/tests_common.h b/elenasrc3/elena-tests/tests_common.h index 6214ace964..8c147fb5b1 100644 --- a/elenasrc3/elena-tests/tests_common.h +++ b/elenasrc3/elena-tests/tests_common.h @@ -8,6 +8,7 @@ #ifndef TESTS_COMMON_H #define TESTS_COMMON_H +#include "pch.h" #include "compiler.h" namespace elena_lang @@ -179,6 +180,26 @@ namespace elena_lang CompilerEnvironment(); }; + + // --- BaseFixture --- + class BaseFixture : public testing::Test + { + protected: + SyntaxTree syntaxTree; + + SyntaxNode declarationNode; + + void LoadDeclarationScenario(ustr_t common, ustr_t descr); + void LoadDeclarationScenario(ustr_t common, ustr_t descr1, ustr_t descr2); + void LoadDeclarationScenario(ustr_t common, ustr_t descr1, ustr_t descr2, ustr_t descr3); + void LoadDeclarationScenario(ustr_t common, ustr_t descr1, ustr_t descr2, ustr_t descr3, ustr_t descr4); + void LoadDeclarationScenario(ustr_t common, ustr_t descr1, ustr_t descr2, ustr_t descr3, ustr_t descr4, ustr_t descr5); + + public: + CompilerEnvironment env; + }; + + void getAppPath(PathString& appPath); } #endif // TESTS_COMMON_H \ No newline at end of file diff --git a/elenasrc3/elenart/elenartmachine.cpp b/elenasrc3/elenart/elenartmachine.cpp index 8820b121ae..13d4173b36 100644 --- a/elenasrc3/elenart/elenartmachine.cpp +++ b/elenasrc3/elenart/elenartmachine.cpp @@ -130,6 +130,27 @@ void ELENARTMachine :: loadSubjectName(IdentifierString& actionName, ref_t subje rtmanager.loadSubjectName(actionName, subjectRef); } +int ELENARTMachine :: loadSignature(mssg_t message, addr_t* output, pos_t maximalCount) +{ + ImageSection msection(_mdata, 0x1000000); + RTManager rtmanager(&msection, nullptr); + + ref_t actionRef, flags; + pos_t argCount = 0; + decodeMessage(message, actionRef, argCount, flags); + + if (testany(message, FUNCTION_MESSAGE | CONVERSION_MESSAGE)) { + argCount = _min(maximalCount, argCount); + } + else argCount = _min(maximalCount, argCount - 1); + + if (rtmanager.loadSignature(actionRef, maximalCount, output)) { + return argCount; + } + + return 0; +} + size_t ELENARTMachine :: loadMessageName(mssg_t message, char* buffer, size_t length) { ref_t actionRef, flags; @@ -353,4 +374,3 @@ size_t ELENARTMachine :: loadClassMessages(void* classPtr, mssg_t* output, size_ return SystemRoutineProvider::LoadMessages(&msection, classPtr, output, skip, maxLength, false); } - diff --git a/elenasrc3/elenart/elenartmachine.h b/elenasrc3/elenart/elenartmachine.h index 50c27a0a81..2e048c6498 100644 --- a/elenasrc3/elenart/elenartmachine.h +++ b/elenasrc3/elenart/elenartmachine.h @@ -63,6 +63,8 @@ namespace elena_lang int loadExtensionDispatcher(const char* moduleList, mssg_t message, void* output); + int loadSignature(mssg_t message, addr_t* output, pos_t maximalCount); + void initRandomSeed(SeedStruct& seed) { __routineProvider.InitRandomSeed(seed, __routineProvider.GenerateSeed()); diff --git a/elenasrc3/elenart/rtcommon.h b/elenasrc3/elenart/rtcommon.h index edc2c08769..80506502d3 100644 --- a/elenasrc3/elenart/rtcommon.h +++ b/elenasrc3/elenart/rtcommon.h @@ -14,7 +14,7 @@ namespace elena_lang { -#define ELENART_REVISION_NUMBER 0x0026 +#define ELENART_REVISION_NUMBER 0x0005 } diff --git a/elenasrc3/elenart/windows/dllmain.cpp b/elenasrc3/elenart/windows/dllmain.cpp index dba9fc5005..aeb367e0d6 100644 --- a/elenasrc3/elenart/windows/dllmain.cpp +++ b/elenasrc3/elenart/windows/dllmain.cpp @@ -252,6 +252,26 @@ EXTERN_DLL_EXPORT void WaitForSignalsGCLA(size_t count, void* handles) SystemRoutineProvider::GCWaitForSignals(count, handles); } +/// +/// Inject an interface VMT into a dynamic proxy class +/// +/// a reference to dynamically created VMT +EXTERN_DLL_EXPORT void* InjectProxyTypeLA(void* target, void* type, int staticLength, int nameIndex) +{ + return (void*)machine->injectType(systemEnv, target, type, staticLength, nameIndex); +} + +/// +/// Returns the signature list +/// +/// A strong-typed message +/// Signature tyoe +/// the total length +EXTERN_DLL_EXPORT int LoadSignatureLA(mssg_t message, addr_t* output, int maximalLength) +{ + return machine->loadSignature(message, output, maximalLength); +} + BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved diff --git a/elenasrc3/elenavm/vmcommon.h b/elenasrc3/elenavm/vmcommon.h index 6956f30bd3..3675d99d32 100644 --- a/elenasrc3/elenavm/vmcommon.h +++ b/elenasrc3/elenavm/vmcommon.h @@ -9,7 +9,7 @@ #ifndef VMCOMMON_H #define VMCOMMON_H -#define ELENAVM_REVISION_NUMBER 0x0025 +#define ELENAVM_REVISION_NUMBER 0x0001 namespace elena_lang { diff --git a/elenasrc3/engine/bcwriter.cpp b/elenasrc3/engine/bcwriter.cpp index 2032d0a26c..9ab128e124 100644 --- a/elenasrc3/engine/bcwriter.cpp +++ b/elenasrc3/engine/bcwriter.cpp @@ -2852,6 +2852,26 @@ void ByteCodeWriter :: saveBranching(CommandTape& tape, BuildNode node, TapeScop } } +void ByteCodeWriter :: saveTernaryOp(CommandTape& tape, BuildNode node, TapeScope& tapeScope, + ReferenceMap& paths, bool tapeOptMode) +{ + BuildNode lnodeNode = node.findChild(BuildKey::Tape); + BuildNode rnodeNode = lnodeNode.nextNode(); + + tape.write(ByteCode::StoreSI, 1); + + saveTape(tape, lnodeNode, tapeScope, paths, tapeOptMode); + tape.write(ByteCode::StoreSI); + + saveTape(tape, rnodeNode, tapeScope, paths, tapeOptMode); + tape.write(ByteCode::SwapSI, 1); + + tape.write(ByteCode::CmpR, node.findChild(BuildKey::Const).arg.reference | mskVMTRef); + + tape.write(ByteCode::PeekSI, 1); + tape.write(ByteCode::XPeekEq); +} + void ByteCodeWriter :: saveNativeBranching(CommandTape& tape, BuildNode node, TapeScope& tapeScope, ReferenceMap& paths, bool tapeOptMode, bool loopMode) { @@ -3455,6 +3475,9 @@ void ByteCodeWriter :: saveTape(CommandTape& tape, BuildNode node, TapeScope& ta case BuildKey::YieldDispatch: saveYieldDispatch(tape, current, tapeScope, paths, tapeOptMode); break; + case BuildKey::TernaryOp: + saveTernaryOp(tape, current, tapeScope, paths, tapeOptMode); + break; case BuildKey::Path: case BuildKey::InplaceCall: // ignore special nodes @@ -3619,7 +3642,7 @@ void ByteCodeWriter :: saveProcedure(BuildNode node, Scope& scope, bool classMod endDebugInfo(scope); } -void ByteCodeWriter :: saveVMT(BuildNode node, Scope& scope, pos_t sourcePathRef, +void ByteCodeWriter :: saveVMT(ClassInfo& info, BuildNode node, Scope& scope, pos_t sourcePathRef, ReferenceMap& paths, bool tapeOptMode, bool threadFriendly) { BuildNode current = node.firstChild(); @@ -3627,7 +3650,9 @@ void ByteCodeWriter :: saveVMT(BuildNode node, Scope& scope, pos_t sourcePathRef if (current == BuildKey::Method) { pos_t methodSourcePathRef = sourcePathRef; - MethodEntry entry = { current.arg.reference, scope.code->position() }; + auto methodInfo = info.methods.get(current.arg.reference); + + MethodEntry entry = { current.arg.reference, scope.code->position(), methodInfo.outputRef }; scope.vmt->write(&entry, sizeof(MethodEntry)); BuildNode pathNode = current.findChild(BuildKey::Path); @@ -3703,10 +3728,10 @@ void ByteCodeWriter :: saveClass(BuildNode node, SectionScopeBase* moduleScope, openClassDebugInfo(scope, moduleScope->module->resolveReference(node.arg.reference & ~mskAnyRef), info.header.flags); saveFieldDebugInfo(scope, info); - saveVMT(node, scope, sourcePath, paths, tapeOptMode, threadFriendly); + saveVMT(info, node, scope, sourcePath, paths, tapeOptMode, threadFriendly); endDebugInfo(scope); } - else saveVMT(node, scope, INVALID_POS, paths, tapeOptMode, threadFriendly); + else saveVMT(info, node, scope, INVALID_POS, paths, tapeOptMode, threadFriendly); pos_t size = vmtWriter.position() - classPosition; vmtSection->write(classPosition - 4, &size, sizeof(size)); diff --git a/elenasrc3/engine/bcwriter.h b/elenasrc3/engine/bcwriter.h index 92648d2963..35746c6b10 100644 --- a/elenasrc3/engine/bcwriter.h +++ b/elenasrc3/engine/bcwriter.h @@ -91,6 +91,8 @@ namespace elena_lang ReferenceMap& paths, bool tapeOptMode, bool loopMode = false); void saveBranching(CommandTape& tape, BuildNode node, TapeScope& tapeScope, ReferenceMap& paths, bool tapeOptMode, bool loopMode); + void saveTernaryOp(CommandTape& tape, BuildNode node, TapeScope& tapeScope, + ReferenceMap& paths, bool tapeOptMode); void saveNativeBranching(CommandTape& tape, BuildNode node, TapeScope& tapeScope, ReferenceMap& paths, bool tapeOptMode, bool loopMode); void saveLoop(CommandTape& tape, BuildNode node, TapeScope& tapeScope, ReferenceMap& paths, @@ -119,7 +121,7 @@ namespace elena_lang void saveProcedure(BuildNode node, Scope& scope, bool classMode, pos_t sourcePathRef, ReferenceMap& paths, bool tapeOptMode, bool threadFriendly); - void saveVMT(BuildNode node, Scope& scope, pos_t sourcePathRef, ReferenceMap& paths, + void saveVMT(ClassInfo& info, BuildNode node, Scope& scope, pos_t sourcePathRef, ReferenceMap& paths, bool tapeOptMode, bool threadFriendly); void saveSymbol(BuildNode node, SectionScopeBase* moduleScope, int minimalArgList, diff --git a/elenasrc3/engine/buildtree.h b/elenasrc3/engine/buildtree.h index dd879f4080..85a9a7bf8d 100644 --- a/elenasrc3/engine/buildtree.h +++ b/elenasrc3/engine/buildtree.h @@ -185,6 +185,7 @@ namespace elena_lang YieldingOp = 0x00A2, StackCondOp = 0x00A3, YieldDispatch = 0x00A4, + TernaryOp = 0x00A5, VariableInfo = 0x00B0, Variable = 0x00B1, diff --git a/elenasrc3/engine/elena.h b/elenasrc3/engine/elena.h index fd91c28bd7..b0db0f72cc 100644 --- a/elenasrc3/engine/elena.h +++ b/elenasrc3/engine/elena.h @@ -375,7 +375,7 @@ namespace elena_lang virtual SectionInfo getCoreSection(ref_t reference, bool silentMode) = 0; virtual SectionInfo getSection(ReferenceInfo referenceInfo, ref_t mask, ref_t metaMask, bool silentMode) = 0; - virtual ClassSectionInfo getClassSections(ReferenceInfo referenceInfo, ref_t vmtMask, ref_t codeMask, + virtual ClassSectionInfo getClassSections(ReferenceInfo referenceInfo, ref_t vmtMask, ref_t codeMask, bool silentMode) = 0; virtual ModuleInfo getModule(ReferenceInfo referenceInfo, bool silentMode) = 0; @@ -436,7 +436,7 @@ namespace elena_lang virtual addr_t calculateVAddress(MemoryWriter& writer, ref_t addressMask) = 0; - virtual void writeSectionReference(MemoryBase* image, pos_t imageOffset, ref_t reference, + virtual void writeSectionReference(MemoryBase* image, pos_t imageOffset, ref_t reference, SectionInfo* sectionInfo, pos_t sectionOffset, ref_t addressMask) = 0; virtual void writeReference(MemoryBase& target, pos_t position, ref_t reference, pos_t disp, @@ -461,7 +461,7 @@ namespace elena_lang virtual void writeMDataRef32(MemoryBase& target, pos_t position, pos_t disp, ref_t addressMask) = 0; - virtual void writeMDataRef64(MemoryBase& target, pos_t position, + virtual void writeMDataRef64(MemoryBase& target, pos_t position, pos64_t disp, ref_t addressMask) = 0; virtual mssg_t importMessage(mssg_t message, ModuleBase* module = nullptr) = 0; @@ -514,13 +514,24 @@ namespace elena_lang virtual void writeLabelAddress(pos_t label, MemoryWriter& writer, ref_t mask) = 0; }; + typedef CachedList, 10> CachedOutputTypeList; + // --- JITCompilerBase --- class JITCompilerBase { public: + struct VMTFixInfo + { + addr_t parentAddress; + addr_t classClassAddress; + addr_t outputListAddress; + ref_t flags; + pos_t count; + }; + virtual void prepare( - LibraryLoaderBase* loader, - ImageProviderBase* imageProvider, + LibraryLoaderBase* loader, + ImageProviderBase* imageProvider, ReferenceHelperBase* helper, LabelHelperBase* lh, JITSettings settings, @@ -532,26 +543,28 @@ namespace elena_lang virtual void alignCode(MemoryWriter& writer, pos_t alignment, bool isText) = 0; - virtual void compileProcedure(ReferenceHelperBase* helper, MemoryReader& bcReader, + virtual void compileProcedure(ReferenceHelperBase* helper, MemoryReader& bcReader, MemoryWriter& codeWriter, LabelHelperBase* lh) = 0; - virtual void compileSymbol(ReferenceHelperBase* helper, MemoryReader& bcReader, + virtual void compileSymbol(ReferenceHelperBase* helper, MemoryReader& bcReader, MemoryWriter& codeWriter, LabelHelperBase* lh) = 0; virtual void compileMetaList(ReferenceHelperBase* helper, MemoryReader& reader, MemoryWriter& writer, pos_t length) = 0; + virtual void compileOutputTypeList(ReferenceHelperBase* helper, MemoryWriter& writer, CachedOutputTypeList& outputTypeList) = 0; + virtual pos_t getStaticCounter(MemoryBase* statSection, bool emptyNotAllowed = false) = 0; virtual pos_t getVMTLength(void* targetVMT) = 0; virtual addr_t findMethodAddress(void* entries, mssg_t message) = 0; virtual pos_t findMethodOffset(void* entries, mssg_t message) = 0; - virtual void allocateVMT(MemoryWriter& vmtWriter, pos_t flags, pos_t vmtLength, pos_t staticLength) = 0; + virtual void allocateVMT(MemoryWriter& vmtWriter, pos_t flags, pos_t vmtLength, + pos_t staticLength, bool withOutputList) = 0; virtual void addVMTEntry(mssg_t message, addr_t codeAddress, void* targetVMT, pos_t& entryCount) = 0; - virtual void updateVMTHeader(MemoryWriter& vmtWriter, addr_t parentAddress, addr_t classClassAddress, - ref_t flags, pos_t count, FieldAddressMap& staticValues, bool virtualMode) = 0; + virtual void updateVMTHeader(MemoryWriter& vmtWriter, VMTFixInfo& fixInfo, FieldAddressMap& staticValues, bool virtualMode) = 0; virtual pos_t copyParentVMT(void* parentVMT, void* targetVMT) = 0; - virtual void allocateHeader(MemoryWriter& writer, addr_t vmtAddress, int length, + virtual void allocateHeader(MemoryWriter& writer, addr_t vmtAddress, int length, bool structMode, bool virtualMode) = 0; virtual void allocateBody(MemoryWriter& writer, int size) = 0; virtual void writeInt32(MemoryWriter& writer, unsigned int value) = 0; @@ -570,7 +583,7 @@ namespace elena_lang virtual void addBreakpoint(MemoryWriter& writer, addr_t vaddress, bool virtualMode) = 0; virtual pos_t addSignatureEntry(MemoryWriter& writer, addr_t vmtAddress, ref_t& targetMask, bool virtualMode) = 0; - virtual pos_t addActionEntry(MemoryWriter& messageWriter, MemoryWriter& messageBodyWriter, + virtual pos_t addActionEntry(MemoryWriter& messageWriter, MemoryWriter& messageBodyWriter, ustr_t actionName, ref_t weakActionRef, ref_t signature, bool virtualMode) = 0; virtual void addActionEntryStopper(MemoryWriter& messageWriter) = 0; virtual void addSignatureStopper(MemoryWriter& messageWriter) = 0; @@ -817,7 +830,7 @@ namespace elena_lang else append(s[i]); break; case 2: - if ((s[i] < '0' || s[i] > '9') && (s[i] < 'A' || s[i] > 'F') && (s[i] < 'a' || s[i] > 'f')) + if ((s[i] < '0' || s[i] > '9') && (s[i] < 'A' || s[i] > 'F') && (s[i] < 'a' || s[i] > 'f')) { String number(s + index, i - index); unic_c ch = StrConvertor::toInt(number.str(), (s[i] == 'h') ? 16 : 10); @@ -1107,6 +1120,7 @@ namespace elena_lang { mssg_t message; pos_t codeOffset; + ref_t outputRef; }; // --- DebugLineInfo --- diff --git a/elenasrc3/engine/elenaconst.h b/elenasrc3/engine/elenaconst.h index 595921f2cf..393e57b169 100644 --- a/elenasrc3/engine/elenaconst.h +++ b/elenasrc3/engine/elenaconst.h @@ -13,7 +13,7 @@ namespace elena_lang { // --- Common ELENA Engine constants --- #define ENGINE_MAJOR_VERSION 6 // ELENA Engine version - #define ENGINE_MINOR_VERSION 0 + #define ENGINE_MINOR_VERSION 1 constexpr auto LINE_LEN = 0x1000; // the maximal source line length constexpr auto IDENTIFIER_LEN = 0x0300; // the maximal identifier length @@ -38,7 +38,7 @@ namespace elena_lang // --- ELENA Module structure constants --- constexpr auto ELENA_SIGNITURE = "ELENA."; // the stand alone image constexpr auto ELENA_VM_SIGNITURE = "VM.ELENA."; // the stand alone image - constexpr auto MODULE_SIGNATURE = "ELENA.0601"; // the module version + constexpr auto MODULE_SIGNATURE = "ELENA.0611"; // the module version constexpr auto DEBUG_MODULE_SIGNATURE = "ED.06"; // --- ELENA core module names --- @@ -193,6 +193,7 @@ namespace elena_lang constexpr ref_t elAbstract = 0x00000200; constexpr ref_t elNoCustomDispatcher = 0x00000400; constexpr ref_t elStructureRole = 0x00000838; + constexpr ref_t elStructure = 0x00000800; constexpr ref_t elReadOnlyRole = 0x00001000; constexpr ref_t elNonStructureRole = 0x00002000; constexpr ref_t elWrapper = 0x00004000; @@ -209,6 +210,7 @@ namespace elena_lang constexpr ref_t elGroup = 0x10000000; constexpr ref_t elPacked = 0x20000000; constexpr ref_t elTemplatebased = 0x40000000; + constexpr ref_t elWithOutputList = 0x80000000; // NOTE : this flag is set automatically by JIT linker constexpr ref_t elDebugMask = 0x001F0000; constexpr ref_t elDebugDWORD = 0x00010000; @@ -220,6 +222,9 @@ namespace elena_lang constexpr ref_t elDebugArray = 0x00070000; constexpr ref_t elDebugFLOAT64S = 0x00080000; constexpr ref_t elDebugBytes = 0x00090000; + constexpr ref_t elProxy = 0x000A0000; + constexpr ref_t elInterface = 0x000B0000; + constexpr ref_t elWeakInterface = 0x000C0000; // --- LoadResult enum --- enum class LoadResult diff --git a/elenasrc3/engine/elenamachine.cpp b/elenasrc3/engine/elenamachine.cpp index bc4e26fb66..b482135fd3 100644 --- a/elenasrc3/engine/elenamachine.cpp +++ b/elenasrc3/engine/elenamachine.cpp @@ -15,18 +15,169 @@ using namespace elena_lang; typedef VMTHeader32 VMTHeader; typedef VMTEntry32 VMTEntry; +typedef ObjectPage32 ObjectPage; constexpr int elVMTClassOffset = elVMTClassOffset32; +constexpr int gcPageSize = gcPageSize32; +constexpr int elObjectOffset = elObjectOffset32; +constexpr int struct_mask = elStructMask32; #else typedef VMTHeader64 VMTHeader; typedef VMTEntry64 VMTEntry; +typedef ObjectPage64 ObjectPage; constexpr int elVMTClassOffset = elVMTClassOffset64; +constexpr int gcPageSize = gcPageSize64; +constexpr int elObjectOffset = elObjectOffset64; +constexpr int struct_mask = elStructMask64; #endif +inline uintptr_t RetrieveStaticField(uintptr_t ptr, int index) +{ + uintptr_t str = *(uintptr_t*)(ptr - sizeof(VMTHeader) + index * sizeof(uintptr_t)); + + return str; +} + +inline uintptr_t RetrieveVMT(uintptr_t ptr) +{ + return *(uintptr_t*)(ptr - elObjectOffset); +} + +// --- ELENAMachine --- + +uintptr_t ELENAMachine :: createPermString(SystemEnv* env, ustr_t s, uintptr_t classPtr) +{ + size_t nameLen = getlength(s) + 1; + uintptr_t nameAddr = (uintptr_t)SystemRoutineProvider::GCRoutinePerm(env->gc_table, align(nameLen + elObjectOffset, gcPageSize)); + + StrConvertor::copy((char*)nameAddr, s.str(), nameLen, nameLen); + + ObjectPage* header = (ObjectPage*)(nameAddr - elObjectOffset); + header->vmtPtr = classPtr; + header->size = nameLen | struct_mask; + + return nameAddr; +} + +uintptr_t ELENAMachine :: createPermVMT(SystemEnv* env, size_t size) +{ + size += sizeof(ObjectPage); + + uintptr_t addr = (uintptr_t)SystemRoutineProvider::GCRoutinePerm(env->gc_table, align(size, gcPageSize)); + + ObjectPage* header = (ObjectPage*)(addr - elObjectOffset); + header->size = size; + header->vmtPtr = 0; + + return (uintptr_t)header + elObjectOffset; +} + +inline bool isValidProxy(uintptr_t vmtPtr) +{ + int flags = SystemRoutineProvider::GetFlags((void*)vmtPtr); + + return (flags & elDebugMask) == elProxy; +} + +inline bool isWeakInterface(void* vmtPtr) +{ + int flags = SystemRoutineProvider::GetFlags(vmtPtr); + + return (flags & elDebugMask) == elWeakInterface; +} + +addr_t ELENAMachine :: injectType(SystemEnv* env, void* proxy, void* srcVMTPtr, int staticLen, int nameIndex) +{ + uintptr_t proxyVMTPtr = RetrieveVMT((uintptr_t)proxy); + + // verify if the proxy can be used + if (!isValidProxy(proxyVMTPtr)) + return INVALID_ADDR; + + // verify if it is a correct interface + if (!isWeakInterface(srcVMTPtr)) + return INVALID_ADDR; + + assert(nameIndex < 0); + + static int autoIndex = 0; + + uintptr_t namePtr = RetrieveStaticField((uintptr_t)srcVMTPtr, nameIndex); + uintptr_t stringVMT = RetrieveVMT(namePtr); + + IdentifierString dynamicName("proxy$"); + if (namePtr) { + dynamicName.append((const char*)namePtr); + } + else dynamicName.appendInt(++autoIndex); + + addr_t proxyVMTAddress = _generatedClasses.get(*dynamicName); + if (!proxyVMTAddress) { + // NOTE : probably better to create a custom package, but for a moment we can simply copy it + uintptr_t nameAddr = createPermString(env, *dynamicName, stringVMT); + size_t srcLength = SystemRoutineProvider::GetVMTLength(srcVMTPtr); + size_t size = (srcLength * sizeof(VMTEntry)) + sizeof(VMTHeader) + elObjectOffset + staticLen * sizeof(uintptr_t); + int flags = SystemRoutineProvider::GetFlags(srcVMTPtr); + + proxyVMTAddress = createPermVMT(env, size); + + void* baseVMTPtr = (void*)proxyVMTPtr; + size_t baseLength = SystemRoutineProvider::GetVMTLength(baseVMTPtr); + + // HOTFIX : copy build-in static variables + uintptr_t* staticFields = (uintptr_t*)(proxyVMTAddress + staticLen * sizeof(uintptr_t)); + for (int i = 1; i <= staticLen; i++) { + staticFields[-i] = RetrieveStaticField((uintptr_t)srcVMTPtr, -i); + } + staticFields[nameIndex] = nameAddr; + + VMTHeader* header = (VMTHeader*)(proxyVMTAddress + staticLen * sizeof(uintptr_t)); + VMTEntry* entries = (VMTEntry*)(proxyVMTAddress + staticLen * sizeof(uintptr_t) + sizeof(VMTHeader)); + + VMTEntry* base = (VMTEntry*)baseVMTPtr; + VMTEntry* src = (VMTEntry*)srcVMTPtr; + + header->parentRef = (addr_t)srcVMTPtr; + header->count = srcLength; + header->flags = flags & ~elDebugMask; + header->classRef = (addr_t)base; + + // copy the dispatcher + entries[0] = src[0]; + + size_t i = 1, j = 1; + while (i < srcLength) { + if (j < baseLength && base[j].message == src[i].message) { + entries[i] = base[j]; + j++; + } + else if (src[i].address) { + // if the method is not abstract + entries[i] = src[i]; + } + else { + entries[i].message = src[i].message; + entries[i].address = base[0].address; + } + + i++; + } + + // skip a class header + proxyVMTAddress = (addr_t)entries; + + _generatedClasses.add(*dynamicName, proxyVMTAddress); + } + + SystemRoutineProvider::overrideClass(proxy, (void*)proxyVMTAddress); + + return (addr_t)proxy; +} + // --- SystemRoutineProvider --- void SystemRoutineProvider :: InitSTAExceptionHandling(SystemEnv* env, void* criticalHandler) @@ -138,6 +289,47 @@ unsigned int SystemRoutineProvider :: GetRandomNumber(SeedStruct& seed) return (seed.z1 ^ seed.z2 ^ seed.z3 ^ seed.z4); } +size_t SystemRoutineProvider :: GetVMTLength(void* classPtr) +{ + VMTHeader* header = (VMTHeader*)((uintptr_t)classPtr - elVMTClassOffset); + + return header->count; +} + +addr_t SystemRoutineProvider::GetParent(void* classPtr) +{ + VMTHeader* header = (VMTHeader*)((uintptr_t)classPtr - elVMTClassOffset); + + return header->parentRef; +} + +addr_t SystemRoutineProvider :: GetClass(void* ptr) +{ + VMTHeader* header = (VMTHeader*)((uintptr_t)ptr - elVMTClassOffset); + + return header->classRef; +} + +bool SystemRoutineProvider :: overrideClass(void* ptr, void* classPtr) +{ + ObjectPage* header = (ObjectPage*)((uintptr_t)ptr - elObjectOffset); + VMTHeader* vmtHeader = (VMTHeader*)(header->vmtPtr - elVMTClassOffset); + if ((vmtHeader->flags & elDebugMask) == elProxy) { + header->vmtPtr = (uintptr_t)classPtr; + + return true; + } + + return false; +} + +int SystemRoutineProvider :: GetFlags(void* classPtr) +{ + VMTHeader* header = (VMTHeader*)((uintptr_t)classPtr - elVMTClassOffset); + + return header->flags; +} + size_t SystemRoutineProvider :: LoadMessages(MemoryBase* msection, void* classPtr, mssg_t* output, size_t skip, size_t maxLength, bool vmMode) { @@ -151,7 +343,7 @@ size_t SystemRoutineProvider :: LoadMessages(MemoryBase* msection, void* classPt skip--; } else if (counter < maxLength) { - mssg_t weakMessage = ((VMTEntry*)classPtr)[i].message; + mssg_t weakMessage = (mssg_t)((VMTEntry*)classPtr)[i].message; bool duplicate = false; for (size_t i = 0; i < counter; i++) { if (output[i] == weakMessage) { diff --git a/elenasrc3/engine/elenamachine.h b/elenasrc3/engine/elenamachine.h index f7506f0653..565ddf7349 100644 --- a/elenasrc3/engine/elenamachine.h +++ b/elenasrc3/engine/elenamachine.h @@ -79,11 +79,23 @@ namespace elena_lang // --- ELENAMachine --- class ELENAMachine { + protected: + AddressMap _generatedClasses; + + uintptr_t createPermString(SystemEnv* env, ustr_t s, uintptr_t classPtr); + uintptr_t createPermVMT(SystemEnv* env, size_t size); + public: + addr_t injectType(SystemEnv* env, void* proxy, void* srcVMTPtr, int staticLen, int nameIndex/*, addr_t* addresses, size_t length*/); + addr_t execute(SystemEnv* env, void* symbolListEntry); addr_t execute(SystemEnv* env, void* threadEntry, void* threadFunc); - ELENAMachine() = default; + ELENAMachine() + : _generatedClasses(0) + { + + } virtual ~ELENAMachine() = default; }; @@ -129,6 +141,11 @@ namespace elena_lang static size_t LoadMessages(MemoryBase* msection, void* classPtr, mssg_t* output, size_t skip, size_t maxLength, bool vmMode); + static size_t GetVMTLength(void* classPtr); + static addr_t GetClass(void* ptr); + static addr_t GetParent(void* classPtr); + static int GetFlags(void* classPtr); + static bool overrideClass(void* ptr, void* classPtr); static bool CheckMessage(MemoryBase* msection, void* classPtr, mssg_t message); diff --git a/elenasrc3/engine/jitcompiler.cpp b/elenasrc3/engine/jitcompiler.cpp index 72554f3c61..fff39f1684 100644 --- a/elenasrc3/engine/jitcompiler.cpp +++ b/elenasrc3/engine/jitcompiler.cpp @@ -3105,6 +3105,20 @@ pos_t JITCompiler32 :: getStaticCounter(MemoryBase* statSection, bool emptyNotAl return statSection->length() >> 2; } +void JITCompiler32 :: compileOutputTypeList(ReferenceHelperBase* helper, MemoryWriter& writer, CachedOutputTypeList& outputTypeList) +{ + size_t len = outputTypeList.count(); + + writer.writeDWord(len); + for (size_t i = 0; i < len; i++) { + auto info = outputTypeList.get(i); + + writer.writeDWord(info.value1); + writer.writeDWord(0); + helper->writeReference(*writer.Memory(), writer.position() - 4, info.value2, 0, mskRef32); + } +} + void JITCompiler32 :: compileMetaList(ReferenceHelperBase* helper, MemoryReader& reader, MemoryWriter& writer, pos_t length) { writer.writeDWord(length); @@ -3120,7 +3134,7 @@ void JITCompiler32 :: compileMetaList(ReferenceHelperBase* helper, MemoryReader& } void JITCompiler32 :: allocateVMT(MemoryWriter& vmtWriter, pos_t flags, pos_t vmtLength, - pos_t staticLength) + pos_t staticLength, bool withOutputList) { // create VMT static table vmtWriter.writeBytes(0, staticLength << 2); @@ -3140,6 +3154,9 @@ void JITCompiler32 :: allocateVMT(MemoryWriter& vmtWriter, pos_t flags, pos_t vm vmtWriter.writeBytes(0, vmtSize); + if (withOutputList) + vmtWriter.writeDWord(0); + vmtWriter.seek(position); } @@ -3242,18 +3259,21 @@ void JITCompiler32 :: addVMTEntry(mssg_t message, addr_t codeAddress, void* targ entries[index].address = (pos_t)codeAddress; } -void JITCompiler32 :: updateVMTHeader(MemoryWriter& vmtWriter, addr_t parentAddress, addr_t classClassAddress, - ref_t flags, pos_t count, FieldAddressMap& staticValues, bool virtualMode) +void JITCompiler32 :: updateVMTHeader(MemoryWriter& vmtWriter, VMTFixInfo& fixInfo, + FieldAddressMap& staticValues, bool virtualMode) { pos_t position = vmtWriter.position(); + if (fixInfo.outputListAddress) + fixInfo.flags |= elWithOutputList; + vmtWriter.seek(position - sizeof(VMTHeader32)); VMTHeader32 header = { 0 }; - header.flags = flags; - header.count = count; + header.flags = fixInfo.flags; + header.count = fixInfo.count; if (!virtualMode) { - header.parentRef = (pos_t)parentAddress; - header.classRef = (pos_t)classClassAddress; + header.parentRef = (pos_t)fixInfo.parentAddress; + header.classRef = (pos_t)fixInfo.classClassAddress; } vmtWriter.write(&header, sizeof(VMTHeader32)); @@ -3261,18 +3281,19 @@ void JITCompiler32 :: updateVMTHeader(MemoryWriter& vmtWriter, addr_t parentAddr if (virtualMode) { MemoryBase* image = vmtWriter.Memory(); - if (parentAddress) { + if (fixInfo.parentAddress) { vmtWriter.seek(position - sizeof(VMTHeader32) + VMTHeader32ParentRefOffs); - vmtWriter.writeDReference((ref_t)parentAddress | mskRef32, 0); + vmtWriter.writeDReference((ref_t)fixInfo.parentAddress | mskRef32, 0); } - if (classClassAddress) { + if (fixInfo.classClassAddress) { vmtWriter.seek(position - sizeof(VMTHeader32) + VMTHeader32ClassRefOffs); - vmtWriter.writeDReference((ref_t)classClassAddress | mskRef32, 0); + vmtWriter.writeDReference((ref_t)fixInfo.classClassAddress | mskRef32, 0); } pos_t entryPosition = position; - for (pos_t i = 0; i < count; i++) { - image->addReference(mskCodeRef32, entryPosition + 4); + for (pos_t i = 0; i < fixInfo.count; i++) { + if (MemoryBase::getDWord(image, entryPosition + 4)) + image->addReference(mskCodeRef32, entryPosition + 4); entryPosition += 8; } @@ -3286,8 +3307,15 @@ void JITCompiler32 :: updateVMTHeader(MemoryWriter& vmtWriter, addr_t parentAddr } else vmtWriter.writeDWord((pos_t)*it); } - + vmtWriter.seek(position); + + if (fixInfo.outputListAddress) { + if (virtualMode) { + vmtWriter.writeDReference(addrToUInt32(fixInfo.outputListAddress) | mskRef32, 0); + } + else vmtWriter.writeDWord(fixInfo.outputListAddress); + } } pos_t JITCompiler32 :: addActionEntry(MemoryWriter& messageWriter, MemoryWriter& messageBodyWriter, ustr_t actionName, @@ -3554,7 +3582,22 @@ void JITCompiler64 :: compileMetaList(ReferenceHelperBase* helper, MemoryReader& } } -void JITCompiler64 :: allocateVMT(MemoryWriter& vmtWriter, pos_t flags, pos_t vmtLength, pos_t staticLength) +void JITCompiler64 :: compileOutputTypeList(ReferenceHelperBase* helper, MemoryWriter& writer, CachedOutputTypeList& outputTypeList) +{ + size_t len = outputTypeList.count(); + + writer.writeQWord(len); + for (size_t i = 0; i < len; i++) { + auto info = outputTypeList.get(i); + + writer.writeQWord(info.value1); + writer.writeQWord(0); + helper->writeReference(*writer.Memory(), writer.position() - 8, info.value2, 0, mskRef32); + } +} + +void JITCompiler64 :: allocateVMT(MemoryWriter& vmtWriter, pos_t flags, pos_t vmtLength, + pos_t staticLength, bool withOutputList) { // create VMT static table vmtWriter.writeBytes(0, staticLength << 3); @@ -3574,6 +3617,9 @@ void JITCompiler64 :: allocateVMT(MemoryWriter& vmtWriter, pos_t flags, pos_t vm vmtWriter.writeBytes(0, vmtSize); + if (withOutputList) + vmtWriter.writeQWord(0); + vmtWriter.seek(position); } @@ -3664,18 +3710,17 @@ void JITCompiler64 :: addVMTEntry(mssg_t message, addr_t codeAddress, void* targ entries[index].address = codeAddress; } -void JITCompiler64 :: updateVMTHeader(MemoryWriter& vmtWriter, addr_t parentAddress, addr_t classClassAddress, - ref_t flags, pos_t count, FieldAddressMap& staticValues, bool virtualMode) +void JITCompiler64 :: updateVMTHeader(MemoryWriter& vmtWriter, VMTFixInfo& fixInfo, FieldAddressMap& staticValues, bool virtualMode) { pos_t position = vmtWriter.position(); vmtWriter.seek(position - sizeof(VMTHeader64)); VMTHeader64 header = { 0 }; - header.flags = flags; - header.count = count; + header.flags = fixInfo.flags; + header.count = fixInfo.count; if (!virtualMode) { - header.parentRef = parentAddress; - header.classRef = classClassAddress; + header.parentRef = fixInfo.parentAddress; + header.classRef = fixInfo.classClassAddress; } vmtWriter.write(&header, sizeof(VMTHeader64)); @@ -3683,17 +3728,18 @@ void JITCompiler64 :: updateVMTHeader(MemoryWriter& vmtWriter, addr_t parentAddr if (virtualMode) { MemoryBase* image = vmtWriter.Memory(); - if (parentAddress) { + if (fixInfo.parentAddress) { vmtWriter.seek(position - sizeof(VMTHeader64) + VMTHeader64ParentRefOffs); - vmtWriter.writeQReference((ref_t)parentAddress | mskRef64, 0); + vmtWriter.writeQReference((ref_t)fixInfo.parentAddress | mskRef64, 0); } - if (classClassAddress) { + if (fixInfo.classClassAddress) { vmtWriter.seek(position - sizeof(VMTHeader64) + VMTHeader64ClassRefOffs); - vmtWriter.writeQReference((ref_t)classClassAddress | mskRef64, 0); + vmtWriter.writeQReference((ref_t)fixInfo.classClassAddress | mskRef64, 0); } pos_t entryPosition = position; - for (pos_t i = 0; i < count; i++) { - image->addReference(mskCodeRef64, entryPosition + 8); + for (pos_t i = 0; i < fixInfo.count; i++) { + if (MemoryBase::getQWord(image, entryPosition + 8)) + image->addReference(mskCodeRef64, entryPosition + 8); entryPosition += 16; } @@ -3709,6 +3755,13 @@ void JITCompiler64 :: updateVMTHeader(MemoryWriter& vmtWriter, addr_t parentAddr } vmtWriter.seek(position); + + if (fixInfo.outputListAddress) { + if (virtualMode) { + vmtWriter.writeQReference(fixInfo.outputListAddress | mskRef64, 0); + } + else vmtWriter.writeQWord(fixInfo.outputListAddress); + } } pos_t JITCompiler64 :: addActionEntry(MemoryWriter& messageWriter, MemoryWriter& messageBodyWriter, ustr_t actionName, diff --git a/elenasrc3/engine/jitcompiler.h b/elenasrc3/engine/jitcompiler.h index d8f10ea624..598603c2a4 100644 --- a/elenasrc3/engine/jitcompiler.h +++ b/elenasrc3/engine/jitcompiler.h @@ -265,16 +265,18 @@ namespace elena_lang void compileMetaList(ReferenceHelperBase* helper, MemoryReader& reader, MemoryWriter& writer, pos_t length) override; + void compileOutputTypeList(ReferenceHelperBase* helper, MemoryWriter& writer, CachedOutputTypeList& outputTypeList) override; + pos_t getStaticCounter(MemoryBase* statSection, bool emptyNotAllowed) override; pos_t getVMTLength(void* targetVMT) override; addr_t findMethodAddress(void* entries, mssg_t message) override; pos_t findMethodOffset(void* entries, mssg_t message) override; - void allocateVMT(MemoryWriter& vmtWriter, pos_t flags, pos_t vmtLength, pos_t staticLength) override; + void allocateVMT(MemoryWriter& vmtWriter, pos_t flags, pos_t vmtLength, + pos_t staticLength, bool withOutputList) override; void addVMTEntry(mssg_t message, addr_t codeAddress, void* targetVMT, pos_t& entryCount) override; - void updateVMTHeader(MemoryWriter& vmtWriter, addr_t parentAddress, addr_t classClassAddress, - ref_t flags, pos_t count, FieldAddressMap& staticValues, bool virtualMode) override; + void updateVMTHeader(MemoryWriter& vmtWriter, VMTFixInfo& fixInfo, FieldAddressMap& staticValues, bool virtualMode) override; pos_t copyParentVMT(void* parentVMT, void* targetVMT) override; void allocateHeader(MemoryWriter& writer, addr_t vmtAddress, int length, @@ -336,6 +338,8 @@ namespace elena_lang void compileMetaList(ReferenceHelperBase* helper, MemoryReader& reader, MemoryWriter& writer, pos_t length) override; + void compileOutputTypeList(ReferenceHelperBase* helper, MemoryWriter& writer, CachedOutputTypeList& outputTypeList) override; + pos_t getStaticCounter(MemoryBase* statSection, bool emptyNotAllowed) override; int getExtMessageSize() override @@ -348,11 +352,10 @@ namespace elena_lang pos_t findMethodOffset(void* entries, mssg_t message) override; void allocateVMT(MemoryWriter& vmtWriter, pos_t flags, pos_t vmtLength, - pos_t staticLength) override; + pos_t staticLength, bool withOutputList) override; pos_t copyParentVMT(void* parentVMT, void* targetVMT) override; void addVMTEntry(mssg_t message, addr_t codeAddress, void* targetVMT, pos_t& entryCount) override; - void updateVMTHeader(MemoryWriter& vmtWriter, addr_t parentAddress, addr_t classClassAddress, - ref_t flags, pos_t count, FieldAddressMap& staticValues, bool virtualMode) override; + void updateVMTHeader(MemoryWriter& vmtWriter, VMTFixInfo& fixInfo, FieldAddressMap& staticValues, bool virtualMode) override; void allocateHeader(MemoryWriter& writer, addr_t vmtAddress, int length, bool structMode, bool virtualMode) override; diff --git a/elenasrc3/engine/jitlinker.cpp b/elenasrc3/engine/jitlinker.cpp index 76af187c74..cf733d1f09 100644 --- a/elenasrc3/engine/jitlinker.cpp +++ b/elenasrc3/engine/jitlinker.cpp @@ -3,7 +3,7 @@ // // This file contains ELENA JIT linker class implementation. // -// (C)2021-2023, by Aleksey Rakov +// (C)2021-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #include "elena.h" @@ -812,8 +812,11 @@ addr_t JITLinker :: createVMTSection(ReferenceInfo referenceInfo, ClassSectionIn MemoryBase* codeImage = _imageProvider->getTargetSection(mskCodeRef); MemoryWriter vmtWriter(vmtImage); + bool withOutputList = _withOutputList && !test(header.flags, elNestedClass); + // allocate space and make VTM offset - _compiler->allocateVMT(vmtWriter, header.flags, header.count, header.staticSize); + _compiler->allocateVMT(vmtWriter, header.flags, header.count, + header.staticSize, withOutputList); addr_t vaddress = calculateVAddress(vmtWriter, mskRDataRef); @@ -837,6 +840,8 @@ addr_t JITLinker :: createVMTSection(ReferenceInfo referenceInfo, ClassSectionIn addr_t methodPosition = 0; MethodEntry entry = { }; + CachedOutputTypeList outputTypeList({}); + size -= sizeof(ClassHeader); while (size > 0) { vmtReader.read((void*)&entry, sizeof(MethodEntry)); @@ -855,8 +860,15 @@ addr_t JITLinker :: createVMTSection(ReferenceInfo referenceInfo, ClassSectionIn _staticMethods.add( { vaddress, message }, methodPosition); } - else _compiler->addVMTEntry(message, methodPosition, - vmtImage->get(position), count); + else { + _compiler->addVMTEntry(message, methodPosition, + vmtImage->get(position), count); + + if (withOutputList && entry.outputRef && entry.outputRef != sectionInfo.reference) { + // NOTE : the list must contain already resolved message constants, so only type references must be resolved + outputTypeList.add({ message, entry.outputRef }); + } + } if (_addressMapper && methodPosition) _addressMapper->addMethod(vaddress, message, methodPosition); @@ -879,8 +891,12 @@ addr_t JITLinker :: createVMTSection(ReferenceInfo referenceInfo, ClassSectionIn resolveClassGlobalAttributes(referenceInfo, vmtReader, vaddress); + addr_t outputListAddress = withOutputList ? + resolveOutputTypeList(referenceInfo, outputTypeList) : 0; + // update VMT - _compiler->updateVMTHeader(vmtWriter, parentAddress, classClassAddress, header.flags, header.count, staticValues, _virtualMode); + JITCompilerBase::VMTFixInfo fixInfo = { parentAddress, classClassAddress, outputListAddress, header.flags, header.count }; + _compiler->updateVMTHeader(vmtWriter, fixInfo, staticValues, _virtualMode); } return vaddress; @@ -1095,6 +1111,24 @@ addr_t JITLinker :: resolveBytecodeSection(ReferenceInfo referenceInfo, ref_t se return vaddress; } +// NOTE : the list contains already resolved message constants, so only type references must be resolved +addr_t JITLinker :: resolveOutputTypeList(ReferenceInfo referenceInfo, CachedOutputTypeList& outputTypeList) +{ + VAddressMap references({ 0, nullptr, 0, 0 }); + + MemoryBase* image = _imageProvider->getTargetSection(mskRDataRef); + MemoryWriter writer(image); + + addr_t vaddress = calculateVAddress(writer, mskRDataRef); + + JITLinkerReferenceHelper helper(this, referenceInfo.module, &references); + _compiler->compileOutputTypeList(&helper, writer, outputTypeList); + + fixReferences(references, image); + + return vaddress; +} + addr_t JITLinker :: resolveMetaSection(ReferenceInfo referenceInfo, ref_t sectionMask, SectionInfo sectionInfo) { if (sectionInfo.section == nullptr) diff --git a/elenasrc3/engine/jitlinker.h b/elenasrc3/engine/jitlinker.h index c5894cf5b9..2a5d241ba4 100644 --- a/elenasrc3/engine/jitlinker.h +++ b/elenasrc3/engine/jitlinker.h @@ -167,6 +167,7 @@ namespace elena_lang ConstantSettings _constantSettings; bool _virtualMode; bool _classSymbolAutoLoadMode; + bool _withOutputList; bool _withDebugInfo; addr_t calculateVAddress(MemoryWriter& writer, ref_t targetMask); @@ -205,6 +206,8 @@ namespace elena_lang addr_t resolveVMTSection(ReferenceInfo referenceInfo, ClassSectionInfo sectionInfo); addr_t resolveBytecodeSection(ReferenceInfo referenceInfo, ref_t sectionMask, SectionInfo sectionInfo); addr_t resolveMetaSection(ReferenceInfo referenceInfo, ref_t sectionMask, SectionInfo sectionInfo); + // NOTE : the list contains already resolved message constants, so only type references must be resolved + addr_t resolveOutputTypeList(ReferenceInfo referenceInfo, CachedOutputTypeList& outputTypeList); addr_t resolveConstant(ReferenceInfo referenceInfo, ref_t sectionMask); addr_t resolveConstantArray(ReferenceInfo referenceInfo, ref_t sectionMask, bool silentMode); addr_t resolveConstantDump(ReferenceInfo referenceInfo, ref_t sectionMask, bool silentMode); @@ -276,6 +279,7 @@ namespace elena_lang _virtualMode = settings->virtualMode; _classSymbolAutoLoadMode = settings->autoLoadMode; _withDebugInfo = false; + _withOutputList = false; _constantSettings.intLiteralClass = forwardResolver->resolveForward(INTLITERAL_FORWARD); _constantSettings.longLiteralClass = forwardResolver->resolveForward(LONGLITERAL_FORWARD); diff --git a/elenasrc3/engine/langcommon.h b/elenasrc3/engine/langcommon.h index 7f83daa351..9a872cdb26 100644 --- a/elenasrc3/engine/langcommon.h +++ b/elenasrc3/engine/langcommon.h @@ -220,7 +220,7 @@ namespace elena_lang constexpr auto V_CONSTRUCTOR = 0x80001004u; constexpr auto V_EXTENSION = 0x80001005u; constexpr auto V_SINGLETON = 0x80001006u; - constexpr auto V_LIMITED = 0x80001007u; + constexpr auto V_INTERFACE = 0x80001007u; constexpr auto V_METHOD = 0x80001008u; constexpr auto V_FIELD = 0x80001009u; constexpr auto V_NONESTRUCT = 0x8000100Au; diff --git a/elenasrc3/engine/libman.cpp b/elenasrc3/engine/libman.cpp index 9a53044716..d0f36d82b0 100644 --- a/elenasrc3/engine/libman.cpp +++ b/elenasrc3/engine/libman.cpp @@ -217,7 +217,7 @@ ModuleBase* LibraryProvider :: resolveModule(ustr_t referenceName, ref_t& refere if (result == LoadResult::NotFound) { } - else if (!silentMode) { + else if (!silentMode || result == LoadResult::WrongVersion) { throw InternalError(getLoadError(result)); } else return nullptr; diff --git a/elenasrc3/engine/module.cpp b/elenasrc3/engine/module.cpp index 39fdfda622..1b7cc7783e 100644 --- a/elenasrc3/engine/module.cpp +++ b/elenasrc3/engine/module.cpp @@ -352,7 +352,7 @@ ROModule::ROModule(StreamReader& reader, LoadResult& result) char signature[12]; reader.read(signature, getlength_pos(MODULE_SIGNATURE)); signature[getlength(MODULE_SIGNATURE)] = 0; - if (strncmp(signature, ELENA_SIGNITURE, strlen(ELENA_SIGNITURE)) != 0) { + if (strncmp(signature, MODULE_SIGNATURE, strlen(MODULE_SIGNATURE)) != 0) { result = (strncmp(signature, ELENA_SIGNITURE, 6) == 0) ? LoadResult::WrongVersion : LoadResult::WrongStructure; return; } diff --git a/elenasrc3/engine/rtmanager.cpp b/elenasrc3/engine/rtmanager.cpp index 1966523b1b..cc075873ce 100644 --- a/elenasrc3/engine/rtmanager.cpp +++ b/elenasrc3/engine/rtmanager.cpp @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------- // This header contains the implementation of the class // ELENA RT manager. -// (C)2023, by Aleksey Rakov +// (C)2023-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #include "rtmanager.h" @@ -207,8 +207,6 @@ bool RTManager :: loadSignature(ref_t subjectRef, pos_t argCount, addr_t* addres pos_t mtableOffset = MemoryBase::getDWord(msection, 0); ref_t actionPtr = MemoryBase::getDWord(msection, mtableOffset + subjectRef * MessageEntryLen); if (actionPtr != 0) { - size_t counter = 0; - uintptr_t singPtr = 0; msection->read(mtableOffset + subjectRef * MessageEntryLen + sizeof(uintptr_t), &singPtr, sizeof(uintptr_t)); diff --git a/elenasrc3/engine/rtmanager.h b/elenasrc3/engine/rtmanager.h index 13c0bee85c..248cd85936 100644 --- a/elenasrc3/engine/rtmanager.h +++ b/elenasrc3/engine/rtmanager.h @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------- // This header contains the declaration of a class // ELENA RT manager. -// (C)2023, by Aleksey Rakov +// (C)2023-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #ifndef RTMANAGER_H diff --git a/elenasrc3/engine/serializer.cpp b/elenasrc3/engine/serializer.cpp index a909c2b0b7..c71322b357 100644 --- a/elenasrc3/engine/serializer.cpp +++ b/elenasrc3/engine/serializer.cpp @@ -81,6 +81,8 @@ bool syntaxTreeReader(SyntaxKey& key, IdentifierString& strValue, int& value, vo { LoadScope* scope = static_cast(arg); + strValue.clear(); + ScriptToken token; scope->scriptReader.read(token); if (token.compare(")") || token.state == dfaEOF) diff --git a/elenasrc3/engine/syntaxtree.cpp b/elenasrc3/engine/syntaxtree.cpp index 78ef0cac74..d8e5727fbe 100644 --- a/elenasrc3/engine/syntaxtree.cpp +++ b/elenasrc3/engine/syntaxtree.cpp @@ -92,6 +92,9 @@ void SyntaxTree :: loadTokens(TokenMap& map) map.add("dimension", SyntaxKey::Dimension); map.add("eop", SyntaxKey::eop); map.add("EOP", SyntaxKey::EOP); + map.add("template_arg", SyntaxKey::TemplateArg); + map.add("template_type", SyntaxKey::TemplateType); + } bool SyntaxTree :: save(MemoryBase* section) diff --git a/elenasrc3/engine/syntaxtree.h b/elenasrc3/engine/syntaxtree.h index 795ccbdd6a..7f81a74fbc 100644 --- a/elenasrc3/engine/syntaxtree.h +++ b/elenasrc3/engine/syntaxtree.h @@ -192,6 +192,7 @@ namespace elena_lang ByRefRetMethod = 0x00010F, NameArgParameter = 0x000110, FillingAttr = 0x000111, + ProxyDispatcher = 0x000112, Column = 0x000201, Row = 0x000202, @@ -236,6 +237,22 @@ namespace elena_lang return (SyntaxKey)key; } + static bool compareNodes(SyntaxNode n1, SyntaxNode n2) + { + if (n1.key != n2.key) + return false; + + if (n1.arg.strArgPosition != INVALID_POS) { + if (n2.arg.strArgPosition == INVALID_POS || !n1.identifier().compare(n2.identifier())) + return false; + } + else if (n2.arg.strArgPosition != INVALID_POS) { + return false; + } + + return n1.arg.reference == n2.arg.reference; + } + static void copyNewNode(SyntaxTreeWriter& writer, SyntaxNode node) { if (node.arg.strArgPosition != INVALID_POS) { @@ -247,6 +264,25 @@ namespace elena_lang static void copyNode(SyntaxTreeWriter& writer, SyntaxNode node, bool includingNode = false); static void copyNodeSafe(SyntaxTreeWriter& writer, SyntaxNode node, bool includingNode = false); static void saveNode(SyntaxNode node, MemoryBase* section, bool includingNode = false); + + static bool compare(SyntaxNode n1, SyntaxNode n2, bool onlyChildren) + { + if (onlyChildren || compareNodes(n1, n2)) { + SyntaxNode c1 = n1.firstChild(); + SyntaxNode c2 = n2.firstChild(); + while (c1.key != SyntaxKey::None) { + if (!compare(c1, c2, false)) + return false; + + c1 = c1.nextNode(); + c2 = c2.nextNode(); + } + + return c2.key == SyntaxKey::None; + } + + return false; + } }; } #endif diff --git a/elenasrc3/gui/document.cpp b/elenasrc3/gui/document.cpp index 4a3e379c7c..203e1d9e4d 100644 --- a/elenasrc3/gui/document.cpp +++ b/elenasrc3/gui/document.cpp @@ -47,7 +47,7 @@ void LexicalFormatter :: format() text_t s = nullptr; pos_t length = 0; - FormatterInfo info; + FormatterInfo info = {}; TextBookmarkReader reader(_text); diff --git a/elenasrc3/gui/gtklinux/gtkcommon.cpp b/elenasrc3/gui/gtklinux/gtkcommon.cpp index e69de29bb2..8cf1871430 100644 --- a/elenasrc3/gui/gtklinux/gtkcommon.cpp +++ b/elenasrc3/gui/gtklinux/gtkcommon.cpp @@ -0,0 +1,29 @@ +//--------------------------------------------------------------------------- +// E L E N A P r o j e c t: ELENA IDE +// GTK Common Window Implementation +// (C)2024, by Alexei Rakov +//--------------------------------------------------------------------------- + +#include "gtkcommon.h" + +using namespace elena_lang; + +// --- WindowApp --- + +int WindowApp :: run(GUIControlBase* mainWindow, bool maximized, EventBase* startEvent) +{ + Gtk::Window* window = dynamic_cast(mainWindow)->getHandle(); + +// if (maximized) +// maximize(); + + window->show(); + + Gtk::Main::run(*window); + + return 0; +} + +void WindowApp :: notify(EventBase* event) +{ +} diff --git a/elenasrc3/gui/gtklinux/gtkcommon.h b/elenasrc3/gui/gtklinux/gtkcommon.h index 0195a9dd09..8ce12b538b 100644 --- a/elenasrc3/gui/gtklinux/gtkcommon.h +++ b/elenasrc3/gui/gtklinux/gtkcommon.h @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------- // E L E N A P r o j e c t: ELENA IDE // GTK Common Header File -// (C)2021-2022, by Aleksey Rakov +// (C)2024, by Aleksey Rakov //--------------------------------------------------------------------------- #ifndef GTKCOMMON_H @@ -67,6 +67,59 @@ namespace elena_lang } }; + // --- WindowBase --- + class WindowWrapper : public GUIControlBase + { + Gtk::Window* _window; + + public: + Gtk::Window* getHandle() { return _window; } + + bool checkHandle(void* param) const + { + return (void*)_window == param; + } + + Rectangle getRectangle() override { return {}; } + void setRectangle(Rectangle rec) override {} + + void show() override + { + _window->show(); + } + + void hide() override + { + _window->hide(); + } + + virtual bool visible() + { + return _window->is_visible(); + } + + void setFocus() override {} + + void refresh() override {} + + WindowWrapper(Gtk::Window* window) + { + _window = window; + } + virtual ~WindowWrapper() + { + delete _window; + } + }; + + // --- WindowApp --- + class WindowApp : public GUIApp + { + public: + void notify(EventBase* event) override; + + int run(GUIControlBase* mainWindow, bool maximized, EventBase* startEvent) override; + }; } #endif // GTKCOMMON_H diff --git a/elenasrc3/gui/gtklinux/gtksdi.cpp b/elenasrc3/gui/gtklinux/gtksdi.cpp index f01c4f1fcd..939c2010c1 100644 --- a/elenasrc3/gui/gtklinux/gtksdi.cpp +++ b/elenasrc3/gui/gtklinux/gtksdi.cpp @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------- // E L E N A P r o j e c t: ELENA IDE // GTK SDI Control Implementation File -// (C)2021-2022, by Aleksey Rakov +// (C)2024, by Aleksey Rakov //--------------------------------------------------------------------------- #include "gtksdi.h" @@ -18,6 +18,13 @@ SDIWindow :: SDIWindow() _childCounter = 0; add(_box); + + _refActionGroup = Gtk::ActionGroup::create(); + _refUIManager = Gtk::UIManager::create(); + + _refUIManager->insert_action_group(_refActionGroup); + + add_accel_group(_refUIManager->get_accel_group()); } void SDIWindow :: populate(int counter, Gtk::Widget** children) @@ -45,5 +52,14 @@ void SDIWindow::setLayout(int client, int top, int bottom, int right, int left) // _box.pack_start(*statusbar, Gtk::PACK_SHRINK); show_all_children(); // !!temporal +} +void SDIWindow :: loadUI(Glib::ustring ui_info, const char* name) +{ + _refUIManager->add_ui_from_string(ui_info); + + Gtk::Widget* pMenubar = _refUIManager->get_widget(name); + if(pMenubar) + _box.pack_start(*pMenubar, Gtk::PACK_SHRINK); } + diff --git a/elenasrc3/gui/gtklinux/gtksdi.h b/elenasrc3/gui/gtklinux/gtksdi.h index 94be2d2984..d9237f0698 100644 --- a/elenasrc3/gui/gtklinux/gtksdi.h +++ b/elenasrc3/gui/gtklinux/gtksdi.h @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------- // E L E N A P r o j e c t: ELENA IDE // GTK SDI Control Header File -// (C)2021-2022, by Aleksey Rakov +// (C)2024, by Aleksey Rakov //--------------------------------------------------------------------------- #ifndef GTKSDI_H @@ -21,9 +21,14 @@ class SDIWindow : public Gtk::Window Gtk::Box _hbox; Gtk::Box _vbox; + Glib::RefPtr _refUIManager; + Glib::RefPtr _refActionGroup; + int _childCounter; Gtk::Widget** _children; + void loadUI(Glib::ustring ui_info, const char* name); + public: void populate(int counter, Gtk::Widget** children); void setLayout(int center, int top, int bottom, int right, int left); diff --git a/elenasrc3/gui/gtklinux/gtktabbar.cpp b/elenasrc3/gui/gtklinux/gtktabbar.cpp index 9d24de92fc..99fefbb205 100644 --- a/elenasrc3/gui/gtklinux/gtktabbar.cpp +++ b/elenasrc3/gui/gtklinux/gtktabbar.cpp @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------- // E L E N A P r o j e c t: ELENA IDE // GTK+ TabBar Implementation File -// (C)2021-2022, by Aleksey Rakov +// (C)2021-2024, by Aleksey Rakov //--------------------------------------------------------------------------- @@ -12,11 +12,11 @@ using namespace elena_lang; // --- TabBar --- TabBar::TabBar() - : Gtk::Notebook() + //: Gtk::Widget() { } -int TabBar :: addTab(const char* name, Gtk::Widget* control) +void TabBar :: addTab(const char* name, Gtk::Widget* control) { if (!get_visible()) show(); diff --git a/elenasrc3/gui/gtklinux/gtktabbar.h b/elenasrc3/gui/gtklinux/gtktabbar.h index ffe445a254..55ea27e1a5 100644 --- a/elenasrc3/gui/gtklinux/gtktabbar.h +++ b/elenasrc3/gui/gtklinux/gtktabbar.h @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------- // E L E N A P r o j e c t: ELENA IDE // GTK+ TabBar Header File -// (C)2021-2022, by Aleksey Rakov +// (C)2024, by Aleksey Rakov //--------------------------------------------------------------------------- #ifndef GTKTABBAR_H @@ -15,7 +15,7 @@ namespace elena_lang class TabBar : public Gtk::Notebook { public: - int addTab(const char* name, Gtk::Widget* control); + void addTab(const char* name, Gtk::Widget* control); TabBar(); }; diff --git a/elenasrc3/gui/gtklinux/gtktextframe.h b/elenasrc3/gui/gtklinux/gtktextframe.h index 543d481d07..b20dd507bf 100644 --- a/elenasrc3/gui/gtklinux/gtktextframe.h +++ b/elenasrc3/gui/gtklinux/gtktextframe.h @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------- // E L E N A P r o j e c t: ELENA IDE // Linux EditFrame container File -// (C)2021-2022, by Aleksey Rakov +// (C)2021-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #ifndef GTKTEXTFRAME_H diff --git a/elenasrc3/gui/gtklinux/gtktextview.cpp b/elenasrc3/gui/gtklinux/gtktextview.cpp index ee7b0bb8a4..30827a69c9 100644 --- a/elenasrc3/gui/gtklinux/gtktextview.cpp +++ b/elenasrc3/gui/gtklinux/gtktextview.cpp @@ -35,15 +35,15 @@ void ViewStyles::release() // --- TextDrawingArea --- -TextViewWindow::TextDrawingArea :: TextDrawingArea(TextViewWindow* view, TextViewModelBase* model, - ViewStyles* styles +TextViewWindow::TextDrawingArea :: TextDrawingArea(TextViewWindow* view/*, TextViewModelBase* model, + ViewStyles* styles*/ ) : Glib::ObjectBase("textview"), Gtk::DrawingArea() { - _model = model; + //_model = model; _needToResize = false; - _styles = styles; + //_styles = styles; } Gtk::SizeRequestMode TextViewWindow::TextDrawingArea :: get_request_mode_vfunc() const @@ -186,98 +186,98 @@ void TextViewWindow::TextDrawingArea :: onResize(int x, int y, int width, int he void TextViewWindow::TextDrawingArea :: paint(Canvas& canvas , int viewWidth, int viewHeight) { - auto docView = _model->docView; - - Point caret = docView->getCaret(false) - docView->getFrame(); - - Style* defaultStyle = _styles->getStyle(STYLE_DEFAULT); - Style* marginStyle = _styles->getStyle(STYLE_MARGIN); - int lineHeight = _styles->getLineHeight(); - int marginWidth = _styles->getMarginWidth() + getLineNumberMargin(); - - if (!defaultStyle->valid) { - _styles->validate(canvas.layout); - - lineHeight = _styles->getLineHeight(); - marginWidth = _styles->getMarginWidth() + getLineNumberMargin(); - - _needToResize = true; - } - // if document size yet to be defined - if (_needToResize) - resizeDocument(viewWidth, viewHeight); - - // draw background - canvas.fillRectangle(0, 0, viewWidth, viewHeight, defaultStyle); - - // draw margin - canvas.fillRectangle(0, 0, marginWidth, viewHeight, marginStyle); - - // draw text - int x = marginWidth; - int y = 1 - lineHeight; - int width = 0; - - Style* style = defaultStyle; - char buffer[0x100]; - StringTextWriter writer(buffer); - pos_t length = 0; - - DocumentView::LexicalReader reader(docView); - reader.readFirst(writer, 255); - do { - style = _styles->getStyle(reader.style); - length = writer.position(); - - // set the text length - buffer[length] = 0; - - if (reader.newLine) { - reader.newLine = false; - - x = marginWidth; - y += lineHeight; - } - if (reader.bandStyle) { - canvas.fillRectangle(x, y, viewWidth, lineHeight + 1, marginStyle); - - reader.bandStyle = false; - } - - width = canvas.TextWidth(style, buffer); - - /*else */canvas.drawText(x, y, buffer, style); - - x += width; - writer.reset(); - } while (reader.readNext(writer, 255)); +// auto docView = _model->docView; +// +// Point caret = docView->getCaret(false) - docView->getFrame(); +// +// Style* defaultStyle = _styles->getStyle(STYLE_DEFAULT); +// Style* marginStyle = _styles->getStyle(STYLE_MARGIN); +// int lineHeight = _styles->getLineHeight(); +// int marginWidth = _styles->getMarginWidth() + getLineNumberMargin(); +// +// if (!defaultStyle->valid) { +// _styles->validate(canvas.layout); +// +// lineHeight = _styles->getLineHeight(); +// marginWidth = _styles->getMarginWidth() + getLineNumberMargin(); +// +// _needToResize = true; +// } +// // if document size yet to be defined +// if (_needToResize) +// resizeDocument(viewWidth, viewHeight); +// +// // draw background +// canvas.fillRectangle(0, 0, viewWidth, viewHeight, defaultStyle); +// +// // draw margin +// canvas.fillRectangle(0, 0, marginWidth, viewHeight, marginStyle); +// +// // draw text +// int x = marginWidth; +// int y = 1 - lineHeight; +// int width = 0; +// +// Style* style = defaultStyle; +// char buffer[0x100]; +// StringTextWriter writer(buffer); +// pos_t length = 0; +// +// DocumentView::LexicalReader reader(docView); +// reader.readFirst(writer, 255); +// do { +// style = _styles->getStyle(reader.style); +// length = writer.position(); +// +// // set the text length +// buffer[length] = 0; +// +// if (reader.newLine) { +// reader.newLine = false; +// +// x = marginWidth; +// y += lineHeight; +// } +// if (reader.bandStyle) { +// canvas.fillRectangle(x, y, viewWidth, lineHeight + 1, marginStyle); +// +// reader.bandStyle = false; +// } +// +// width = canvas.TextWidth(style, buffer); +// +// /*else */canvas.drawText(x, y, buffer, style); +// +// x += width; +// writer.reset(); +// } while (reader.readNext(writer, 255)); } int TextViewWindow::TextDrawingArea :: getLineNumberMargin() { - if (_model->lineNumbersVisible) { - Style* marginStyle = _styles->getStyle(STYLE_MARGIN); - - return marginStyle->avgCharWidth * 5; - } - else return 0; +// if (_model->lineNumbersVisible) { +// Style* marginStyle = _styles->getStyle(STYLE_MARGIN); +// +// return marginStyle->avgCharWidth * 5; +// } + /*else*/ return 0; } void TextViewWindow::TextDrawingArea :: resizeDocument(int width, int height) { - if (_model->isAssigned()) { - Point size; - auto style = _styles->getStyle(STYLE_DEFAULT); - - int marginWidth = getLineNumberMargin(); - - size.x = (width - marginWidth) / style->avgCharWidth; - size.y = height / _styles->getLineHeight(); - - _model->resize(size); - - _needToResize = false; - } +// if (_model->isAssigned()) { +// Point size; +// auto style = _styles->getStyle(STYLE_DEFAULT); +// +// int marginWidth = getLineNumberMargin(); +// +// size.x = (width - marginWidth) / style->avgCharWidth; +// size.y = height / _styles->getLineHeight(); +// +// _model->resize(size); +// +// _needToResize = false; +// } } void TextViewWindow::TextDrawingArea :: update(bool resized) @@ -295,8 +295,8 @@ void TextViewWindow::TextDrawingArea :: update(bool resized) // --- TextViewWindow --- -TextViewWindow :: TextViewWindow(TextViewModelBase* model, ViewStyles* styles) - : _area(this, model, styles) +TextViewWindow :: TextViewWindow(/*TextViewModelBase* model, ViewStyles* styles*/) + : _area(this/*, model, styles*/) { attach(_area, 0, 1, 0, 1, Gtk::EXPAND | Gtk::FILL, Gtk::EXPAND | Gtk::FILL, 0, 0); } diff --git a/elenasrc3/gui/gtklinux/gtktextview.h b/elenasrc3/gui/gtklinux/gtktextview.h index 2741396978..f94d611f8d 100644 --- a/elenasrc3/gui/gtklinux/gtktextview.h +++ b/elenasrc3/gui/gtklinux/gtktextview.h @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------- // E L E N A P r o j e c t: ELENA IDE // GTK TextView Control Header File -// (C)2021-2022, by Aleksey Rakov +// (C)2021-2024, by Aleksey Rakov //--------------------------------------------------------------------------- #ifndef GTKTEXTVIEW_H @@ -78,9 +78,9 @@ namespace elena_lang protected: Glib::RefPtr _text_area; - TextViewModelBase* _model; + //TextViewModelBase* _model; bool _needToResize; - ViewStyles* _styles; + //ViewStyles* _styles; //Overrides: Gtk::SizeRequestMode get_request_mode_vfunc() const override; @@ -104,14 +104,14 @@ namespace elena_lang void paint(Canvas& canvas, int viewWidth, int viewHeight); public: - TextDrawingArea(TextViewWindow* view, TextViewModelBase* model, ViewStyles* styles); + TextDrawingArea(TextViewWindow* view/*, TextViewModelBase* model, ViewStyles* styles*/); }; protected: TextDrawingArea _area; public: - TextViewWindow(TextViewModelBase* model, ViewStyles* styles); + TextViewWindow(/*TextViewModelBase* model, ViewStyles* styles*/); }; } diff --git a/elenasrc3/gui/guicommon.h b/elenasrc3/gui/guicommon.h index 2bd89bf8c7..661f3cba5b 100644 --- a/elenasrc3/gui/guicommon.h +++ b/elenasrc3/gui/guicommon.h @@ -193,6 +193,23 @@ namespace elena_lang virtual ~GUIApp() = default; }; + // --- ConstantIdentifier --- + class TextString : public String + { + public: + text_str operator*() const { return text_str(_string); } + + TextString() + { + _string[0] = 0; + } + TextString(ustr_t message) + { + size_t length = 0x100; + message.copyTo(_string, length); + _string[length] = 0; + } + }; } #endif diff --git a/elenasrc3/gui/text.cpp b/elenasrc3/gui/text.cpp index 1cc67e1f16..db5c77242a 100644 --- a/elenasrc3/gui/text.cpp +++ b/elenasrc3/gui/text.cpp @@ -635,7 +635,7 @@ void Text :: copyLineToX(TextBookmark& bookmark, TextWriter& writer, pos if (!bookmark.moveOn(i)) break; - length -= i; + length -= (pos_t)i; } } diff --git a/elenasrc3/gui/windows/winsdi.cpp b/elenasrc3/gui/windows/winsdi.cpp index 23e4d80945..9d69efb434 100644 --- a/elenasrc3/gui/windows/winsdi.cpp +++ b/elenasrc3/gui/windows/winsdi.cpp @@ -395,7 +395,6 @@ void SDIWindow :: onResizing(RECT* rect) int SDIWindow :: paintBackground() { HDC hdc; - HBRUSH hbrBkgnd; PAINTSTRUCT ps; RECT r; diff --git a/elenasrc3/ide/codeblocks/elide_gtk.cbp b/elenasrc3/ide/codeblocks/elide_gtk.cbp index 39162f75cd..10d5e740d8 100644 --- a/elenasrc3/ide/codeblocks/elide_gtk.cbp +++ b/elenasrc3/ide/codeblocks/elide_gtk.cbp @@ -12,10 +12,10 @@