Skip to content

Commit

Permalink
[ADDED] #637 : bt optimization 4 unit test
Browse files Browse the repository at this point in the history
  • Loading branch information
arakov committed Jul 25, 2024
1 parent 54a7c4c commit 14f4a64
Show file tree
Hide file tree
Showing 9 changed files with 159 additions and 47 deletions.
2 changes: 0 additions & 2 deletions doc/todo.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ In development:
--------------------------------------
- web server - weather forecast (project setup)
--------------------------------------
- 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 ===
--------------------------------------
Expand Down
3 changes: 2 additions & 1 deletion elenasrc3/elc/clicommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -416,8 +416,9 @@ enum class ExpressionAttribute : pos64_t
RetrievingType = 0x00010000000,
RetValExpected = 0x00020000000,
CheckShortCircle = 0x00040000000,
LookaheadExprMode = 0x00080000000,
LookaheadExprMode = 0x00080000000,
Class = 0x00100000000,
Nillable = 0x00200000000,
OutRefOp = 0x01000000000,
WithVariadicArgCast = 0x02008000000,
DistributedForward = 0x04000000000,
Expand Down
2 changes: 1 addition & 1 deletion elenasrc3/elc/cliconst.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

namespace elena_lang
{
#define ELC_REVISION_NUMBER 0x0029
#define ELC_REVISION_NUMBER 0x002A

#if defined _M_IX86 || _M_X64

Expand Down
70 changes: 44 additions & 26 deletions elenasrc3/elc/compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7992,7 +7992,7 @@ ObjectInfo Compiler :: compileRedirect(BuildTreeWriter& writer, CodeScope& codeS
signRef, arguments, EAttr::None, &updatedOuterArgs);

if (outputRef) {
expression.convertObject(node, expression.saveToTempLocal(retVal), outputRef, true, false);
expression.convertObject(node, expression.saveToTempLocal(retVal), outputRef, true, false, false);
}

expression.scope.syncStack();
Expand Down Expand Up @@ -8056,8 +8056,9 @@ ObjectInfo Compiler :: compileResendCode(BuildTreeWriter& writer, CodeScope& cod

mssg_t messageRef = mapMessage(codeScope, current, propertyMode, codeScope.isExtension(), false);

int resolvedNillableArgs = 0;
mssg_t resolvedMessage = _logic->resolveSingleDispatch(*codeScope.moduleScope,
retrieveType(codeScope, source), messageRef);
retrieveType(codeScope, source), messageRef, resolvedNillableArgs);

ref_t expectedSignRef = 0;
if (resolvedMessage)
Expand All @@ -8068,7 +8069,7 @@ ObjectInfo Compiler :: compileResendCode(BuildTreeWriter& writer, CodeScope& cod

Expression::ArgumentListType argListType = Expression::ArgumentListType::Normal;
ref_t implicitSignatureRef = expression.compileMessageArguments(current, arguments, expectedSignRef,
EAttr::NoPrimitives, &updatedOuterArgs, argListType);
EAttr::NoPrimitives, &updatedOuterArgs, argListType, resolvedNillableArgs);

EAttr opMode = EAttr::CheckShortCircle;
if (argListType == Expression::ArgumentListType::VariadicArgList || argListType == Expression::ArgumentListType::VariadicArgListWithTypecasting) {
Expand Down Expand Up @@ -11238,6 +11239,7 @@ ObjectInfo Compiler::Expression :: compile(SyntaxNode node, ref_t targetRef, EAt
bool noPrimitives = EAttrs::testAndExclude(mode, EAttr::NoPrimitives);
bool dynamicRequired = EAttrs::testAndExclude(mode, EAttr::DynamicObject);
bool lookaheadMode = EAttrs::testAndExclude(mode, EAttr::LookaheadExprMode) && compiler->_lookaheadOptMode;
bool nillableArg = EAttrs::test(mode, EAttr::Nillable);

ObjectInfo retVal;

Expand Down Expand Up @@ -11303,7 +11305,7 @@ ObjectInfo Compiler::Expression :: compile(SyntaxNode node, ref_t targetRef, EAt
case SyntaxKey::OrOperation:
retVal = compileBoolOperation(current, (int)current.key - OPERATOR_MAKS);
if (targetRef)
typecastObject(current, retVal, targetRef);
typecastObject(current, retVal, targetRef, EAttrs::test(mode, EAttr::Nillable));

break;
case SyntaxKey::IndexerOperation:
Expand Down Expand Up @@ -11400,7 +11402,7 @@ ObjectInfo Compiler::Expression :: compile(SyntaxNode node, ref_t targetRef, EAt
}

retVal = validateObject(node, retVal, targetRef,
noPrimitives, paramMode, dynamicRequired);
noPrimitives, paramMode, dynamicRequired, nillableArg);

return retVal;
}
Expand Down Expand Up @@ -11486,16 +11488,17 @@ ObjectInfo Compiler::Expression :: compileMessageOperationR(SyntaxNode node, Syn
arguments.add(source);

mssg_t resolvedMessage = 0;
int resolvedNillableArgs = 0;

EAttr paramMode = EAttr::NoPrimitives;
if (source.mode != TargetMode::Weak) {
resolvedMessage = compiler->_logic->resolveSingleDispatch(*scope.moduleScope,
compiler->retrieveType(scope, source), messageRef);
compiler->retrieveType(scope, source), messageRef, resolvedNillableArgs);
if (!resolvedMessage && !ignoreVariadics) {
ref_t variadicMssg = resolveVariadicMessage(scope, messageRef);

resolvedMessage = compiler->_logic->resolveSingleDispatch(*scope.moduleScope,
compiler->retrieveType(scope, source), variadicMssg);
compiler->retrieveType(scope, source), variadicMssg, resolvedNillableArgs);
if (resolvedMessage) {
messageRef = variadicMssg;
paramMode = paramMode | EAttr::WithVariadicArg;
Expand All @@ -11509,7 +11512,7 @@ ObjectInfo Compiler::Expression :: compileMessageOperationR(SyntaxNode node, Syn

ArgumentListType argListType = ArgumentListType::Normal;
ref_t implicitSignatureRef = compileMessageArguments(messageNode, arguments, expectedSignRef, paramMode,
updatedOuterArgs, argListType);
updatedOuterArgs, argListType, resolvedNillableArgs);

EAttr opMode = EAttr::None;
if (argListType == ArgumentListType::VariadicArgList || argListType == ArgumentListType::VariadicArgListWithTypecasting) {
Expand Down Expand Up @@ -11600,7 +11603,7 @@ ObjectInfo Compiler::Expression :: compileMessageOperation(SyntaxNode node,
case TargetMode::External:
case TargetMode::WinApi:
{
compileMessageArguments(current, arguments, 0, EAttr::None, nullptr, argListType);
compileMessageArguments(current, arguments, 0, EAttr::None, nullptr, argListType, 0);
if (argListType != ArgumentListType::Normal)
scope.raiseError(errInvalidOperation, current);

Expand All @@ -11610,7 +11613,7 @@ ObjectInfo Compiler::Expression :: compileMessageOperation(SyntaxNode node,
}
case TargetMode::CreatingArray:
{
compileMessageArguments(current, arguments, 0, EAttr::NoPrimitives, nullptr, argListType);
compileMessageArguments(current, arguments, 0, EAttr::NoPrimitives, nullptr, argListType, 0);
if (argListType != ArgumentListType::Normal)
scope.raiseError(errInvalidOperation, current);

Expand All @@ -11619,7 +11622,7 @@ ObjectInfo Compiler::Expression :: compileMessageOperation(SyntaxNode node,
}
case TargetMode::Creating:
{
ref_t signRef = compileMessageArguments(current, arguments, 0, EAttr::NoPrimitives, nullptr, argListType);
ref_t signRef = compileMessageArguments(current, arguments, 0, EAttr::NoPrimitives, nullptr, argListType, 0);
if (argListType != ArgumentListType::Normal)
scope.raiseError(errInvalidOperation, current);

Expand All @@ -11635,7 +11638,7 @@ ObjectInfo Compiler::Expression :: compileMessageOperation(SyntaxNode node,
default:
{
// NOTE : the operation target shouldn't be a primtive type
source = validateObject(node, source, 0, true, true, false);
source = validateObject(node, source, 0, true, true, false, false);

current = current.nextNode();

Expand All @@ -11661,7 +11664,7 @@ ObjectInfo Compiler::Expression :: compilePropertyOperation(SyntaxNode node, ref
scope.raiseError(errInvalidOperation, node);

// NOTE : the operation target shouldn't be a primtive type
source = validateObject(node, source, 0, true, true, false);
source = validateObject(node, source, 0, true, true, false, false);

current = current.nextNode();

Expand Down Expand Up @@ -11950,13 +11953,25 @@ inline mssg_t mapTypecasting(ModuleBase* module, ref_t targetRef)
return encodeMessage(actionRef, 1, CONVERSION_MESSAGE);
}

ObjectInfo Compiler::Expression :: typecastObject(SyntaxNode node, ObjectInfo source, ref_t targetRef)
ObjectInfo Compiler::Expression :: typecastObject(SyntaxNode node, ObjectInfo source, ref_t targetRef, bool nillable)
{
if (targetRef == scope.moduleScope->buildins.superReference)
return source;

mssg_t typecastMssg = mapTypecasting(scope.module, targetRef);

// if it is a weak argument
if (nillable && !isBoxingRequired(source, false)) {
if (!source.typeInfo.typeRef || source.typeInfo.typeRef == scope.moduleScope->buildins.superReference || source.typeInfo.nillable) {
IdentifierString nilForward(FORWARD_PREFIX_NS, NILVALUE_FORWARD);
writeObjectInfo(scope.mapGlobal(*nilForward));
writer->appendNode(BuildKey::SavingInStack);
writeObjectInfo(source, node);
writer->appendNode(BuildKey::NilOp, ISNIL_OPERATOR_ID);
source = saveToTempLocal({ ObjectKind::Object });
}
}

ArgumentsInfo arguments;
arguments.add(source);

Expand Down Expand Up @@ -12591,7 +12606,7 @@ ObjectInfo Compiler::Expression :: compileTupleAssigning(SyntaxNode node)
}

ObjectInfo Compiler::Expression :: validateObject(SyntaxNode node, ObjectInfo retVal, ref_t targetRef, bool noPrimitives,
bool paramMode, bool dynamicRequired)
bool paramMode, bool dynamicRequired, bool nillable)
{
if (!targetRef && retVal.typeInfo.isPrimitive() && noPrimitives) {
targetRef = compiler->resolveStrongType(scope, retVal.typeInfo);
Expand All @@ -12608,7 +12623,7 @@ ObjectInfo Compiler::Expression :: validateObject(SyntaxNode node, ObjectInfo re
return retVal;
}

retVal = convertObject(node, retVal, targetRef, dynamicRequired, false);
retVal = convertObject(node, retVal, targetRef, dynamicRequired, false, nillable);
if (paramMode && hasToBePresaved(retVal))
retVal = saveToTempLocal(retVal);
}
Expand Down Expand Up @@ -12671,7 +12686,7 @@ ObjectInfo Compiler::Expression :: compileNewOp(SyntaxNode node, ObjectInfo sour
}

ref_t Compiler::Expression :: compileMessageArguments(SyntaxNode current, ArgumentsInfo& arguments, ref_t expectedSignRef, EAttr mode,
ArgumentsInfo* updatedOuterArgs, ArgumentListType& argListType)
ArgumentsInfo* updatedOuterArgs, ArgumentListType& argListType, int nillableArgs)
{
bool variadicArg = EAttrs::testAndExclude(mode, EAttr::WithVariadicArg);

Expand All @@ -12688,17 +12703,19 @@ ref_t Compiler::Expression :: compileMessageArguments(SyntaxNode current, Argume
if (expectedSignRef)
signatureMaxLength = scope.module->resolveSignature(expectedSignRef, signatures);

int argMask = 1;
while (current != SyntaxKey::None) {
if (current == SyntaxKey::Expression) {
if (variadicArg && signatureLen == signatureMaxLength && signatureLen > 0) {
// for variadic last argument - stay at the same position
signatureLen--;
argMask >>= 1;
}

// 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);
paramMode | (test(nillableArgs, argMask) ? EAttr::Nillable : EAttr::None), updatedOuterArgs);

if ((argInfo.mode == TargetMode::UnboxingVarArgument || argInfo.mode == TargetMode::UnboxingAndTypecastingVarArgument) && signatureLen < ARG_COUNT) {
if (argInfo.typeInfo.elementRef) {
Expand All @@ -12724,6 +12741,7 @@ ref_t Compiler::Expression :: compileMessageArguments(SyntaxNode current, Argume
else signatures[signatureLen++] = superReference;
}
arguments.add(argInfo);
argMask <<= 1;
}

current = current.nextNode();
Expand Down Expand Up @@ -12900,7 +12918,7 @@ ObjectInfo Compiler::Expression :: compileNewArrayOp(SyntaxNode node, ObjectInfo
}

ObjectInfo Compiler::Expression :: convertObject(SyntaxNode node, ObjectInfo source,
ref_t targetRef, bool dynamicRequired, bool withoutBoxing)
ref_t targetRef, bool dynamicRequired, bool withoutBoxing, bool nillable)
{
if (!compiler->_logic->isCompatible(*scope.moduleScope, { targetRef }, source.typeInfo, false)) {
if (source.kind == ObjectKind::Default) {
Expand Down Expand Up @@ -13011,7 +13029,7 @@ ObjectInfo Compiler::Expression :: convertObject(SyntaxNode node, ObjectInfo sou

return source;
}
else source = typecastObject(node, source, targetRef);
else source = typecastObject(node, source, targetRef, nillable);
}

return source;
Expand Down Expand Up @@ -14060,7 +14078,7 @@ ObjectInfo Compiler::Expression :: compileMessageOperationR(ObjectInfo target, S
case TargetMode::Casting:
{
ArgumentListType argListType = ArgumentListType::Normal;
compileMessageArguments(messageNode, arguments, 0, EAttr::NoPrimitives, nullptr, argListType);
compileMessageArguments(messageNode, arguments, 0, EAttr::NoPrimitives, nullptr, argListType, 0);
if (arguments.count() == 1) {
ref_t targetRef = compiler->resolveStrongType(scope, target.typeInfo);

Expand All @@ -14070,7 +14088,7 @@ ObjectInfo Compiler::Expression :: compileMessageOperationR(ObjectInfo target, S

return arguments[0];
}
else return convertObject(messageNode, arguments[0], targetRef, false, true);
else return convertObject(messageNode, arguments[0], targetRef, false, true, false);
}
else scope.raiseError(errInvalidOperation, messageNode);
break;
Expand All @@ -14080,7 +14098,7 @@ ObjectInfo Compiler::Expression :: compileMessageOperationR(ObjectInfo target, S
ArgumentsInfo updatedOuterArgs;

// NOTE : the operation target shouldn't be a primitive type
ObjectInfo source = validateObject(messageNode, target, 0, true, true, false);
ObjectInfo source = validateObject(messageNode, target, 0, true, true, false, false);

return compileMessageOperationR(messageNode, messageNode, source, arguments, &updatedOuterArgs, 0,
propertyMode, false, false, EAttr::None);
Expand Down Expand Up @@ -15079,7 +15097,7 @@ ObjectInfo Compiler::Expression :: boxVariadicArgument(ObjectInfo info)
if (info.typeInfo.typeRef && info.typeInfo.typeRef != typeRef) {
// if the conversion is required
ObjectInfo convInfo = convertObject({}, destLocal,
info.typeInfo.typeRef, false, false);
info.typeInfo.typeRef, false, false, false);

compileAssigningOp(destLocal, convInfo, dummy);

Expand All @@ -15093,7 +15111,7 @@ void Compiler::Expression :: compileAssigning(SyntaxNode node, ObjectInfo target
{
if (!noConversion) {
source = convertObject(node, source,
compiler->resolveStrongType(scope, target.typeInfo), false, false);
compiler->resolveStrongType(scope, target.typeInfo), false, false, false);
}

bool nillableOp = false;
Expand All @@ -15107,7 +15125,7 @@ void Compiler::Expression :: compileAssigning(SyntaxNode node, ObjectInfo target
void Compiler::Expression :: compileConverting(SyntaxNode node, ObjectInfo source, ref_t targetRef, bool stackSafe)
{
if (targetRef && targetRef != V_AUTO) {
source = convertObject(node, source, targetRef, false, false);
source = convertObject(node, source, targetRef, false, false, false);

scope.syncStack();
}
Expand Down
9 changes: 5 additions & 4 deletions elenasrc3/elc/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -1256,17 +1256,18 @@ namespace elena_lang

ObjectInfo compileNewOp(SyntaxNode node, ObjectInfo source, ref_t signRef, ArgumentsInfo& arguments);

ObjectInfo typecastObject(SyntaxNode node, ObjectInfo source, ref_t targetRef);
ObjectInfo typecastObject(SyntaxNode node, ObjectInfo source, ref_t targetRef, bool nillable);

ObjectInfo validateObject(SyntaxNode node, ObjectInfo retVal,
ref_t targetRef, bool noPrimitives, bool paramMode, bool dynamicRequired);
ref_t targetRef, bool noPrimitives, bool paramMode, bool dynamicRequired, bool nillable);

ObjectInfo compileExternalOp(SyntaxNode node, ref_t externalRef, bool stdCall,
ArgumentsInfo& arguments, ref_t expectedRef);

ObjectInfo compileNewArrayOp(SyntaxNode node, ObjectInfo source, ref_t targetRef, ArgumentsInfo& arguments);

ObjectInfo convertObject(SyntaxNode node, ObjectInfo source, ref_t targetRef, bool dynamicRequired, bool withoutBoxing);
ObjectInfo convertObject(SyntaxNode node, ObjectInfo source, ref_t targetRef, bool dynamicRequired,
bool withoutBoxing, bool nillable);

ObjectInfo compileMessageOperation(SyntaxNode node, ObjectInfo target, MessageResolution resolution, ref_t implicitSignatureRef,
ArgumentsInfo& arguments, ExpressionAttributes mode, ArgumentsInfo* updatedOuterArgs);
Expand All @@ -1279,7 +1280,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, ArgumentListType& argListType);
ArgumentsInfo* updatedOuterArgs, ArgumentListType& argListType, int nillableArgs);

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,
Expand Down
14 changes: 10 additions & 4 deletions elenasrc3/elc/compilerlogic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2349,6 +2349,7 @@ bool CompilerLogic :: checkMethod(ClassInfo& info, mssg_t message, CheckMethodRe
}

result.stackSafe = test(methodInfo.hints, (ref_t)MethodHint::Stacksafe);
result.nillableArgs = methodInfo.nillableArgs;

if (test(methodInfo.hints, (ref_t)MethodHint::Constant)) {
result.constRef = info.attributes.get({ message, ClassAttribute::ConstantMethod });
Expand Down Expand Up @@ -2577,20 +2578,25 @@ void CompilerLogic :: generateVirtualDispatchMethod(ModuleScopeBase& scope, ref_
methods.add({ mssg, methodInfo.outputRef });
}
}

}

mssg_t CompilerLogic :: resolveSingleDispatch(ModuleScopeBase& scope, ref_t reference, ref_t weakMessage)
mssg_t CompilerLogic :: resolveSingleDispatch(ModuleScopeBase& scope, ref_t reference, ref_t weakMessage, int& nillableArgs)
{
if (!reference)
return 0;

ClassInfo info;
if (defineClassInfo(scope, info, reference)) {
return info.attributes.get({ weakMessage, ClassAttribute::SingleDispatch });
mssg_t dispatcher = info.attributes.get({ weakMessage, ClassAttribute::SingleDispatch });
if (dispatcher) {
CheckMethodResult result;
if (checkMethod(info, dispatcher, result))
nillableArgs = result.nillableArgs;
}

return dispatcher;
}
else return 0;

}

inline size_t readSignatureMember(ustr_t signature, size_t index)
Expand Down
3 changes: 2 additions & 1 deletion elenasrc3/elc/compilerlogic.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ namespace elena_lang
bool stackSafe;
bool withVariadicDispatcher;
bool withCustomDispatcher;
int nillableArgs;
};

struct TypeAttributes
Expand Down Expand Up @@ -195,7 +196,7 @@ namespace elena_lang
bool resolveCallType(ModuleScopeBase& scope, ref_t classRef, mssg_t message,
CheckMethodResult& result);

mssg_t resolveSingleDispatch(ModuleScopeBase& scope, ref_t reference, ref_t weakMessage);
mssg_t resolveSingleDispatch(ModuleScopeBase& scope, ref_t reference, ref_t weakMessage, int& nillableArgs);

void injectOverloadList(CompilerBase* compiler, ModuleScopeBase& scope, ClassInfo& info, ref_t classRef);
void injectMethodOverloadList(CompilerBase* compiler, ModuleScopeBase& scope, ref_t flags,
Expand Down
Loading

0 comments on commit 14f4a64

Please sign in to comment.