@@ -372,7 +372,7 @@ static void bindBinaryArithmeticExpression(deBlock scopeBlock, deExpression expr
372
372
373
373
// Bind a bitwise OR expression. This is different from the other bitwise
374
374
// operators because it also used in type unions, such as "a: Uint | Int".
375
- static void bindBitwiseOrExpression (deBlock scopeBlock , deExpression expression ) {
375
+ static void bindBitwiseOrExpression (deBlock scopeBlock , deExpression expression , bool isTypeExpr ) {
376
376
deExpression left = deExpressionGetFirstExpression (expression );
377
377
deExpression right = deExpressionGetNextExpression (left );
378
378
if (deExpressionIsType (left ) && deExpressionIsType (right )) {
@@ -381,10 +381,7 @@ static void bindBitwiseOrExpression(deBlock scopeBlock, deExpression expression)
381
381
}
382
382
deDatatype leftType , rightType ;
383
383
checkBinaryExpression (scopeBlock , expression , & leftType , & rightType , false);
384
- if (deExpressionIsType (left )) {
385
- if (!deExpressionIsType (right )) {
386
- deExprError (expression , "Non-equal types passed to binary operator" );
387
- }
384
+ if (isTypeExpr ) {
388
385
deExpressionSetIsType (expression , true);
389
386
deExpressionSetDatatype (expression , deNoneDatatypeCreate ());
390
387
} else {
@@ -1023,8 +1020,8 @@ static void bindCastExpression(deExpression expression) {
1023
1020
leftDatatype = deSetDatatypeSecret (leftDatatype , deDatatypeSecret (rightDatatype ));
1024
1021
if (deDatatypeGetType (leftDatatype ) == DE_TYPE_ENUMCLASS ) {
1025
1022
// If the cast is to an ENUMCLASS, instead cast to an ENUM.
1026
- deBlock enumBlock = deFunctionGetSubBlock ( deDatatypeGetFunction (leftDatatype ) );
1027
- leftDatatype = deFindEnumIntType ( enumBlock );
1023
+ deFunction enumFunc = deDatatypeGetFunction (leftDatatype );
1024
+ leftDatatype = deEnumDatatypeCreate ( enumFunc );
1028
1025
}
1029
1026
verifyCast (expression , leftDatatype , rightDatatype , line );
1030
1027
deExpressionSetDatatype (expression , leftDatatype );
@@ -1559,10 +1556,9 @@ static bool bindDotExpression(deBlock scopeBlock, deExpression expression) {
1559
1556
deBlock classBlock ;
1560
1557
if (type == DE_TYPE_CLASS ) {
1561
1558
if (deDatatypeNullable (datatype )) {
1562
- deString string = deMutableStringCreate ();
1563
- deDumpExpressionStr (string , expression );
1564
- deExprError (expression , "Cannot use dot operator on nullable type: %s." ,
1565
- deStringGetCstr (string ));
1559
+ // Infer the ! operator.
1560
+ datatype = deSetDatatypeNullable (datatype , false);
1561
+ deExpressionSetDatatype (accessExpr , datatype );
1566
1562
}
1567
1563
classBlock = deClassGetSubBlock (deDatatypeGetClass (datatype ));
1568
1564
} else if (type == DE_TYPE_TEMPLATE ) {
@@ -1659,7 +1655,7 @@ static void bindTemplateInst(deBlock scopeBlock, deExpression expression) {
1659
1655
}
1660
1656
1661
1657
// Bind the expression's expression.
1662
- static deBindRes bindExpression (deBlock scopeBlock , deExpression expression ) {
1658
+ static deBindRes bindExpression (deBlock scopeBlock , deExpression expression , bool isTypeExpr ) {
1663
1659
deDatatype oldDatatype = deExpressionGetDatatype (expression );
1664
1660
if (oldDatatype != deDatatypeNull && deDatatypeGetType (oldDatatype ) == DE_TYPE_MODINT ) {
1665
1661
// TODO: Add support for operator overloading in modular expressions.
@@ -1701,7 +1697,7 @@ static deBindRes bindExpression(deBlock scopeBlock, deExpression expression) {
1701
1697
break ;
1702
1698
case DE_EXPR_BITOR :
1703
1699
case DE_EXPR_BITOR_EQUALS :
1704
- bindBitwiseOrExpression (scopeBlock , expression );
1700
+ bindBitwiseOrExpression (scopeBlock , expression , isTypeExpr );
1705
1701
break ;
1706
1702
case DE_EXPR_ADD :
1707
1703
case DE_EXPR_SUB :
@@ -2001,7 +1997,9 @@ void deBindStatement(deBinding binding) {
2001
1997
deExpression expression = deBindingGetFirstExpression (binding );
2002
1998
deBlock scopeBlock = deGetBindingBlock (binding );
2003
1999
while (expression != deExpressionNull ) {
2004
- deBindRes result = bindExpression (scopeBlock , expression );
2000
+ deBindingType type = deBindingGetType (binding );
2001
+ bool isTypeExpr = type == DE_BIND_VAR_CONSTRAINT || type == DE_BIND_FUNC_CONSTRAINT ;
2002
+ deBindRes result = bindExpression (scopeBlock , expression , isTypeExpr );
2005
2003
if (result == DE_BINDRES_BLOCKED ) {
2006
2004
return ;
2007
2005
} else if (result == DE_BINDRES_REBIND ) {
0 commit comments