From 54a7c4c84d05d0f21f0062c05cd1abd89f9211b8 Mon Sep 17 00:00:00 2001 From: arakov Date: Wed, 24 Jul 2024 09:46:38 +0200 Subject: [PATCH] [FIXED] single dispatcher : if an argument is nillable, it can accept nil value --- doc/todo.txt | 3 +- elenasrc3/common/common.h | 30 +++++ elenasrc3/common/lists.h | 8 ++ elenasrc3/elc/clicommon.h | 23 +++- elenasrc3/elc/cliconst.h | 2 +- elenasrc3/elc/compiler.cpp | 78 +++++++---- elenasrc3/elc/compiler.h | 8 +- elenasrc3/elc/compilerlogic.cpp | 2 +- elenasrc3/elc/windows/ntlinker.cpp | 2 +- elenasrc3/engine/bcwriter.h | 1 + elenasrc3/engine/elena.h | 195 --------------------------- elenasrc3/engine/elenaconst.h | 4 +- elenasrc3/engine/langcommon.h | 198 ++++++++++++++++++++++++++++ elenasrc3/engine/syntaxtree.h | 1 + elenasrc3/tools/ecv/ecviewer.cpp | 1 - elenasrc3/tools/ecv/ecviewer.h | 1 + elenasrc3/tools/ecv/windows/ecv.cpp | 3 - elenasrc3/tools/ldoc/ldoc.h | 1 + tests60/sandbox/sandbox.l | 19 ++- 19 files changed, 342 insertions(+), 238 deletions(-) diff --git a/doc/todo.txt b/doc/todo.txt index e59dc6dca..7bca0a5ff 100644 --- a/doc/todo.txt +++ b/doc/todo.txt @@ -19,8 +19,9 @@ In development: prom: posting weekly -------------------------------------- - web server - weather forecast (project setup) - - constructor - single dispatcher; passing nil to single dispatcher (both normal / constructor) -------------------------------------- + - passing nil to single dispatcher (both normal / constructor) + - add support for nilable argument; if the argument is nillable - check for nil and replace with nilValue === Iteration 30 === -------------------------------------- diff --git a/elenasrc3/common/common.h b/elenasrc3/common/common.h index 281ed5660..1ed33d50d 100644 --- a/elenasrc3/common/common.h +++ b/elenasrc3/common/common.h @@ -14,6 +14,36 @@ #include #include +#if defined(_MSC_VER) +#define DISABLE_WARNING_PUSH __pragma(warning( push )) +#define DISABLE_WARNING_POP __pragma(warning( pop )) +#define DISABLE_WARNING(warningNumber) __pragma(warning( disable : warningNumber )) + +#define DISABLE_WARNING_UNREFERENCED_FORMAL_PARAMETER DISABLE_WARNING(4100) +#define DISABLE_WARNING_UNREFERENCED_FUNCTION DISABLE_WARNING(4505) +#define DISABLE_WARNING_UNINITIALIZED_FIELD DISABLE_WARNING(26495) +// other warnings you want to deactivate... + +#elif defined(__GNUC__) || defined(__clang__) +#define DO_PRAGMA(X) _Pragma(#X) +#define DISABLE_WARNING_PUSH DO_PRAGMA(GCC diagnostic push) +#define DISABLE_WARNING_POP DO_PRAGMA(GCC diagnostic pop) +#define DISABLE_WARNING(warningName) DO_PRAGMA(GCC diagnostic ignored #warningName) + +#define DISABLE_WARNING_UNREFERENCED_FORMAL_PARAMETER DISABLE_WARNING(-Wunused-parameter) +#define DISABLE_WARNING_UNREFERENCED_FUNCTION DISABLE_WARNING(-Wunused-function) +#define DISABLE_WARNING_UNINITIALIZED_FIELD DISABLE_WARNING(-Wunused-function) +// other warnings you want to deactivate... + +#else +#define DISABLE_WARNING_PUSH +#define DISABLE_WARNING_POP +#define DISABLE_WARNING_UNREFERENCED_FORMAL_PARAMETER +#define DISABLE_WARNING_UNREFERENCED_FUNCTION +// other warnings you want to deactivate... + +#endif + namespace elena_lang { diff --git a/elenasrc3/common/lists.h b/elenasrc3/common/lists.h index 484c90823..5a995c7fc 100644 --- a/elenasrc3/common/lists.h +++ b/elenasrc3/common/lists.h @@ -718,6 +718,8 @@ namespace elena_lang int count_int() const { return (int)_list.count(); } + short count_short() const { return (short)_list.count(); } + Iterator start() { return _list.start(); @@ -3201,11 +3203,17 @@ namespace elena_lang _allocatedSize = _length = 0; } +DISABLE_WARNING_PUSH +DISABLE_WARNING_UNINITIALIZED_FIELD + CachedList() { _allocated = nullptr; _allocatedSize = _length = 0; } + +DISABLE_WARNING_POP + ~CachedList() { freeobj(_allocated); diff --git a/elenasrc3/elc/clicommon.h b/elenasrc3/elc/clicommon.h index 6f66f17ed..631d6cf22 100644 --- a/elenasrc3/elc/clicommon.h +++ b/elenasrc3/elc/clicommon.h @@ -764,8 +764,27 @@ enum class VirtualType : int AbstractEmbeddableWrapper }; -typedef Pair VirtualMethod; -typedef List VirtualMethodList; +struct VirtualMethod +{ + mssg_t message; + VirtualType type; + int nillableArgs; + + VirtualMethod() + { + message = 0; + type = VirtualType::None; + nillableArgs = 0; + } + VirtualMethod(mssg_t message, VirtualType type, int nillableArgs) + { + this->message = message; + this->type = type; + this->nillableArgs = nillableArgs; + } +}; + +typedef List VirtualMethodList; } diff --git a/elenasrc3/elc/cliconst.h b/elenasrc3/elc/cliconst.h index 98bdf3947..f5d362b44 100644 --- a/elenasrc3/elc/cliconst.h +++ b/elenasrc3/elc/cliconst.h @@ -13,7 +13,7 @@ namespace elena_lang { - #define ELC_REVISION_NUMBER 0x0028 + #define ELC_REVISION_NUMBER 0x0029 #if defined _M_IX86 || _M_X64 diff --git a/elenasrc3/elc/compiler.cpp b/elenasrc3/elc/compiler.cpp index f42bc08ba..36852047e 100644 --- a/elenasrc3/elc/compiler.cpp +++ b/elenasrc3/elc/compiler.cpp @@ -2597,6 +2597,8 @@ void Compiler :: generateMethodAttributes(ClassScope& scope, SyntaxNode node, if (byRefMethod) methodInfo.byRefHandler = byRefMethod; + methodInfo.nillableArgs = node.findChild(SyntaxKey::NillableInfo).arg.reference; + // check duplicates with different visibility scope if (MethodScope::checkHint(methodInfo, MethodHint::Private)) { checkMethodDuplicates(scope, node, message, message & ~STATIC_MESSAGE, false, false); @@ -2770,8 +2772,8 @@ inline mssg_t retrieveMethod(VirtualMethodList& implicitMultimethods, mssg_t mul { return implicitMultimethods.retrieve(multiMethod, [](mssg_t arg, VirtualMethod current) { - return current.value1 == arg; - }).value1; + return current.message == arg; + }).message; } mssg_t Compiler :: defineMultimethod(Scope& scope, mssg_t messageRef, bool extensionMode) @@ -2845,7 +2847,7 @@ inline TypeInfo mapOutputType(MethodInfo info) } void Compiler :: injectVirtualMultimethod(SyntaxNode classNode, SyntaxKey methodType, Scope& scope, - ref_t targetRef, ClassInfo& info, mssg_t multiMethod) + ref_t targetRef, ClassInfo& info, mssg_t multiMethod, int nillableArgs) { MethodInfo methodInfo = {}; @@ -2872,7 +2874,7 @@ void Compiler :: injectVirtualMultimethod(SyntaxNode classNode, SyntaxKey method inherited = false; injectVirtualMultimethod(classNode, methodType, scope, targetRef, info, multiMethod, inherited, - mapOutputType(methodInfo), visibility); + mapOutputType(methodInfo), visibility, nillableArgs); // COMPILER MAGIC : injecting try-multi-method dispather if (_logic->isTryDispatchAllowed(*scope.moduleScope, multiMethod)) { @@ -2890,15 +2892,15 @@ void Compiler :: injectVirtualMethods(SyntaxNode classNode, SyntaxKey methodType // generate implicit mutli methods for (auto it = implicitMultimethods.start(); !it.eof(); ++it) { auto methodInfo = *it; - switch (methodInfo.value2) { + switch (methodInfo.type) { case VirtualType::Multimethod: - injectVirtualMultimethod(classNode, methodType, scope, targetRef, info, methodInfo.value1); + injectVirtualMultimethod(classNode, methodType, scope, targetRef, info, methodInfo.message, methodInfo.nillableArgs); break; case VirtualType::EmbeddableWrapper: - injectVirtualEmbeddableWrapper(classNode, methodType, targetRef, info, methodInfo.value1, false); + injectVirtualEmbeddableWrapper(classNode, methodType, targetRef, info, methodInfo.message, false); break; case VirtualType::AbstractEmbeddableWrapper: - injectVirtualEmbeddableWrapper(classNode, methodType, targetRef, info, methodInfo.value1, true); + injectVirtualEmbeddableWrapper(classNode, methodType, targetRef, info, methodInfo.message, true); break; default: break; @@ -2996,7 +2998,7 @@ void Compiler :: generateMethodDeclarations(ClassScope& scope, SyntaxNode node, current.appendChild(SyntaxKey::Multimethod, multiMethod); if (retrieveMethod(implicitMultimethods, multiMethod) == 0) { - implicitMultimethods.add({ multiMethod, VirtualType::Multimethod }); + implicitMultimethods.add({ multiMethod, VirtualType::Multimethod, current.findChild(SyntaxKey::NillableInfo).arg.value}); thirdPassRequired = true; } } @@ -3016,9 +3018,9 @@ void Compiler :: generateMethodDeclarations(ClassScope& scope, SyntaxNode node, && retrieveMethod(implicitMultimethods, byRefMethod) == 0) { if (SyntaxTree::ifChildExists(current, SyntaxKey::Attribute, V_ABSTRACT)) { - implicitMultimethods.add({ byRefMethod, VirtualType::AbstractEmbeddableWrapper }); + implicitMultimethods.add({ byRefMethod, VirtualType::AbstractEmbeddableWrapper, 0 }); } - else implicitMultimethods.add({ byRefMethod, VirtualType::EmbeddableWrapper }); + else implicitMultimethods.add({ byRefMethod, VirtualType::EmbeddableWrapper, 0 }); thirdPassRequired = true; } } @@ -3577,7 +3579,7 @@ void Compiler :: declareMethodMetaInfo(MethodScope& scope, SyntaxNode node) void Compiler :: declareParameter(MethodScope& scope, SyntaxNode current, bool withoutWeakMessages, bool declarationMode, bool& variadicMode, bool& weakSignature, bool& noSignature, - pos_t& paramCount, ref_t* signature, size_t& signatureLen) + pos_t& paramCount, ref_t* signature, size_t& signatureLen, bool& nillable) { int index = 1 + scope.parameters.count(); @@ -3624,6 +3626,8 @@ void Compiler :: declareParameter(MethodScope& scope, SyntaxNode current, bool w scope.parameters.add(terminal, Parameter(index, paramTypeInfo, sizeInfo.size, paramTypeInfo.typeRef == V_OUTWRAPPER)); + + nillable |= paramTypeInfo.nillable; } void Compiler :: declareVMTMessage(MethodScope& scope, SyntaxNode node, bool withoutWeakMessages, bool declarationMode) @@ -3666,21 +3670,33 @@ void Compiler :: declareVMTMessage(MethodScope& scope, SyntaxNode node, bool wit flags |= FUNCTION_MESSAGE; } + int nillableArgs = 0; + int argMask = 1; bool mixinFunction = false; bool noSignature = true; // NOTE : is similar to weakSignature except if withoutWeakMessages=true // if method has an argument list SyntaxNode current = node.findChild(SyntaxKey::Parameter); while (current != SyntaxKey::None) { if (current == SyntaxKey::Parameter) { + bool nillable = false; declareParameter(scope, current, withoutWeakMessages, declarationMode, variadicMode, weakSignature, noSignature, - paramCount, signature, signatureLen); + paramCount, signature, signatureLen, nillable); + + if (nillable) + { + nillableArgs |= argMask; + } } else break; current = current.nextNode(); + argMask <<= 1; } + if (nillableArgs) + scope.info.nillableArgs = nillableArgs; + // if the signature consists only of generic parameters - ignore it if (weakSignature) signatureLen = 0; @@ -3855,9 +3871,10 @@ ref_t Compiler :: declareClosureParameters(MethodScope& methodScope, SyntaxNode ref_t signatures[ARG_COUNT]; size_t signatureLen = 0; while (argNode == SyntaxKey::Parameter) { + bool dummy = false; declareParameter(methodScope, argNode, false, false, variadicMode, weakSingature, noSignature, - paramCount, signatures, signatureLen); + paramCount, signatures, signatureLen, dummy); if (variadicMode) flags |= VARIADIC_MESSAGE; @@ -3917,6 +3934,9 @@ void Compiler :: declareMethod(MethodScope& methodScope, SyntaxNode node, bool a addTypeInfo(methodScope, node, SyntaxKey::OutputInfo, mapOutputType(methodScope.info)); } + if (methodScope.info.nillableArgs) + node.appendChild(SyntaxKey::NillableInfo, methodScope.info.nillableArgs); + if (methodScope.info.hints) node.appendChild(SyntaxKey::Hints, methodScope.info.hints); @@ -4641,7 +4661,7 @@ void Compiler :: declareArgumentAttributes(MethodScope& scope, SyntaxNode node, bool declarationMode) { SyntaxNode current = node.firstChild(); - TypeAttributes attributes = { false, false, false }; + TypeAttributes attributes = { }; while (current != SyntaxKey::None) { switch (current.key) { case SyntaxKey::Type: @@ -4652,8 +4672,8 @@ void Compiler :: declareArgumentAttributes(MethodScope& scope, SyntaxNode node, // if it is a template type attribute typeInfo = resolveTypeAttribute(scope, current, attributes, declarationMode, false); break; - case SyntaxKey::ArrayType: case SyntaxKey::NullableType: + case SyntaxKey::ArrayType: // if it is a type attribute typeInfo = resolveTypeScope(scope, current, attributes, declarationMode, false); break; @@ -5528,8 +5548,8 @@ TypeInfo Compiler :: resolveTypeScope(Scope& scope, SyntaxNode node, TypeAttribu case SyntaxKey::reference: elementRef = resolveTypeIdentifier(scope, current.identifier(), node.key, declarationMode, allowRole); break; - case SyntaxKey::ArrayType: case SyntaxKey::NullableType: + case SyntaxKey::ArrayType: elementRef = resolvePrimitiveType(*scope.moduleScope, resolveTypeAttribute(scope, current, attributes, declarationMode, allowRole), declarationMode); break; @@ -6473,7 +6493,7 @@ ref_t Compiler :: compileExtensionDispatcher(BuildTreeWriter& writer, NamespaceS for(auto it = scope.extensions.getIt(genericMessage); !it.eof(); it = scope.extensions.nextIt(genericMessage, it)) { auto extInfo = *it; - methods.add(extInfo.value2, { false, 0, 0, genericMessage | FUNCTION_MESSAGE, 0 }); + methods.add(extInfo.value2, { false, 0, 0, genericMessage | FUNCTION_MESSAGE, 0, 0 }); targets.add(extInfo.value2, extInfo.value1); } @@ -9194,7 +9214,7 @@ void Compiler :: compileClosureClass(BuildTreeWriter& writer, ClassScope& scope, classWriter.newNode(SyntaxKey::Class, scope.reference); SyntaxNode classNode = classWriter.CurrentNode(); - injectVirtualMultimethod(classNode, SyntaxKey::Method, scope, scope.reference, scope.info, multiMethod); + injectVirtualMultimethod(classNode, SyntaxKey::Method, scope, scope.reference, scope.info, multiMethod, 0); classWriter.closeNode(); classWriter.closeNode(); @@ -10055,7 +10075,7 @@ inline bool isSingleDispatch(SyntaxNode node, SyntaxKey methodType, mssg_t messa } bool Compiler :: injectVirtualStrongTypedMultimethod(SyntaxNode classNode, SyntaxKey methodType, Scope& scope, - mssg_t message, mssg_t resendMessage, TypeInfo outputInfo, Visibility visibility, bool isExtension) + mssg_t message, mssg_t resendMessage, TypeInfo outputInfo, Visibility visibility, bool isExtension, int nillableArgs) { bool variadicOne = (getFlags(resendMessage) & PREFIX_MESSAGE_MASK) == VARIADIC_MESSAGE; @@ -10095,6 +10115,8 @@ bool Compiler :: injectVirtualStrongTypedMultimethod(SyntaxNode classNode, Synta String arg; for (size_t i = 0; i < len; i++) { + bool isNillable = test(nillableArgs, 1 << i); + arg.copy("$"); arg.appendInt((int)i); @@ -10108,7 +10130,14 @@ bool Compiler :: injectVirtualStrongTypedMultimethod(SyntaxNode classNode, Synta castObject.appendChild(SyntaxKey::Attribute, V_CONVERSION); castObject.appendChild(SyntaxKey::Type, signArgs[i]); castNode.appendChild(SyntaxKey::Message); - castNode.appendChild(SyntaxKey::Expression).appendChild(SyntaxKey::Object).appendChild(SyntaxKey::identifier, arg.str()); + if (isNillable) { + SyntaxNode isNilOp = castNode.appendChild(SyntaxKey::Expression).appendChild(SyntaxKey::IsNilOperation); + isNilOp.appendChild(SyntaxKey::Object).appendChild(SyntaxKey::identifier, arg.str()); + SyntaxNode nilObject = isNilOp.appendChild(SyntaxKey::Expression).appendChild(SyntaxKey::Object); + nilObject.appendChild(SyntaxKey::Attribute, V_FORWARD); + nilObject.appendChild(SyntaxKey::identifier, NILVALUE_FORWARD); + } + else castNode.appendChild(SyntaxKey::Expression).appendChild(SyntaxKey::Object).appendChild(SyntaxKey::identifier, arg.str()); } else operationNode.appendChild(SyntaxKey::Expression).appendChild(SyntaxKey::Object).appendChild(SyntaxKey::identifier, arg.str()); } @@ -10143,7 +10172,8 @@ bool Compiler :: injectVirtualStrongTypedMultimethod(SyntaxNode classNode, Synta } void Compiler :: injectVirtualMultimethod(SyntaxNode classNode, SyntaxKey methodType, Scope& scope, - ref_t targetRef, ClassInfo& info, mssg_t message, bool inherited, TypeInfo outputInfo, Visibility visibility) + ref_t targetRef, ClassInfo& info, mssg_t message, bool inherited, TypeInfo outputInfo, + Visibility visibility, int nillableArgs) { bool isExtension = test(info.header.flags, elExtension); @@ -10160,7 +10190,7 @@ void Compiler :: injectVirtualMultimethod(SyntaxNode classNode, SyntaxKey method // !! temporally do not support variadic arguments if (isSingleDispatch(classNode, methodType, message, resendMessage) && injectVirtualStrongTypedMultimethod(classNode, methodType, scope, message, resendMessage, - outputInfo, visibility, isExtension)) + outputInfo, visibility, isExtension, nillableArgs)) { // mark the message as a signle dispatcher if the class is sealed / closed / class class // and default multi-method was not explicitly declared @@ -10485,7 +10515,7 @@ void Compiler :: declareModuleExtensionDispatcher(NamespaceScope& scope, SyntaxN if (retrieveIndex(genericMethods, genericMessage) == -1) genericMethods.add(genericMessage); - methods.add(extInfo.value2, { false, 0, 0, genericMessage | FUNCTION_MESSAGE, 0 }); + methods.add(extInfo.value2, { false, 0, 0, genericMessage | FUNCTION_MESSAGE, 0, 0 }); targets.add(extInfo.value2, extInfo.value1); } } diff --git a/elenasrc3/elc/compiler.h b/elenasrc3/elc/compiler.h index e2960e74f..d9d92788d 100644 --- a/elenasrc3/elc/compiler.h +++ b/elenasrc3/elc/compiler.h @@ -1538,7 +1538,7 @@ namespace elena_lang void declareParameter(MethodScope& scope, SyntaxNode node, bool withoutWeakMessages, bool declarationMode, bool& variadicMode, bool& weakSignature, bool& noSignature, - pos_t& paramCount, ref_t* signature, size_t& signatureLen); + pos_t& paramCount, ref_t* signature, size_t& signatureLen, bool& nillable); ref_t declareClosureParameters(MethodScope& methodScope, SyntaxNode argNode); @@ -1703,7 +1703,7 @@ namespace elena_lang void injectVirtualCode(SyntaxNode classNode, ClassScope& scope, bool interfaceBased); void injectVirtualMultimethod(SyntaxNode classNode, SyntaxKey methodType, Scope& scope, - ref_t targetRef, ClassInfo& info, mssg_t multiMethod); + ref_t targetRef, ClassInfo& info, mssg_t multiMethod, int nillableArgs); void injectVirtualEmbeddableWrapper(SyntaxNode classNode, SyntaxKey methodType, ref_t targetRef, ClassInfo& info, mssg_t multiMethod, bool abstractOne); @@ -1713,12 +1713,12 @@ namespace elena_lang void injectInitializer(SyntaxNode classNode, SyntaxKey methodType, mssg_t message); bool injectVirtualStrongTypedMultimethod(SyntaxNode classNode, SyntaxKey methodType, Scope& scope, - mssg_t message, mssg_t resendMessage, TypeInfo outputInfo, Visibility visibility, bool isExtension); + mssg_t message, mssg_t resendMessage, TypeInfo outputInfo, Visibility visibility, bool isExtension, int nillableArgs); 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, Scope& scope, - ref_t targetRef, ClassInfo& classInfo, mssg_t message, bool inherited, TypeInfo outputInfo, Visibility visibility); + ref_t targetRef, ClassInfo& classInfo, mssg_t message, bool inherited, TypeInfo outputInfo, Visibility visibility, int nillableArgs); void injectVirtualMultimethod(SyntaxNode classNode, SyntaxKey methodType, Scope& scope, mssg_t message, mssg_t resendMessage, ref_t resendTarget, TypeInfo outputInfo, Visibility visibility, bool isExtension); diff --git a/elenasrc3/elc/compilerlogic.cpp b/elenasrc3/elc/compilerlogic.cpp index c550b5056..384467863 100644 --- a/elenasrc3/elc/compilerlogic.cpp +++ b/elenasrc3/elc/compilerlogic.cpp @@ -2439,7 +2439,7 @@ bool CompilerLogic :: isNeedVerification(ClassInfo& info, VirtualMethodList& imp for (auto it = implicitMultimethods.start(); !it.eof(); it++) { auto vm = *it; - mssg_t message = vm.value1; + mssg_t message = vm.message; auto methodInfo = info.methods.get(message); ref_t outputRef = methodInfo.outputRef; diff --git a/elenasrc3/elc/windows/ntlinker.cpp b/elenasrc3/elc/windows/ntlinker.cpp index 4e347e873..606858524 100644 --- a/elenasrc3/elc/windows/ntlinker.cpp +++ b/elenasrc3/elc/windows/ntlinker.cpp @@ -42,7 +42,7 @@ void WinNtLinker :: writeExecutableHeader(WinNtExecutableImage& image, FileWrite IMAGE_FILE_HEADER header = {}; header.Characteristics = image.characteristics; - header.NumberOfSections = image.imageSections.headers.count(); + header.NumberOfSections = image.imageSections.headers.count_short(); header.TimeDateStamp = (int)time(nullptr); header.PointerToSymbolTable = 0; header.NumberOfSymbols = 0; diff --git a/elenasrc3/engine/bcwriter.h b/elenasrc3/engine/bcwriter.h index a38ee17d7..189d6e24b 100644 --- a/elenasrc3/engine/bcwriter.h +++ b/elenasrc3/engine/bcwriter.h @@ -11,6 +11,7 @@ #include "buildtree.h" #include "bytecode.h" +#include "langcommon.h" namespace elena_lang { diff --git a/elenasrc3/engine/elena.h b/elenasrc3/engine/elena.h index 4a84faa74..f00cc013e 100644 --- a/elenasrc3/engine/elena.h +++ b/elenasrc3/engine/elena.h @@ -1108,33 +1108,6 @@ namespace elena_lang ref_t valueRef; }; - // --- MethodInfo --- - struct MethodInfo - { - bool inherited; - ref_t hints; - ref_t outputRef; - mssg_t multiMethod; - mssg_t byRefHandler; - - MethodInfo() - { - inherited = false; - hints = 0; - outputRef = 0; - multiMethod = 0; - byRefHandler = 0; - } - MethodInfo(bool inherited, ref_t hints, ref_t outputRef, mssg_t multiMethod, mssg_t byRefHandler) : - inherited(inherited), - hints(hints), - outputRef(outputRef), - multiMethod(multiMethod), - byRefHandler(byRefHandler) - { - } - }; - // --- ClassHeader --- struct ClassHeader { @@ -1201,174 +1174,6 @@ namespace elena_lang }; #pragma pack(pop) - // --- SymbolInfo --- - enum class SymbolType : int - { - Symbol = 0, - Singleton, - Constant, - ConstantArray, - }; - - struct SymbolInfo - { - SymbolType symbolType; - ref_t valueRef; - ref_t typeRef; - bool loadableInRuntime; - - SymbolInfo() - { - symbolType = SymbolType::Symbol; - valueRef = typeRef = 0; - loadableInRuntime = false; - } - SymbolInfo(SymbolType symbolType, ref_t valueRef, ref_t typeRef, bool loadableInRuntime) - { - this->symbolType = symbolType; - this->valueRef = valueRef; - this->typeRef = typeRef; - this->loadableInRuntime = loadableInRuntime; - } - - void load(StreamReader* reader) - { - symbolType = (SymbolType)reader->getDWord(); - valueRef = reader->getRef(); - typeRef = reader->getRef(); - loadableInRuntime = reader->getBool(); - } - - void save(StreamWriter* writer) - { - writer->writeDWord((unsigned int)symbolType); - writer->writeRef(valueRef); - writer->writeRef(typeRef); - writer->writeBool(loadableInRuntime); - } - }; - - // --- ClassInfo --- - struct ClassInfo - { - typedef MemoryMap MethodMap; - typedef MemoryMap FieldMap; - typedef MemoryMap StaticFieldMap; - - ClassHeader header; - pos_t size; // Object size - MethodMap methods; - FieldMap fields; - StaticFieldMap statics; - ClassAttributes attributes; - - static void loadStaticFields(StreamReader* reader, StaticFieldMap& statics) - { - pos_t statCount = reader->getPos(); - for (pos_t i = 0; i < statCount; i++) { - IdentifierString fieldName; - reader->readString(fieldName); - StaticFieldInfo fieldInfo; - reader->read(&fieldInfo, sizeof(fieldInfo)); - - statics.add(*fieldName, fieldInfo); - } - } - - static void saveStaticFields(StreamWriter* writer, StaticFieldMap& statics) - { - writer->writePos(statics.count()); - statics.forEach(writer, [](StreamWriter* writer, ustr_t name, StaticFieldInfo info) - { - writer->writeString(name); - writer->write(&info, sizeof(info)); - }); - } - - void save(StreamWriter* writer, bool headerAndSizeOnly = false) - { - writer->write(&header, sizeof(ClassHeader)); - writer->writeDWord(size); - if (!headerAndSizeOnly) { - writer->writePos(fields.count()); - fields.forEach(writer, [](StreamWriter* writer, ustr_t name, FieldInfo info) - { - writer->writeString(name); - writer->write(&info, sizeof(info)); - }); - - writer->writePos(methods.count()); - methods.forEach(writer, [](StreamWriter* writer, mssg_t message, MethodInfo info) - { - writer->writeDWord(message); - writer->write(&info, sizeof(info)); - }); - - writer->writePos(attributes.count()); - attributes.forEach(writer, [](StreamWriter* writer, ClassAttributeKey key, ref_t reference) - { - writer->write(&key, sizeof(key)); - writer->writeRef(reference); - }); - - saveStaticFields(writer, statics); - } - } - - void load(StreamReader* reader, bool headerAndSizeOnly = false, bool fieldsOnly = false) - { - reader->read(&header, sizeof(ClassHeader)); - size = reader->getDWord(); - if (!headerAndSizeOnly) { - pos_t fieldCount = reader->getPos(); - for (pos_t i = 0; i < fieldCount; i++) { - IdentifierString fieldName; - reader->readString(fieldName); - FieldInfo fieldInfo; - reader->read(&fieldInfo, sizeof(fieldInfo)); - - fields.add(*fieldName, fieldInfo); - } - - if (!fieldsOnly) { - pos_t methodsCount = reader->getPos(); - for (pos_t i = 0; i < methodsCount; i++) { - mssg_t message = reader->getDWord(); - MethodInfo methodInfo; - reader->read(&methodInfo, sizeof(MethodInfo)); - - methods.add(message, methodInfo); - } - pos_t attrCount = reader->getPos(); - for (pos_t i = 0; i < attrCount; i++) { - ClassAttributeKey key; - reader->read(&key, sizeof(key)); - - ref_t reference = reader->getRef(); - - attributes.add(key, reference); - } - - loadStaticFields(reader, statics); - } - } - } - - ClassInfo() : - header({}), - size(0), - methods({}), - fields({ -1 }), - statics({ -1 }), - attributes(0) - { - //header.staticSize = 0; - //header.parentRef = header.classRef = 0; - //header.flags = 0; - //header.count = size = 0; - } - }; - // --- ExceptionBase --- class ExceptionBase {}; diff --git a/elenasrc3/engine/elenaconst.h b/elenasrc3/engine/elenaconst.h index f1ba2fec9..1d5faed3e 100644 --- a/elenasrc3/engine/elenaconst.h +++ b/elenasrc3/engine/elenaconst.h @@ -13,7 +13,7 @@ namespace elena_lang { // --- Common ELENA Engine constants --- #define ENGINE_MAJOR_VERSION 6 // ELENA Engine version - #define ENGINE_MINOR_VERSION 2 + #define ENGINE_MINOR_VERSION 3 constexpr auto LINE_LEN = 0x1000; // the maximal source line length constexpr auto IDENTIFIER_LEN = 0x0300; // the maximal identifier length @@ -38,7 +38,7 @@ namespace elena_lang // --- ELENA Module structure constants --- constexpr auto ELENA_SIGNITURE = "ELENA."; // the stand alone image constexpr auto ELENA_VM_SIGNITURE = "VM.ELENA."; // the stand alone image - constexpr auto MODULE_SIGNATURE = "ELENA.0612"; // the module version + constexpr auto MODULE_SIGNATURE = "ELENA.0620"; // the module version constexpr auto DEBUG_MODULE_SIGNATURE = "ED.06"; // --- ELENA core module names --- diff --git a/elenasrc3/engine/langcommon.h b/elenasrc3/engine/langcommon.h index 74f23653f..c35dfec89 100644 --- a/elenasrc3/engine/langcommon.h +++ b/elenasrc3/engine/langcommon.h @@ -59,6 +59,204 @@ namespace elena_lang Yieldable = 0x80000000, }; + // --- MethodInfo --- + struct MethodInfo + { + bool inherited; + ref_t hints; + ref_t outputRef; + mssg_t multiMethod; + mssg_t byRefHandler; + int nillableArgs; + + MethodInfo() + { + inherited = false; + hints = 0; + outputRef = 0; + multiMethod = 0; + byRefHandler = 0; + nillableArgs = 0; + } + MethodInfo(bool inherited, ref_t hints, ref_t outputRef, mssg_t multiMethod, mssg_t byRefHandler, int nillableArgs) : + inherited(inherited), + hints(hints), + outputRef(outputRef), + multiMethod(multiMethod), + byRefHandler(byRefHandler), + nillableArgs(nillableArgs) + { + } + }; + + // --- SymbolInfo --- + enum class SymbolType : int + { + Symbol = 0, + Singleton, + Constant, + ConstantArray, + }; + + struct SymbolInfo + { + SymbolType symbolType; + ref_t valueRef; + ref_t typeRef; + bool loadableInRuntime; + + SymbolInfo() + { + symbolType = SymbolType::Symbol; + valueRef = typeRef = 0; + loadableInRuntime = false; + } + SymbolInfo(SymbolType symbolType, ref_t valueRef, ref_t typeRef, bool loadableInRuntime) + { + this->symbolType = symbolType; + this->valueRef = valueRef; + this->typeRef = typeRef; + this->loadableInRuntime = loadableInRuntime; + } + + void load(StreamReader* reader) + { + symbolType = (SymbolType)reader->getDWord(); + valueRef = reader->getRef(); + typeRef = reader->getRef(); + loadableInRuntime = reader->getBool(); + } + + void save(StreamWriter* writer) + { + writer->writeDWord((unsigned int)symbolType); + writer->writeRef(valueRef); + writer->writeRef(typeRef); + writer->writeBool(loadableInRuntime); + } + }; + + // --- ClassInfo --- + struct ClassInfo + { + typedef MemoryMap MethodMap; + typedef MemoryMap FieldMap; + typedef MemoryMap StaticFieldMap; + + ClassHeader header; + pos_t size; // Object size + MethodMap methods; + FieldMap fields; + StaticFieldMap statics; + ClassAttributes attributes; + + static void loadStaticFields(StreamReader* reader, StaticFieldMap& statics) + { + pos_t statCount = reader->getPos(); + for (pos_t i = 0; i < statCount; i++) { + IdentifierString fieldName; + reader->readString(fieldName); + StaticFieldInfo fieldInfo; + reader->read(&fieldInfo, sizeof(fieldInfo)); + + statics.add(*fieldName, fieldInfo); + } + } + + static void saveStaticFields(StreamWriter* writer, StaticFieldMap& statics) + { + writer->writePos(statics.count()); + statics.forEach(writer, [](StreamWriter* writer, ustr_t name, StaticFieldInfo info) + { + writer->writeString(name); + writer->write(&info, sizeof(info)); + }); + } + + void save(StreamWriter* writer, bool headerAndSizeOnly = false) + { + writer->write(&header, sizeof(ClassHeader)); + writer->writeDWord(size); + if (!headerAndSizeOnly) { + writer->writePos(fields.count()); + fields.forEach(writer, [](StreamWriter* writer, ustr_t name, FieldInfo info) + { + writer->writeString(name); + writer->write(&info, sizeof(info)); + }); + + writer->writePos(methods.count()); + methods.forEach(writer, [](StreamWriter* writer, mssg_t message, MethodInfo info) + { + writer->writeDWord(message); + writer->write(&info, sizeof(info)); + }); + + writer->writePos(attributes.count()); + attributes.forEach(writer, [](StreamWriter* writer, ClassAttributeKey key, ref_t reference) + { + writer->write(&key, sizeof(key)); + writer->writeRef(reference); + }); + + saveStaticFields(writer, statics); + } + } + + void load(StreamReader* reader, bool headerAndSizeOnly = false, bool fieldsOnly = false) + { + reader->read(&header, sizeof(ClassHeader)); + size = reader->getDWord(); + if (!headerAndSizeOnly) { + pos_t fieldCount = reader->getPos(); + for (pos_t i = 0; i < fieldCount; i++) { + IdentifierString fieldName; + reader->readString(fieldName); + FieldInfo fieldInfo; + reader->read(&fieldInfo, sizeof(fieldInfo)); + + fields.add(*fieldName, fieldInfo); + } + + if (!fieldsOnly) { + pos_t methodsCount = reader->getPos(); + for (pos_t i = 0; i < methodsCount; i++) { + mssg_t message = reader->getDWord(); + MethodInfo methodInfo; + reader->read(&methodInfo, sizeof(MethodInfo)); + + methods.add(message, methodInfo); + } + pos_t attrCount = reader->getPos(); + for (pos_t i = 0; i < attrCount; i++) { + ClassAttributeKey key; + reader->read(&key, sizeof(key)); + + ref_t reference = reader->getRef(); + + attributes.add(key, reference); + } + + loadStaticFields(reader, statics); + } + } + } + + ClassInfo() : + header({}), + size(0), + methods({}), + fields({ -1 }), + statics({ -1 }), + attributes(0) + { + //header.staticSize = 0; + //header.parentRef = header.classRef = 0; + //header.flags = 0; + //header.count = size = 0; + } + }; + // === ELENA Error codes === constexpr auto errInvalidSyntax = 4; constexpr auto errCBrExpectedSyntax = 9; diff --git a/elenasrc3/engine/syntaxtree.h b/elenasrc3/engine/syntaxtree.h index e8ee04818..79cfd002b 100644 --- a/elenasrc3/engine/syntaxtree.h +++ b/elenasrc3/engine/syntaxtree.h @@ -205,6 +205,7 @@ namespace elena_lang ProxyDispatcher = 0x000112, EnumNameArgParameter = 0x000113, EnumArgParameter = 0x000114, + NillableInfo = 0x000115, Column = 0x000201, Row = 0x000202, diff --git a/elenasrc3/tools/ecv/ecviewer.cpp b/elenasrc3/tools/ecv/ecviewer.cpp index d75059819..1e2fbab14 100644 --- a/elenasrc3/tools/ecv/ecviewer.cpp +++ b/elenasrc3/tools/ecv/ecviewer.cpp @@ -9,7 +9,6 @@ #include "ecviewer.h" #include "ecvconst.h" #include "module.h" -#include "langcommon.h" using namespace elena_lang; diff --git a/elenasrc3/tools/ecv/ecviewer.h b/elenasrc3/tools/ecv/ecviewer.h index 871615677..0b935394b 100644 --- a/elenasrc3/tools/ecv/ecviewer.h +++ b/elenasrc3/tools/ecv/ecviewer.h @@ -12,6 +12,7 @@ #include "elena.h" #include "bytecode.h" #include "libman.h" +#include "langcommon.h" namespace elena_lang { diff --git a/elenasrc3/tools/ecv/windows/ecv.cpp b/elenasrc3/tools/ecv/windows/ecv.cpp index dc5e7e8c2..798514735 100644 --- a/elenasrc3/tools/ecv/windows/ecv.cpp +++ b/elenasrc3/tools/ecv/windows/ecv.cpp @@ -15,9 +15,6 @@ using namespace elena_lang; -constexpr auto PLATFORM_CATEGORY = "configuration/platform"; -constexpr auto LIB_PATH = "project/libpath"; - #ifdef _M_IX86 constexpr auto PLATFORM_KEY = "Win_x86"; diff --git a/elenasrc3/tools/ldoc/ldoc.h b/elenasrc3/tools/ldoc/ldoc.h index dcad273f3..68128074b 100644 --- a/elenasrc3/tools/ldoc/ldoc.h +++ b/elenasrc3/tools/ldoc/ldoc.h @@ -11,6 +11,7 @@ #include "elena.h" #include "libman.h" +#include "langcommon.h" namespace elena_lang { diff --git a/tests60/sandbox/sandbox.l b/tests60/sandbox/sandbox.l index d49144976..e0957d632 100644 --- a/tests60/sandbox/sandbox.l +++ b/tests60/sandbox/sandbox.l @@ -1,8 +1,21 @@ import extensions; -public program() +B; + +A { - int n := 3; + B b; + + constructor new(B? b) + { + this b := b + } +} - int r := n + 2; +public program() +{ + var b := nil; +// var t := A; +// var a1 := t.new(b); + var a2 := A.new(b); } \ No newline at end of file