1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 11:38:21 +02:00

Added overflow operators &+, &-, &*

This commit is contained in:
Brian Fiete 2021-07-15 06:01:17 -07:00
parent 8d2b222c1a
commit d475d3641f
7 changed files with 151 additions and 25 deletions

View file

@ -1500,6 +1500,12 @@ const char* Beefy::BfTokenToString(BfToken token)
return ">>="; return ">>=";
case BfToken_AndEquals: case BfToken_AndEquals:
return "&="; return "&=";
case BfToken_AndMinus:
return "&-";
case BfToken_AndPlus:
return "&+";
case BfToken_AndStar:
return "&*";
case BfToken_OrEquals: case BfToken_OrEquals:
return "|="; return "|=";
case BfToken_XorEquals: case BfToken_XorEquals:
@ -1630,11 +1636,14 @@ int Beefy::BfGetBinaryOpPrecendence(BfBinaryOp binOp)
switch (binOp) switch (binOp)
{ {
case BfBinaryOp_Multiply: case BfBinaryOp_Multiply:
case BfBinaryOp_OverflowMultiply:
case BfBinaryOp_Divide: case BfBinaryOp_Divide:
case BfBinaryOp_Modulus: case BfBinaryOp_Modulus:
return 13; return 13;
case BfBinaryOp_Add: case BfBinaryOp_Add:
case BfBinaryOp_Subtract: case BfBinaryOp_Subtract:
case BfBinaryOp_OverflowAdd:
case BfBinaryOp_OverflowSubtract:
return 12; return 12;
case BfBinaryOp_LeftShift: case BfBinaryOp_LeftShift:
case BfBinaryOp_RightShift: case BfBinaryOp_RightShift:
@ -1682,6 +1691,9 @@ const char* Beefy::BfGetOpName(BfBinaryOp binOp)
case BfBinaryOp_Add: return "+"; case BfBinaryOp_Add: return "+";
case BfBinaryOp_Subtract: return "-"; case BfBinaryOp_Subtract: return "-";
case BfBinaryOp_Multiply: return "*"; case BfBinaryOp_Multiply: return "*";
case BfBinaryOp_OverflowAdd: return "&+";
case BfBinaryOp_OverflowSubtract: return "&-";
case BfBinaryOp_OverflowMultiply: return "&*";
case BfBinaryOp_Divide: return "/"; case BfBinaryOp_Divide: return "/";
case BfBinaryOp_Modulus: return "%"; case BfBinaryOp_Modulus: return "%";
case BfBinaryOp_BitwiseAnd: return "&"; case BfBinaryOp_BitwiseAnd: return "&";
@ -1742,6 +1754,12 @@ BfBinaryOp Beefy::BfTokenToBinaryOp(BfToken token)
return BfBinaryOp_Subtract; return BfBinaryOp_Subtract;
case BfToken_Star: case BfToken_Star:
return BfBinaryOp_Multiply; return BfBinaryOp_Multiply;
case BfToken_AndPlus:
return BfBinaryOp_OverflowAdd;
case BfToken_AndMinus:
return BfBinaryOp_OverflowSubtract;
case BfToken_AndStar:
return BfBinaryOp_OverflowMultiply;
case BfToken_ForwardSlash: case BfToken_ForwardSlash:
return BfBinaryOp_Divide; return BfBinaryOp_Divide;
case BfToken_Modulus: case BfToken_Modulus:

View file

@ -210,6 +210,9 @@ enum BfToken : uint8
BfToken_ShiftLeftEquals, BfToken_ShiftLeftEquals,
BfToken_ShiftRightEquals, BfToken_ShiftRightEquals,
BfToken_AndEquals, BfToken_AndEquals,
BfToken_AndMinus,
BfToken_AndPlus,
BfToken_AndStar,
BfToken_OrEquals, BfToken_OrEquals,
BfToken_XorEquals, BfToken_XorEquals,
BfToken_NullCoalsceEquals, BfToken_NullCoalsceEquals,
@ -1795,6 +1798,9 @@ enum BfBinaryOp
BfBinaryOp_Add, BfBinaryOp_Add,
BfBinaryOp_Subtract, BfBinaryOp_Subtract,
BfBinaryOp_Multiply, BfBinaryOp_Multiply,
BfBinaryOp_OverflowAdd,
BfBinaryOp_OverflowSubtract,
BfBinaryOp_OverflowMultiply,
BfBinaryOp_Divide, BfBinaryOp_Divide,
BfBinaryOp_Modulus, BfBinaryOp_Modulus,
BfBinaryOp_BitwiseAnd, BfBinaryOp_BitwiseAnd,

View file

@ -21177,11 +21177,20 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
BfBinaryOp findBinaryOp = binaryOp; BfBinaryOp findBinaryOp = binaryOp;
bool isComparison = (binaryOp >= BfBinaryOp_Equality) && (binaryOp <= BfBinaryOp_LessThanOrEqual); bool isComparison = (binaryOp >= BfBinaryOp_Equality) && (binaryOp <= BfBinaryOp_LessThanOrEqual);
for (int pass = 0; pass < 2; pass++) for (int pass = 0; pass < 2; pass++)
{ {
BfBinaryOp oppositeBinaryOp = BfGetOppositeBinaryOp(findBinaryOp); BfBinaryOp oppositeBinaryOp = BfGetOppositeBinaryOp(findBinaryOp);
bool foundOp = false; BfBinaryOp overflowBinaryOp = BfBinaryOp_None;
if (findBinaryOp == BfBinaryOp_OverflowAdd)
overflowBinaryOp = BfBinaryOp_Add;
else if (findBinaryOp == BfBinaryOp_OverflowSubtract)
overflowBinaryOp = BfBinaryOp_Subtract;
else if (findBinaryOp == BfBinaryOp_OverflowMultiply)
overflowBinaryOp = BfBinaryOp_Multiply;
bool foundOp = false;
BfResolvedArg leftArg; BfResolvedArg leftArg;
leftArg.mExpression = leftExpression; leftArg.mExpression = leftExpression;
@ -21225,7 +21234,7 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
bool invertResult = false; bool invertResult = false;
BfType* operatorConstraintReturnType = NULL; BfType* operatorConstraintReturnType = NULL;
bool wasTransformedUsage = pass == 1; bool wasTransformedUsage = (pass == 1);
while (true) while (true)
{ {
@ -21288,7 +21297,7 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
} }
} }
} }
else if (operatorDef->mOperatorDeclaration->mBinOp == oppositeBinaryOp) else if ((operatorDef->mOperatorDeclaration->mBinOp == oppositeBinaryOp) || (operatorDef->mOperatorDeclaration->mBinOp == overflowBinaryOp))
oppositeOperatorDefs.Add(operatorDef); oppositeOperatorDefs.Add(operatorDef);
} }
@ -21309,7 +21318,8 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
methodMatcher.mBestMethodDef = oppositeOperatorDef; methodMatcher.mBestMethodDef = oppositeOperatorDef;
methodMatcher.mBestMethodTypeInstance = checkType; methodMatcher.mBestMethodTypeInstance = checkType;
methodMatcher.mSelfType = entry.mSrcType; methodMatcher.mSelfType = entry.mSrcType;
wasTransformedUsage = true; if (oppositeBinaryOp != BfBinaryOp_None)
wasTransformedUsage = true;
} }
} }
else else
@ -21322,7 +21332,8 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
{ {
operatorConstraintReturnType = returnType; operatorConstraintReturnType = returnType;
methodMatcher.mSelfType = entry.mSrcType; methodMatcher.mSelfType = entry.mSrcType;
wasTransformedUsage = true; if (oppositeBinaryOp != BfBinaryOp_None)
wasTransformedUsage = true;
} }
} }
} }
@ -21332,7 +21343,8 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
if (methodMatcher.CheckMethod(NULL, checkType, oppositeOperatorDef, false)) if (methodMatcher.CheckMethod(NULL, checkType, oppositeOperatorDef, false))
{ {
methodMatcher.mSelfType = entry.mSrcType; methodMatcher.mSelfType = entry.mSrcType;
wasTransformedUsage = true; if (oppositeBinaryOp != BfBinaryOp_None)
wasTransformedUsage = true;
} }
} }
} }
@ -21526,12 +21538,12 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
if (pass == 1) if (pass == 1)
break; break;
auto flippedBinaryOp = BfGetFlippedBinaryOp(findBinaryOp); auto flippedBinaryOp = BfGetFlippedBinaryOp(findBinaryOp);
if (flippedBinaryOp != BfBinaryOp_None) if (flippedBinaryOp != BfBinaryOp_None)
findBinaryOp = flippedBinaryOp; findBinaryOp = flippedBinaryOp;
} }
auto prevResultType = resultType; auto prevResultType = resultType;
if ((leftValue.mType->IsPrimitiveType()) && (!rightValue.mType->IsTypedPrimitive())) if ((leftValue.mType->IsPrimitiveType()) && (!rightValue.mType->IsTypedPrimitive()))
resultType = leftValue.mType; resultType = leftValue.mType;
@ -21567,7 +21579,7 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
} }
//TODO: Allow all pointer comparisons, but only allow SUBTRACTION between equal pointer types //TODO: Allow all pointer comparisons, but only allow SUBTRACTION between equal pointer types
if (binaryOp == BfBinaryOp_Subtract) if ((binaryOp == BfBinaryOp_Subtract) || (binaryOp == BfBinaryOp_OverflowSubtract))
{ {
if (!mModule->CanCast(*otherTypedValue, resultType)) if (!mModule->CanCast(*otherTypedValue, resultType))
{ {
@ -21622,7 +21634,7 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
// One pointer // One pointer
if ((!otherType->IsIntegral()) || if ((!otherType->IsIntegral()) ||
((binaryOp != BfBinaryOp_Add) && (binaryOp != BfBinaryOp_Subtract))) ((binaryOp != BfBinaryOp_Add) && (binaryOp != BfBinaryOp_Subtract) && (binaryOp != BfBinaryOp_OverflowAdd) && (binaryOp != BfBinaryOp_OverflowSubtract)))
{ {
_OpFail(); _OpFail();
return; return;
@ -21632,7 +21644,7 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
BfIRValue addValue = otherTypedValue->mValue; BfIRValue addValue = otherTypedValue->mValue;
if ((!otherTypedValue->mType->IsSigned()) && (otherTypedValue->mType->mSize < mModule->mSystem->mPtrSize)) if ((!otherTypedValue->mType->IsSigned()) && (otherTypedValue->mType->mSize < mModule->mSystem->mPtrSize))
addValue = mModule->mBfIRBuilder->CreateNumericCast(addValue, false, BfTypeCode_UIntPtr); addValue = mModule->mBfIRBuilder->CreateNumericCast(addValue, false, BfTypeCode_UIntPtr);
if (binaryOp == BfBinaryOp_Subtract) if ((binaryOp == BfBinaryOp_Subtract) || (binaryOp == BfBinaryOp_OverflowSubtract))
{ {
if (resultTypeSrc == rightExpression) if (resultTypeSrc == rightExpression)
mModule->Fail("Cannot subtract a pointer from an integer", resultTypeSrc); mModule->Fail("Cannot subtract a pointer from an integer", resultTypeSrc);
@ -21731,7 +21743,7 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
} }
// Allow integer offsetting // Allow integer offsetting
if ((binaryOp == BfBinaryOp_Add) || (binaryOp == BfBinaryOp_Subtract)) if ((binaryOp == BfBinaryOp_Add) || (binaryOp == BfBinaryOp_Subtract) || (binaryOp == BfBinaryOp_OverflowAdd) || (binaryOp == BfBinaryOp_OverflowSubtract))
{ {
if (otherType->IsIntegral()) if (otherType->IsIntegral())
needsOtherCast = false; needsOtherCast = false;
@ -21954,7 +21966,7 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
if (rightValue.mType->IsIntegral()) if (rightValue.mType->IsIntegral())
explicitCast = true; explicitCast = true;
} }
else if (((binaryOp == BfBinaryOp_Add) || (binaryOp == BfBinaryOp_Subtract)) && (resultType->IsChar()) && (otherType->IsInteger())) else if (((binaryOp == BfBinaryOp_Add) || (binaryOp == BfBinaryOp_Subtract) || (binaryOp == BfBinaryOp_OverflowAdd) || (binaryOp == BfBinaryOp_OverflowSubtract)) && (resultType->IsChar()) && (otherType->IsInteger()))
{ {
// charVal += intVal; // charVal += intVal;
explicitCast = true; explicitCast = true;
@ -21980,14 +21992,15 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
} }
else else
{ {
if ((binaryOp == BfBinaryOp_Subtract) && (resultType->IsChar()) && (otherType->IsChar())) if (((binaryOp == BfBinaryOp_Subtract) || (binaryOp == BfBinaryOp_OverflowSubtract)) &&
(resultType->IsChar()) && (otherType->IsChar()))
{ {
// "wchar - char" subtraction will always fit into int32, because of unicode range // "wchar - char" subtraction will always fit into int32, because of unicode range
resultType = mModule->GetPrimitiveType(BfTypeCode_Int32); resultType = mModule->GetPrimitiveType(BfTypeCode_Int32);
explicitCast = true; explicitCast = true;
} }
else if ((otherType->IsChar()) && else if ((otherType->IsChar()) &&
((binaryOp == BfBinaryOp_Add) || (binaryOp == BfBinaryOp_Subtract))) ((binaryOp == BfBinaryOp_Add) || (binaryOp == BfBinaryOp_Subtract) || (binaryOp == BfBinaryOp_OverflowAdd) || (binaryOp == BfBinaryOp_OverflowSubtract)))
{ {
mModule->Fail(StrFormat("Cannot perform operation between types '%s' and '%s'", mModule->Fail(StrFormat("Cannot perform operation between types '%s' and '%s'",
mModule->TypeToString(leftValue.mType).c_str(), mModule->TypeToString(leftValue.mType).c_str(),
@ -22142,6 +22155,7 @@ void BfExprEvaluator::PerformBinaryOperation(BfType* resultType, BfIRValue convL
if ((resultType->IsChar()) && if ((resultType->IsChar()) &&
((binaryOp == BfBinaryOp_Multiply) || ((binaryOp == BfBinaryOp_Multiply) ||
(binaryOp == BfBinaryOp_OverflowMultiply) ||
(binaryOp == BfBinaryOp_Divide) || (binaryOp == BfBinaryOp_Divide) ||
(binaryOp == BfBinaryOp_Modulus))) (binaryOp == BfBinaryOp_Modulus)))
{ {
@ -22151,15 +22165,18 @@ void BfExprEvaluator::PerformBinaryOperation(BfType* resultType, BfIRValue convL
switch (binaryOp) switch (binaryOp)
{ {
case BfBinaryOp_Add: case BfBinaryOp_Add:
case BfBinaryOp_OverflowAdd:
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateAdd(convLeftValue, convRightValue), resultType); mResult = BfTypedValue(mModule->mBfIRBuilder->CreateAdd(convLeftValue, convRightValue), resultType);
mModule->CheckRangeError(resultType, opToken); mModule->CheckRangeError(resultType, opToken);
break; break;
case BfBinaryOp_Subtract: case BfBinaryOp_Subtract:
case BfBinaryOp_OverflowSubtract:
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateSub(convLeftValue, convRightValue), resultType); mResult = BfTypedValue(mModule->mBfIRBuilder->CreateSub(convLeftValue, convRightValue), resultType);
mModule->CheckRangeError(resultType, opToken); mModule->CheckRangeError(resultType, opToken);
break; break;
case BfBinaryOp_Multiply: case BfBinaryOp_Multiply:
case BfBinaryOp_OverflowMultiply:
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateMul(convLeftValue, convRightValue), resultType); mResult = BfTypedValue(mModule->mBfIRBuilder->CreateMul(convLeftValue, convRightValue), resultType);
mModule->CheckRangeError(resultType, opToken); mModule->CheckRangeError(resultType, opToken);
break; break;

View file

@ -754,6 +754,15 @@ String BfGNUMangler::Mangle(BfMethodInstance* methodInst)
case BfBinaryOp_Multiply: case BfBinaryOp_Multiply:
methodName = "ml"; methodName = "ml";
break; break;
case BfBinaryOp_OverflowAdd:
methodName = "opl";
break;
case BfBinaryOp_OverflowSubtract:
methodName = "omi";
break;
case BfBinaryOp_OverflowMultiply:
methodName = "oml";
break;
case BfBinaryOp_Divide: case BfBinaryOp_Divide:
methodName = "dv"; methodName = "dv";
break; break;
@ -1872,6 +1881,15 @@ void BfMSMangler::Mangle(StringImpl& name, bool is64Bit, BfMethodInstance* metho
case BfBinaryOp_Multiply: case BfBinaryOp_Multiply:
name += "?D"; name += "?D";
break; break;
case BfBinaryOp_OverflowAdd:
name += "?OH";
break;
case BfBinaryOp_OverflowSubtract:
name += "?OG";
break;
case BfBinaryOp_OverflowMultiply:
name += "?OD";
break;
case BfBinaryOp_Divide: case BfBinaryOp_Divide:
name += "?K"; name += "?K";
break; break;

View file

@ -1549,6 +1549,21 @@ void BfParser::NextToken(int endIdx, bool outerIsInterpolate)
mToken = BfToken_AndEquals; mToken = BfToken_AndEquals;
mTokenEnd = ++mSrcIdx; mTokenEnd = ++mSrcIdx;
} }
else if (mSrc[mSrcIdx] == '+')
{
mToken = BfToken_AndPlus;
mTokenEnd = ++mSrcIdx;
}
else if (mSrc[mSrcIdx] == '-')
{
mToken = BfToken_AndMinus;
mTokenEnd = ++mSrcIdx;
}
else if (mSrc[mSrcIdx] == '*')
{
mToken = BfToken_AndStar;
mTokenEnd = ++mSrcIdx;
}
else else
mToken = BfToken_Ampersand; mToken = BfToken_Ampersand;
mSyntaxToken = BfSyntaxToken_Token; mSyntaxToken = BfSyntaxToken_Token;

View file

@ -5975,13 +5975,13 @@ void DbgExprEvaluator::PerformBinaryOperation(ASTREF(BfExpression*)& leftExpress
// One pointer // One pointer
if ((!otherType->IsInteger()) || if ((!otherType->IsInteger()) ||
((binaryOp != BfBinaryOp_Add) && (binaryOp != BfBinaryOp_Subtract) && (!isCompare))) ((binaryOp != BfBinaryOp_Add) && (binaryOp != BfBinaryOp_Subtract) && (binaryOp != BfBinaryOp_OverflowAdd) && (binaryOp != BfBinaryOp_OverflowSubtract) && (!isCompare)))
{ {
Fail("Can only add or subtract integer values from pointers", rightExpression); Fail("Can only add or subtract integer values from pointers", rightExpression);
return; return;
} }
if ((binaryOp == BfBinaryOp_Add) || (binaryOp == BfBinaryOp_Subtract)) if ((binaryOp == BfBinaryOp_Add) || (binaryOp == BfBinaryOp_Subtract) || (binaryOp == BfBinaryOp_OverflowAdd) || (binaryOp == BfBinaryOp_OverflowSubtract))
{ {
auto underlyingType = otherType->GetUnderlyingType(); auto underlyingType = otherType->GetUnderlyingType();
mResult.mType = resultType; mResult.mType = resultType;
@ -6262,6 +6262,7 @@ void DbgExprEvaluator::PerformBinaryOperation(DbgType* resultType, DbgTypedValue
switch (binaryOp) switch (binaryOp)
{ {
case BfBinaryOp_Add: case BfBinaryOp_Add:
case BfBinaryOp_OverflowAdd:
if (resultType->mTypeCode == DbgType_Single) if (resultType->mTypeCode == DbgType_Single)
mResult.mSingle = convLeftValue.mSingle + convRightValue.mSingle; mResult.mSingle = convLeftValue.mSingle + convRightValue.mSingle;
else if (resultType->mTypeCode == DbgType_Double) else if (resultType->mTypeCode == DbgType_Double)
@ -6270,6 +6271,7 @@ void DbgExprEvaluator::PerformBinaryOperation(DbgType* resultType, DbgTypedValue
mResult.mInt64 = convLeftValue.GetInt64() + convRightValue.GetInt64(); mResult.mInt64 = convLeftValue.GetInt64() + convRightValue.GetInt64();
break; break;
case BfBinaryOp_Subtract: case BfBinaryOp_Subtract:
case BfBinaryOp_OverflowSubtract:
if (resultType->mTypeCode == DbgType_Single) if (resultType->mTypeCode == DbgType_Single)
mResult.mSingle = convLeftValue.mSingle - convRightValue.mSingle; mResult.mSingle = convLeftValue.mSingle - convRightValue.mSingle;
else if (resultType->mTypeCode == DbgType_Double) else if (resultType->mTypeCode == DbgType_Double)
@ -6278,6 +6280,7 @@ void DbgExprEvaluator::PerformBinaryOperation(DbgType* resultType, DbgTypedValue
mResult.mInt64 = convLeftValue.GetInt64() - convRightValue.GetInt64(); mResult.mInt64 = convLeftValue.GetInt64() - convRightValue.GetInt64();
break; break;
case BfBinaryOp_Multiply: case BfBinaryOp_Multiply:
case BfBinaryOp_OverflowMultiply:
if (resultType->mTypeCode == DbgType_Single) if (resultType->mTypeCode == DbgType_Single)
mResult.mSingle = convLeftValue.mSingle * convRightValue.mSingle; mResult.mSingle = convLeftValue.mSingle * convRightValue.mSingle;
else if (resultType->mTypeCode == DbgType_Double) else if (resultType->mTypeCode == DbgType_Double)

View file

@ -198,6 +198,41 @@ namespace Tests
} }
} }
struct StructH
{
public static int operator+(StructH lhs, int rhs)
{
return 1;
}
public static int operator+(int lhs, StructH rhs)
{
return 2;
}
[Commutable]
public static int operator+(StructH lhs, float rhs)
{
return 3;
}
public static int operator&+(StructH lhs, int rhs)
{
return 4;
}
public static int operator&+(int lhs, StructH rhs)
{
return 5;
}
[Commutable]
public static int operator&+(StructH lhs, float rhs)
{
return 6;
}
}
struct StructOp<T, T2> where T : operator T + T2 struct StructOp<T, T2> where T : operator T + T2
{ {
public T DoIt(T val, T2 val2) public T DoIt(T val, T2 val2)
@ -428,6 +463,20 @@ namespace Tests
Test.Assert(10 + sf == 2); Test.Assert(10 + sf == 2);
Test.Assert(sf + 1.0f == 3); Test.Assert(sf + 1.0f == 3);
Test.Assert(2.0f + sf == 3); Test.Assert(2.0f + sf == 3);
Test.Assert(sf &+ 10 == 1);
Test.Assert(10 &+ sf == 2);
Test.Assert(sf &+ 1.0f == 3);
Test.Assert(2.0f &+ sf == 3);
StructH sh = default;
Test.Assert(sh + 10 == 1);
Test.Assert(10 + sh == 2);
Test.Assert(sh + 1.0f == 3);
Test.Assert(2.0f + sh == 3);
Test.Assert(sh &+ 10 == 4);
Test.Assert(10 &+ sh == 5);
Test.Assert(sh &+ 1.0f == 6);
Test.Assert(2.0f &+ sh == 6);
StructG sg = .(100); StructG sg = .(100);
StructG sg2 = .(200); StructG sg2 = .(200);