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