@@ -429,7 +429,8 @@ bool AddDependencyGenerator(EvaluatorEnvironment& environment, const EvaluatorCo
429
429
}
430
430
431
431
bool DefunGenerator (EvaluatorEnvironment& environment, const EvaluatorContext& context,
432
- const std::vector<Token>& tokens, int startTokenIndex, GeneratorOutput& output)
432
+ const std::vector<Token>& tokens, int startTokenIndex,
433
+ GeneratorOutput& runtimeOutput)
433
434
{
434
435
if (!ExpectEvaluatorScope (" defun" , tokens[startTokenIndex], context, EvaluatorScope_Module))
435
436
return false ;
@@ -452,6 +453,26 @@ bool DefunGenerator(EvaluatorEnvironment& environment, const EvaluatorContext& c
452
453
return false ;
453
454
454
455
bool isModuleLocal = tokens[startTokenIndex + 1 ].contents .compare (" defun-local" ) == 0 ;
456
+ bool isCompileTime = tokens[startTokenIndex + 1 ].contents .compare (" defun-comptime" ) == 0 ;
457
+ GeneratorOutput* functionOutput = isCompileTime ? new GeneratorOutput : &runtimeOutput;
458
+
459
+ // Register definition before evaluating body, otherwise references in body will be orphaned
460
+ {
461
+ ObjectDefinition newFunctionDef = {};
462
+ newFunctionDef.name = &nameToken;
463
+ newFunctionDef.type = isCompileTime ? ObjectType_CompileTimeFunction : ObjectType_Function;
464
+ // Compile-time objects only get built with compile-time references
465
+ newFunctionDef.isRequired = isCompileTime ? false : context.isRequired ;
466
+ if (isCompileTime)
467
+ newFunctionDef.output = functionOutput;
468
+ if (!addObjectDefinition (environment, newFunctionDef))
469
+ {
470
+ if (isCompileTime)
471
+ delete functionOutput;
472
+ return false ;
473
+ }
474
+ // Past this point, compile-time output will be handled by environment destruction
475
+ }
455
476
456
477
int returnTypeStart = -1 ;
457
478
std::vector<FunctionArgumentTokens> arguments;
@@ -460,30 +481,32 @@ bool DefunGenerator(EvaluatorEnvironment& environment, const EvaluatorContext& c
460
481
461
482
if (environment.enableHotReloading )
462
483
{
463
- addStringOutput (isModuleLocal ? output. source : output. header , " extern \" C \" " ,
464
- StringOutMod_SpaceAfter, &tokens[startTokenIndex]);
484
+ addStringOutput (isModuleLocal ? functionOutput-> source : functionOutput-> header ,
485
+ " extern \" C \" " , StringOutMod_SpaceAfter, &tokens[startTokenIndex]);
465
486
}
466
487
467
488
// TODO: Hot-reloading functions shouldn't be declared static, right?
468
489
if (isModuleLocal)
469
- addStringOutput (output.source , " static" , StringOutMod_SpaceAfter, &tokens[startTokenIndex]);
490
+ addStringOutput (functionOutput->source , " static" , StringOutMod_SpaceAfter,
491
+ &tokens[startTokenIndex]);
470
492
471
493
int endArgsIndex = FindCloseParenTokenIndex (tokens, argsIndex);
472
- if (!outputFunctionReturnType (tokens, output, returnTypeStart, startTokenIndex, endArgsIndex,
494
+ if (!outputFunctionReturnType (tokens, *functionOutput, returnTypeStart, startTokenIndex,
495
+ endArgsIndex,
473
496
/* outputSource=*/ true , /* outputHeader=*/ !isModuleLocal))
474
497
return false ;
475
498
476
- addStringOutput (output. source , nameToken.contents , StringOutMod_ConvertFunctionName,
499
+ addStringOutput (functionOutput-> source , nameToken.contents , StringOutMod_ConvertFunctionName,
477
500
&nameToken);
478
501
if (!isModuleLocal)
479
- addStringOutput (output. header , nameToken.contents , StringOutMod_ConvertFunctionName ,
480
- &nameToken);
502
+ addStringOutput (functionOutput-> header , nameToken.contents ,
503
+ StringOutMod_ConvertFunctionName, &nameToken);
481
504
482
- addLangTokenOutput (output. source , StringOutMod_OpenParen, &argsStart);
505
+ addLangTokenOutput (functionOutput-> source , StringOutMod_OpenParen, &argsStart);
483
506
if (!isModuleLocal)
484
- addLangTokenOutput (output. header , StringOutMod_OpenParen, &argsStart);
507
+ addLangTokenOutput (functionOutput-> header , StringOutMod_OpenParen, &argsStart);
485
508
486
- if (!outputFunctionArguments (tokens, output , arguments, /* outputSource=*/ true ,
509
+ if (!outputFunctionArguments (tokens, *functionOutput , arguments, /* outputSource=*/ true ,
487
510
/* outputHeader=*/ !isModuleLocal))
488
511
return false ;
489
512
@@ -498,41 +521,35 @@ bool DefunGenerator(EvaluatorEnvironment& environment, const EvaluatorContext& c
498
521
argumentsMetadata.push_back ({tokens[arg.nameIndex ].contents , startTypeToken, endTypeToken});
499
522
}
500
523
501
- addLangTokenOutput (output. source , StringOutMod_CloseParen, &tokens[endArgsIndex]);
524
+ addLangTokenOutput (functionOutput-> source , StringOutMod_CloseParen, &tokens[endArgsIndex]);
502
525
if (!isModuleLocal)
503
526
{
504
- addLangTokenOutput (output. header , StringOutMod_CloseParen, &tokens[endArgsIndex]);
527
+ addLangTokenOutput (functionOutput-> header , StringOutMod_CloseParen, &tokens[endArgsIndex]);
505
528
// Forward declarations end with ;
506
- addLangTokenOutput (output.header , StringOutMod_EndStatement, &tokens[endArgsIndex]);
507
- }
508
-
509
- // Register definition before evaluating body, otherwise references in body will be orphaned
510
- {
511
- ObjectDefinition newFunctionDef = {};
512
- newFunctionDef.name = &nameToken;
513
- newFunctionDef.type = ObjectType_Function;
514
- newFunctionDef.isRequired = context.isRequired ;
515
- if (!addObjectDefinition (environment, newFunctionDef))
516
- return false ;
529
+ addLangTokenOutput (functionOutput->header , StringOutMod_EndStatement,
530
+ &tokens[endArgsIndex]);
517
531
}
518
532
519
533
int startBodyIndex = endArgsIndex + 1 ;
520
- addLangTokenOutput (output. source , StringOutMod_OpenBlock, &tokens[startBodyIndex]);
534
+ addLangTokenOutput (functionOutput-> source , StringOutMod_OpenBlock, &tokens[startBodyIndex]);
521
535
522
536
// Evaluate our body!
523
537
EvaluatorContext bodyContext = context;
524
538
bodyContext.scope = EvaluatorScope_Body;
525
539
bodyContext.definitionName = &nameToken;
526
540
// The statements will need to handle their ;
527
541
int numErrors = EvaluateGenerateAll_Recursive (environment, bodyContext, tokens, startBodyIndex,
528
- /* delimiterTemplate=*/ nullptr , output );
542
+ /* delimiterTemplate=*/ nullptr , *functionOutput );
529
543
if (numErrors)
544
+ {
545
+ // Don't delete compile time function output. Evaluate may have caused references to it
530
546
return false ;
547
+ }
531
548
532
- addLangTokenOutput (output. source , StringOutMod_CloseBlock, &tokens[endTokenIndex]);
549
+ addLangTokenOutput (functionOutput-> source , StringOutMod_CloseBlock, &tokens[endTokenIndex]);
533
550
534
- output. functions .push_back ({nameToken.contents , &tokens[startTokenIndex],
535
- &tokens[endTokenIndex], std::move (argumentsMetadata)});
551
+ functionOutput-> functions .push_back ({nameToken.contents , &tokens[startTokenIndex],
552
+ &tokens[endTokenIndex], std::move (argumentsMetadata)});
536
553
537
554
return true ;
538
555
}
@@ -1969,6 +1986,7 @@ void importFundamentalGenerators(EvaluatorEnvironment& environment)
1969
1986
1970
1987
environment.generators [" defun" ] = DefunGenerator;
1971
1988
environment.generators [" defun-local" ] = DefunGenerator;
1989
+ environment.generators [" defun-comptime" ] = DefunGenerator;
1972
1990
1973
1991
environment.generators [" def-function-signature" ] = DefFunctionSignatureGenerator;
1974
1992
environment.generators [" def-function-signature-local" ] = DefFunctionSignatureGenerator;
0 commit comments