Skip to content

Commit

Permalink
[FIXED]#508 - working on multi-value assigning
Browse files Browse the repository at this point in the history
[FIXED]#86 - primitive operations : int + long
  • Loading branch information
arakov committed Nov 29, 2023
1 parent b843118 commit de1c6f4
Show file tree
Hide file tree
Showing 19 changed files with 246 additions and 60 deletions.
38 changes: 32 additions & 6 deletions dat/sg/syntax60.txt
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,6 @@ __define INLINE 4303;
__define SUB_DECLARATION 4312;
__define FINALLY 7385;
__define PARAMETER_BLOCK 4336;
__define LESS_EXPRESSION 4340;
__define L7_LESS_EXPRESSION 4341;

START ::=
{ DECLARATION | META_DECLARATION }+ eof
Expand Down Expand Up @@ -238,6 +236,7 @@ ROOT_EXPRESSION ::=
| L9_OOP
| eps ^OBJECT
}
| "," ^OBJECT SUB_VARIABLE { "," SUB_VARIABLE }* ASSIGN EXPRESSION ^TUPLE_ASSIGNING
| SBRACKET ^OBJECT INDEXER_R L0_F
| ASSIGN ^OBJECT ASSIGN_R
| L1a_OOP
Expand Down Expand Up @@ -313,7 +312,16 @@ ROOT_EXPRESSION ::=
| "$break" ^BREAK_OPERATION
| BRACKET SUB_EXPRESSION {
"=>" { SWITCH_OPTION+ SWITCH_LAST_OPTION? } ^SWITCH_OPERATION
| L_F
| L2_OP+ L3_OP* L4_OP* L5_OP* L6_OP? L7_OP* L8_OP? L9_OP?
| L3_OP+ L4_OP* L5_OP* L6_OP? L7_OP* L8_OP? L9_OP?
| L4_OP+ L5_OP* L6_OP? L7_OP* L8_OP? L9_OP?
| L5_OP+ L6_OP? L7_OP* L8_OP? L9_OP?
| L6_OP L7_OP* L8_OP? L9_OP?
| L7_OP+ L8_OP? L9_OP?
| L8_OP
| L9_OP
| ASSIGN EXPRESSION ^TUPLE_ASSIGNING
| eps
};

NESTED_ROOT_EXPRESSION ::=
Expand All @@ -330,6 +338,7 @@ NESTED_ROOT_EXPRESSION ::=
| L9_OOP
| eps ^OBJECT
}
| "," ^OBJECT SUB_VARIABLE { "," SUB_VARIABLE }* ASSIGN EXPRESSION ^TUPLE_ASSIGNING
| SBRACKET ^OBJECT INDEXER_R L0_F
| ASSIGN ^OBJECT ASSIGN_R
| L1a_OOP
Expand Down Expand Up @@ -480,7 +489,18 @@ EXPRESSION ::=
| "$reference" SINGLE_EXPRESSION ^REFER_OPERATION
| "$len" SINGLE_EXPRESSION ^LEN_OPERATION
| "{" BLOCK ^CLOSURE L2_OP* L3_OP* L4_OP* L5_OP* L6_OP? L7_OP* L8_OP? L9_OP?
| BRACKET SUB_EXPRESSION L2_OP* L3_OP* L4_OP* L5_OP* L6_OP? L7_OP* L8_OP? L9_OP?
| BRACKET SUB_EXPRESSION {
L2_OP+ L3_OP* L4_OP* L5_OP* L6_OP? L7_OP* L8_OP? L9_OP?
| L3_OP+ L4_OP* L5_OP* L6_OP? L7_OP* L8_OP? L9_OP?
| L4_OP+ L5_OP* L6_OP? L7_OP* L8_OP? L9_OP?
| L5_OP+ L6_OP? L7_OP* L8_OP? L9_OP?
| L6_OP L7_OP* L8_OP? L9_OP?
| L7_OP+ L8_OP? L9_OP?
| L8_OP
| L9_OP
| ASSIGN ^TUPLE_BLOCK EXPRESSION ^TUPLE_ASSIGNING
| eps
}
| "$lazy" EXPRESSION;

