Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions .github/workflows/auto-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ name: Automated test
permissions:
contents: read

on:
push:
branches: [ "master" ]
on: [push, pull_request]

jobs:
Linux_x86-64_GCC:
Expand Down
4 changes: 4 additions & 0 deletions sdk/angelscript/include/angelscript.h
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,10 @@ enum asEBehaviours
asBEHAVE_RELEASEREFS,
asBEHAVE_LAST_GC = asBEHAVE_RELEASEREFS,

// User-defined literal support
asBEHAVE_LITERAL_CONSTRUCT,
asBEHAVE_LITERAL_CALLBACK,

asBEHAVE_MAX
};

Expand Down
18 changes: 15 additions & 3 deletions sdk/angelscript/source/as_builder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1310,12 +1310,14 @@ asCGlobalProperty *asCBuilder::GetGlobalProperty(const char *prop, asSNameSpace
return 0;
}

int asCBuilder::ParseFunctionDeclaration(asCObjectType *objType, const char *decl, asCScriptFunction *func, bool isSystemFunction, asCArray<bool> *paramAutoHandles, bool *returnAutoHandle, asSNameSpace *ns, asCScriptNode **listPattern, asCObjectType **outParentClass)
int asCBuilder::ParseFunctionDeclaration(asCObjectType *objType, const char *decl, asCScriptFunction *func, bool isSystemFunction, asCArray<bool> *paramAutoHandles, bool *returnAutoHandle, asSNameSpace *ns, asCScriptNode **listPattern, asCScriptNode **literalPattern, asCObjectType **outParentClass)
{
asASSERT( objType || ns );

if (listPattern)
*listPattern = 0;
if (literalPattern)
*literalPattern = 0;
if (outParentClass)
*outParentClass = 0;

Expand All @@ -1327,7 +1329,7 @@ int asCBuilder::ParseFunctionDeclaration(asCObjectType *objType, const char *dec
source.SetCode(TXT_SYSTEM_FUNCTION, decl, true);

asCParser parser(this);
int r = parser.ParseFunctionDefinition(&source, listPattern != 0);
int r = parser.ParseFunctionDefinition(&source, listPattern != 0, literalPattern != 0);
if( r < 0 )
return asINVALID_DECLARATION;

Expand Down Expand Up @@ -1503,7 +1505,7 @@ int asCBuilder::ParseFunctionDeclaration(asCObjectType *objType, const char *dec
n = n->next;
}

// If the caller expects a list pattern, check for the existence, else report an error if not
// If the caller expects a list or literal pattern, check for the existence, else report an error if not
if( listPattern )
{
if( n == 0 || n->nodeType != snListPattern )
Expand All @@ -1514,6 +1516,16 @@ int asCBuilder::ParseFunctionDeclaration(asCObjectType *objType, const char *dec
n->DisconnectParent();
}
}
else if( literalPattern )
{
if( n == 0 || n->nodeType != snLiteralPattern )
return asINVALID_DECLARATION;
else
{
*literalPattern = n;
n->DisconnectParent();
}
}
else
{
if( n )
Expand Down
2 changes: 1 addition & 1 deletion sdk/angelscript/source/as_builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ class asCBuilder
int VerifyProperty(asCDataType *dt, const char *decl, asCString &outName, asCDataType &outType, asSNameSpace *ns);
int ParseDataType(const char *datatype, asCDataType *result, asSNameSpace *implicitNamespace, bool isReturnType = false);
int ParseTemplateDecl(const char *decl, asCString *name, asCArray<asCString> &subtypeNames);
int ParseFunctionDeclaration(asCObjectType *type, const char *decl, asCScriptFunction *func, bool isSystemFunction, asCArray<bool> *paramAutoHandles = 0, bool *returnAutoHandle = 0, asSNameSpace *ns = 0, asCScriptNode **outListPattern = 0, asCObjectType **outParentClass = 0);
int ParseFunctionDeclaration(asCObjectType *type, const char *decl, asCScriptFunction *func, bool isSystemFunction, asCArray<bool> *paramAutoHandles = 0, bool *returnAutoHandle = 0, asSNameSpace *ns = 0, asCScriptNode **outListPattern = 0, asCScriptNode **outLiteralPattern = 0, asCObjectType **outParentClass = 0);
int ParseVariableDeclaration(const char *decl, asSNameSpace *implicitNamespace, asCString &outName, asSNameSpace *&outNamespace, asCDataType &outDt);
int CheckNameConflict(const char *name, asCScriptNode *node, asCScriptCode *code, asSNameSpace *ns, bool isProperty, bool isVirtualProperty, bool isSharedIntf);
int CheckNameConflictMember(asCTypeInfo *type, const char *name, asCScriptNode *node, asCScriptCode *code, bool isProperty, bool isVirtualProperty);
Expand Down
103 changes: 102 additions & 1 deletion sdk/angelscript/source/as_compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10826,6 +10826,99 @@ int asCCompiler::CompilePostFixExpression(asCArray<asCScriptNode *> *postfix, as
return ret;
}


// Compile a user-defined literal expression (e.g., 3.14_f32)
// constNode is the snConstant node with an snUserLiteral child
// ctx contains the constant value in ctx->type from CompileExpressionValue
void asCCompiler::CompileUserLiteral(asCScriptNode *constNode, asCExprContext *ctx)
{
// Get the suffix name from the snIdentifier child of snUserLiteral
asCScriptNode *userLiteralNode = constNode->firstChild;
asASSERT(userLiteralNode && userLiteralNode->nodeType == snUserLiteral);
asCScriptNode *identNode = userLiteralNode->firstChild;
asASSERT(identNode && identNode->nodeType == snIdentifier);
asCString suffix(&script->code[identNode->tokenPos], identNode->tokenLength);

// Look up the function ID from the appropriate suffix map
int funcId = 0;
switch (constNode->tokenType)
{
case ttIntConstant:
case ttBitsConstant:
{
asSMapNode<asCString, int> *cursor = 0;
if (engine->literals.suffix.uint64Literals.MoveTo(&cursor, suffix))
funcId = cursor->value;
}
break;
case ttFloatConstant:
case ttDoubleConstant:
{
asSMapNode<asCString, int> *cursor = 0;
if (engine->literals.suffix.doubleLiterals.MoveTo(&cursor, suffix))
funcId = cursor->value;
}
break;
default:
break;
}

if (funcId == 0 || funcId >= (int)engine->scriptFunctions.GetLength())
{
asCString msg;
msg.Format(TXT_NO_MATCHING_SIGNATURES_TO_s, suffix.AddressOf());
Error(msg, constNode);
ctx->type.SetDummy();
return;
}

asCScriptFunction *funcDesc = engine->scriptFunctions[funcId];
asCObjectType *objType = funcDesc->objectType;
if (!objType || !(objType->flags & asOBJ_VALUE))
{
asCString msg;
msg.Format(TXT_NO_MATCHING_SIGNATURES_TO_s, suffix.AddressOf());
Error(msg, constNode);
ctx->type.SetDummy();
return;
}

// Allocate a temp variable for the constructed object
asCDataType targetType = asCDataType::CreateType(objType, false);
int offset = AllocateVariable(targetType, true);

// Create an argument expression context with the constant value
asCExprContext *arg = asNEW(asCExprContext)(engine);
arg->type = ctx->type;
arg->exprNode = constNode;

asCArray<asCExprContext *> args;
args.PushLast(arg);

// Prepare the argument and move it to the stack
PrepareFunctionCall(funcId, &ctx->bc, args);
MoveArgsToStack(funcId, &ctx->bc, args, false);

// Push the object address for OBJLAST calling convention
ctx->bc.InstrSHORT(asBC_PSF, (short)offset);

// Call the literal construct function
PerformFunctionCall(funcId, ctx, false, &args, objType);

// Mark the temp variable as initialized
ctx->bc.ObjInfo(offset, asOBJ_INIT);

// Set the return type to the constructed object
ctx->type.SetVariable(targetType, offset, true);
ctx->type.dataType.MakeReference(false);

// Push the object address for the expression chain
ctx->bc.InstrSHORT(asBC_PSF, (short)offset);

// Clean up
asDELETE(arg, asCExprContext);
}

int asCCompiler::CompileAnonymousInitList(asCScriptNode *node, asCExprContext *ctx, const asCDataType &dt)
{
asASSERT(node->nodeType == snInitList);
Expand Down Expand Up @@ -12050,7 +12143,7 @@ int asCCompiler::CompileExpressionValue(asCScriptNode *node, asCExprContext *ctx
size_t numScanned;
double v = asStringScanDouble(value.AddressOf(), &numScanned);
ctx->type.SetConstantD(asCDataType::CreatePrimitive(ttDouble, true), v);
asASSERT(numScanned == vnode->tokenLength);
if (numScanned != vnode->tokenLength && !(vnode->firstChild && vnode->firstChild->nodeType == snUserLiteral)) asASSERT(false);
}
else if( vnode->tokenType == ttTrue ||
vnode->tokenType == ttFalse )
Expand Down Expand Up @@ -12167,6 +12260,14 @@ int asCCompiler::CompileExpressionValue(asCScriptNode *node, asCExprContext *ctx
}
else
asASSERT(false);

// Check for user literal suffix on numeric constants
if (vnode->firstChild &&
vnode->firstChild->nodeType == snUserLiteral)
{
CompileUserLiteral(vnode, ctx);
return 0;
}
}
else if( vnode->nodeType == snFunctionCall )
{
Expand Down
2 changes: 2 additions & 0 deletions sdk/angelscript/source/as_compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,8 @@ class asCCompiler
int CompileInitListElement(asSListPatternNode *&patternNode, asCScriptNode *&valueNode, int bufferTypeId, short bufferVar, asUINT &bufferSize, asCByteCode &byteCode, int &elementsInSubList);
int CompileAnonymousInitList(asCScriptNode *listNode, asCExprContext *ctx, const asCDataType &dt);

void CompileUserLiteral(asCScriptNode *constNode, asCExprContext *ctx);

int CallDefaultConstructor(const asCDataType &type, int offset, bool isObjectOnHeap, asCByteCode *bc, asCScriptNode *node, EVarGlobOrMem isVarGlobOrMem = asVGM_VARIABLE, bool derefDest = false);
int CallCopyConstructor(asCDataType &type, int offset, bool isObjectOnHeap, asCExprContext *ctx, asCExprContext *arg, asCScriptNode *node, EVarGlobOrMem isVarGlobOrMem = asVGM_VARIABLE, bool derefDestination = false);
void CallDestructor(asCDataType &type, int offset, bool isObjectOnHeap, asCByteCode *bc);
Expand Down
1 change: 0 additions & 1 deletion sdk/angelscript/source/as_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2325,7 +2325,6 @@ static const void *const dispatch_table[256] = {
asDWORD *old = l_bc;
#endif


// Remember to keep the cases in order and without
// gaps, because that will make the switch faster.
// It will be faster since only one lookup will be
Expand Down
2 changes: 2 additions & 0 deletions sdk/angelscript/source/as_objecttype.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,12 @@ struct asSTypeBehaviour
gcReleaseAllReferences = 0;
templateCallback = 0;
getWeakRefFlag = 0;
literalFactory = 0;
}

int factory;
int listFactory; // Used for initialization lists only
int literalFactory; // Used for user literal suffixes
int copyfactory;
int construct;
int copyconstruct;
Expand Down
Loading
Loading