SUB_EXPRESSION ::=
Expand Down Expand Up @@ -547,8 +567,8 @@ SUB_EXPRESSION ::=
| L9_OOP ")"
| "{" NESTED_EXPRESSION ^NESTED L2_OP* L3_OP* L4_OP* L5_OP* L6_OP? L7_OP* L8_OP? L9_OP? TUPLE_R? ")"
| "=>" ^ PARAMETER RET_EXPRESSION ^CLOSURE ")" ^EXPRESSION
| "," ^ OBJECT ^ EXPRESSION EXPRESSION { "," EXPRESSION }*
{ "=>" ^ PARAMETER_BLOCK RET_EXPRESSION ^CLOSURE ")" ^EXPRESSION
| "," ^ OBJECT ^ EXPRESSION EXPRESSION { "," EXPRESSION }* {
"=>" ^ PARAMETER_BLOCK RET_EXPRESSION ^CLOSURE ")" ^EXPRESSION
| ")" {
"{" ^ PARAMETER_BLOCK BLOCK ^CLOSURE ^EXPRESSION
| eps ^TUPLE_COLLECTION
Expand Down Expand Up @@ -1034,6 +1054,12 @@ PARAMETER ::=
| eps
};

SUB_VARIABLE ::=
identifier+ {
DYNAMIC_DIMENSION ^ARRAY_TYPE identifier
| TEMPLATE_BRACKETS identifier
| eps };

TEMPLATE_BRACKETS ::=
"<" TEMPLATE_ARG { "," TEMPLATE_ARG }* ">";

Expand Down
9 changes: 9 additions & 0 deletions doc/api/extensions.html
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,15 @@ <H3>Method Summary</H3>
</CODE>
</TD>
</TR>
<TR CLASS="altColor">
<TD CLASS="colFirst">
<CODE>
</CODE></TD>
<TD CLASS="colLast">
<CODE>ifNil(b)
</CODE>
</TD>
</TR>
</TABLE>
</LI>
</UL>
Expand Down
24 changes: 10 additions & 14 deletions doc/todo.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,37 +5,33 @@ In development:
[development]
### EPIC: elena 6.0 - redux ###
=== Iteration 19 ===
dev: #608
dev: #608, #562
op:github actions : x86
opt:#602
maint:#616, system module warnings, #622
exp:using expression trees in real-life apps (see c#)
ide:backlog (#617), vm debugger, debugger watch - struct
tools:backlog
prom:tutorial 2 - program entry / linker
prom:tutorial forwards
port:db samples, elenavm / elt for linux
--------------------------------------

* test elenasm for linux : i386, amd64, ppc64le, aarch64 (calc, interpreter, js)

* multi-value return type
* it should be possible to use your own operation patterns, module should contain the meta declaration to use the oepration
patterns

* multi-value type take into account the expected value
* meta command to use statement templates

* check multi value return from function
* #563 : patterns (https://endjin.com/blog/2022/02/pattern-matching-in-csharp)

* default: should use class.Default if the constructor is protected / private
* remove temporal solution for Map<Key,T> (see retrieve(int index, TKey key))

* test ++

* #563 : patterns
* #562 : nullable

int? varNullableInt := nil;
* if:is
* foreach:in

* system warnings
* extensions warnings
* review code - check for the common patterns
* chat sample

=== Iteration 20 ===
dev: async programming (instant messagange sample (chat) )
Expand Down
2 changes: 2 additions & 0 deletions elenasrc3/elc/clicommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ struct BuiltinReferences
mssg_t if_message, iif_message;
mssg_t equal_message;
mssg_t not_message, negate_message, value_message;
mssg_t default_message;
mssg_t notequal_message;
mssg_t less_message, greater_message;
mssg_t notless_message, notgreater_message;
Expand Down Expand Up @@ -227,6 +228,7 @@ struct BuiltinReferences
if_message = iif_message = 0;
equal_message = 0;
not_message = negate_message = value_message = 0;
default_message = 0;
notequal_message = 0;
greater_message = less_message = 0;
notgreater_message = notless_message = 0;
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 0x0228
#define ELC_REVISION_NUMBER 0x0229

#if defined _M_IX86 || _M_X64

Expand Down
57 changes: 46 additions & 11 deletions elenasrc3/elc/compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8168,17 +8168,33 @@ ObjectInfo Compiler :: compileTupleAssigning(BuildTreeWriter& writer, ExprScope&
ArgumentsInfo arguments;

SyntaxNode current = node.firstChild();
targets.add(mapObject(scope, current, EAttr::None));
current = current.nextNode();
while (current == SyntaxKey::SubVariable) {
ObjectInfo subVar = mapObject(scope, current, EAttr::NewVariable | EAttr::IgnoreDuplicate);
if (subVar.kind == ObjectKind::Unknown)
scope.raiseError(errUnknownObject, current);
if (current == SyntaxKey::TupleCollection) {
SyntaxNode identNode = current.firstChild();
while (identNode != SyntaxKey::None) {
SyntaxNode objNode = identNode.firstChild();
if (objNode == SyntaxKey::Object) {
targets.add(mapObject(scope, objNode, EAttr::None));
}
else scope.raiseError(errInvalidOperation, identNode);

targets.add(subVar);
identNode = identNode.nextNode();
}

current = current.nextNode();
}
else {
targets.add(mapObject(scope, current, EAttr::None));
current = current.nextNode();
while (current == SyntaxKey::SubVariable) {
ObjectInfo subVar = mapObject(scope, current, EAttr::NewVariable | EAttr::IgnoreDuplicate);
if (subVar.kind == ObjectKind::Unknown)
scope.raiseError(errUnknownObject, current);

targets.add(subVar);

current = current.nextNode();
}
}

ObjectInfo exprVal = compileExpression(writer, scope, current, 0, EAttr::Parameter, nullptr);
for (pos_t i = 0; i < targets.count_pos(); i++) {
Expand Down Expand Up @@ -9455,10 +9471,23 @@ ObjectInfo Compiler :: convertObject(BuildTreeWriter& writer, ExprScope& scope,
if (!_logic->isCompatible(*scope.moduleScope, { targetRef }, source.typeInfo, false)) {
if (source.kind == ObjectKind::Default) {
if (_logic->isEmbeddable(*context.scope->moduleScope, targetRef)) {
ObjectInfo classSymbol = mapClassSymbol(*context.scope, targetRef);

ArgumentsInfo arguments;

return compileNewOp(*context.writer, *context.scope, context.node,
mapClassSymbol(*context.scope, targetRef), 0, arguments);
CheckMethodResult dummy = {};
if (_logic->resolveCallType(*scope.moduleScope, classSymbol.typeInfo.typeRef, scope.moduleScope->buildins.constructor_message, dummy)
&& dummy.visibility == Visibility::Public)
{
return compileNewOp(*context.writer, *context.scope, context.node,
classSymbol, 0, arguments);
}
else {
// BAD LUCK : Default property should be returned
return compileWeakOperation(writer, scope, node, nullptr, 0, classSymbol,
arguments, scope.moduleScope->buildins.default_message, targetRef, nullptr);

}
}
else return { ObjectKind::Nil, { V_NIL } };
}
Expand Down Expand Up @@ -9874,7 +9903,7 @@ ref_t Compiler :: resolveTupleClass(Scope& scope, SyntaxNode node, ArgumentsInfo
templateReference, parameters, false, nullptr);
}

ObjectInfo Compiler :: compileTupleCollectiom(BuildTreeWriter& writer, ExprScope& scope, SyntaxNode node)
ObjectInfo Compiler :: compileTupleCollectiom(BuildTreeWriter& writer, ExprScope& scope, SyntaxNode node, ref_t targetRef)
{
WriterContext context = { &writer, &scope, node };

Expand All @@ -9895,6 +9924,9 @@ ObjectInfo Compiler :: compileTupleCollectiom(BuildTreeWriter& writer, ExprScope

ref_t tupleRef = resolveTupleClass(scope, node, arguments);

if (_logic->isTemplateCompatible(*scope.moduleScope, targetRef, tupleRef))
tupleRef = targetRef;

writer.newNode(BuildKey::CreatingClass, arguments.count_pos());
writer.appendNode(BuildKey::Type, tupleRef);
writer.closeNode();
Expand Down Expand Up @@ -10211,7 +10243,7 @@ ObjectInfo Compiler :: compileExpression(BuildTreeWriter& writer, ExprScope& sco
break;
}
case SyntaxKey::TupleCollection:
retVal = compileTupleCollectiom(writer, scope, current);
retVal = compileTupleCollectiom(writer, scope, current, targetRef);
break;
case SyntaxKey::TupleAssignOperation:
retVal = compileTupleAssigning(writer, scope, current);
Expand Down Expand Up @@ -12763,6 +12795,9 @@ void Compiler :: prepare(ModuleScopeBase* moduleScope, ForwardResolverBase* forw
moduleScope->buildins.value_message =
encodeMessage(moduleScope->module->mapAction(VALUE_MESSAGE, 0, false),
1, PROPERTY_MESSAGE);
moduleScope->buildins.default_message =
encodeMessage(moduleScope->module->mapAction(DEFAULT_MESSAGE, 0, false),
1, PROPERTY_MESSAGE);
moduleScope->buildins.bnot_message =
encodeMessage(moduleScope->module->mapAction(BNOT_MESSAGE, 0, false),
1, PROPERTY_MESSAGE);
Expand Down
2 changes: 1 addition & 1 deletion elenasrc3/elc/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -1452,7 +1452,7 @@ namespace elena_lang
void compileClassVMT(BuildTreeWriter& writer, ClassScope& classClassScope, ClassScope& scope, SyntaxNode node);

ObjectInfo compileCollection(BuildTreeWriter& writer, ExprScope& scope, SyntaxNode node, ExpressionAttribute mode);
ObjectInfo compileTupleCollectiom(BuildTreeWriter& writer, ExprScope& scope, SyntaxNode node);
ObjectInfo compileTupleCollectiom(BuildTreeWriter& writer, ExprScope& scope, SyntaxNode node, ref_t targetRef);

void compileSymbol(BuildTreeWriter& writer, SymbolScope& scope, SyntaxNode node);
void compileClassSymbol(BuildTreeWriter& writer, ClassScope& scope);
Expand Down
44 changes: 44 additions & 0 deletions elenasrc3/elc/compilerlogic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1738,6 +1738,50 @@ ref_t CompilerLogic :: definePrimitiveArray(ModuleScopeBase& scope, ref_t elemen
else return V_OBJARRAY;
}

bool CompilerLogic :: isTemplateCompatible(ModuleScopeBase& scope, ref_t targetRef, ref_t sourceRef)
{
ustr_t targetName = scope.module->resolveReference(targetRef);
ustr_t sourceName = scope.module->resolveReference(sourceRef);

size_t pos = targetName.find('&');

// check if it is the same template
if (sourceName.length() < pos || !targetName.compare(sourceName, pos))
return false;

// check if the signature is compatible
size_t targetStart = pos + 1;
size_t sourceStart = pos + 1;

while (true) {
size_t targetEndPos = targetName.findSub(targetStart, '&', targetName.length());
size_t sourceEndPos = sourceName.findSub(sourceStart, '&', sourceName.length());

IdentifierString targetArg;
IdentifierString sourceArg;

targetArg.copy(targetName.str() + targetStart, targetEndPos - targetStart);
sourceArg.copy(sourceName.str() + sourceStart, sourceEndPos - sourceStart);

targetArg.replaceAll('@', '\'', 0);
sourceArg.replaceAll('@', '\'', 0);

ref_t targetArgRef = scope.mapFullReference(*targetArg);
ref_t sourceArgRef = scope.mapFullReference(*sourceArg);

if (!isCompatible(scope, { targetArgRef }, { sourceArgRef }, true))
return false;

if (targetEndPos >= targetName.length() || sourceEndPos >= sourceName.length())
break;

targetStart = targetEndPos + 1;
sourceStart = sourceEndPos + 1;
}

return true;
}

bool CompilerLogic :: isCompatible(ModuleScopeBase& scope, TypeInfo targetInfo, TypeInfo sourceInfo, bool ignoreNils)
{
if ((!targetInfo.typeRef || targetInfo.typeRef == scope.buildins.superReference) && !sourceInfo.isPrimitive())
Expand Down
1 change: 1 addition & 0 deletions elenasrc3/elc/compilerlogic.h
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ namespace elena_lang

bool isCompatible(ModuleScopeBase& scope, TypeInfo targetInfo, TypeInfo sourceInfo, bool ignoreNils);
bool isPrimitiveCompatible(ModuleScopeBase& scope, TypeInfo target, TypeInfo source);
bool isTemplateCompatible(ModuleScopeBase& scope, ref_t targetRef, ref_t sourceRef);

bool isSignatureCompatible(ModuleScopeBase& scope, mssg_t targetMessage, mssg_t sourceMessage);
bool isMessageCompatibleWithSignature(ModuleScopeBase& scope, ref_t targetRef,
Expand Down
3 changes: 3 additions & 0 deletions elenasrc3/elc/derivation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,9 @@ void SyntaxTreeBuilder :: flushExpressionMember(SyntaxTreeWriter& writer, Scope&
case SyntaxKey::TemplateOperation:
generateTemplateOperation(writer, scope, current);
break;
case SyntaxKey::TupleBlock:
flushExpression(writer, scope, current);
break;
default:
if (SyntaxTree::testSuperKey(current.key, SyntaxKey::Expression)) {
current.setKey(SyntaxKey::Expression);
Expand Down
1 change: 1 addition & 0 deletions elenasrc3/engine/elenaconst.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ namespace elena_lang
constexpr auto NEGATE_MESSAGE = "Negative";
constexpr auto VALUE_MESSAGE = "Value";
constexpr auto ITEM_MESSAGE = "Value";
constexpr auto DEFAULT_MESSAGE = "Default";
constexpr auto BNOT_MESSAGE = "BInverted";
constexpr auto NOTEQUAL_MESSAGE = "notequal";
constexpr auto LESS_MESSAGE = "less";
Expand Down
2 changes: 1 addition & 1 deletion elenasrc3/engine/syntaxtree.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ namespace elena_lang
StaticInitializerMethod = 0x0010F1,
PrimitiveCollection = 0x0018F2,
BranchOperation = 0x0018F3,
LessExpression = 0x0010F4,
TupleBlock = 0x0010F4,

Name = 0x000101,
Namespace = 0x000103,
Expand Down
8 changes: 8 additions & 0 deletions src60/extensions/tests.l
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,14 @@ public singleton Assert
AssertException.raise("Assertion failed")
}
}

ifNil(b)
{
ifnot(nil == b)
{
AssertException.raise("Assertion failed")
}
}
}

// --- testOp ---
Expand Down
Loading

0 comments on commit de1c6f4

Please sign in to comment.