Skip to content

Commit

Permalink
add an (internal) constness property to EidosValue
Browse files Browse the repository at this point in the history
  • Loading branch information
bhaller committed Dec 23, 2023
1 parent 2c6d069 commit 0c8e4de
Show file tree
Hide file tree
Showing 18 changed files with 362 additions and 129 deletions.
3 changes: 3 additions & 0 deletions core/community.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ extern "C" {

Community::Community(void) : self_symbol_(gID_community, EidosValue_SP(new (gEidosValuePool->AllocateChunk()) EidosValue_Object_singleton(this, gSLiM_Community_Class)))
{
// self_symbol_ is always a constant, but can't be marked as such on construction
self_symbol_.second->MarkAsConstant();

// BCH 3/16/2022: We used to allocate the Species object here, as the first thing we did. In SLiM 4 there can
// be multiple species and they can have names other than "sim", so we delay species creation until parse time.

Expand Down
3 changes: 3 additions & 0 deletions core/genomic_element_type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ GenomicElementType::GenomicElementType(Species &p_species, slim_objectid_t p_gen
self_symbol_(EidosStringRegistry::GlobalStringIDForString(SLiMEidosScript::IDStringWithPrefix('g', p_genomic_element_type_id)), EidosValue_SP(new (gEidosValuePool->AllocateChunk()) EidosValue_Object_singleton(this, gSLiM_GenomicElementType_Class))),
species_(p_species), genomic_element_type_id_(p_genomic_element_type_id), mutation_type_ptrs_(std::move(p_mutation_type_ptrs)), mutation_fractions_(std::move(p_mutation_fractions)), mutation_matrix_(nullptr)
{
// self_symbol_ is always a constant, but can't be marked as such on construction
self_symbol_.second->MarkAsConstant();

InitializeDraws();
}

Expand Down
3 changes: 3 additions & 0 deletions core/interaction_type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ InteractionType::InteractionType(Community &p_community, slim_objectid_t p_inter
spatiality_string_(std::move(p_spatiality_string)), reciprocal_(p_reciprocal), max_distance_(p_max_distance), max_distance_sq_(p_max_distance * p_max_distance), if_type_(SpatialKernelType::kFixed), if_param1_(1.0), if_param2_(0.0),
community_(p_community), interaction_type_id_(p_interaction_type_id)
{
// self_symbol_ is always a constant, but can't be marked as such on construction
self_symbol_.second->MarkAsConstant();

// Figure out our spatiality, which is the number of spatial dimensions we actively use for distances
if (spatiality_string_ == "") { spatiality_ = 0; required_dimensionality_ = 0; }
else if (spatiality_string_ == "x") { spatiality_ = 1; required_dimensionality_ = 1; }
Expand Down
3 changes: 3 additions & 0 deletions core/mutation_type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ self_symbol_(EidosStringRegistry::GlobalStringIDForString(SLiMEidosScript::IDStr
, mutation_type_index_(p_mutation_type_index)
#endif
{
// self_symbol_ is always a constant, but can't be marked as such on construction
self_symbol_.second->MarkAsConstant();

// In WF models, convertToSubstitution defaults to T; in nonWF models it defaults to F as specified above
if (species_.community_.ModelType() == SLiMModelType::kModelTypeWF)
convert_to_substitution_ = true;
Expand Down
8 changes: 8 additions & 0 deletions core/slim_eidos_block.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -788,6 +788,10 @@ SLiMEidosBlock::SLiMEidosBlock(EidosASTNode *p_root_node) :
script_block_symbol_(gEidosID_none, EidosValue_SP(new (gEidosValuePool->AllocateChunk()) EidosValue_Object_singleton(this, gSLiM_SLiMEidosBlock_Class))),
root_node_(p_root_node), user_script_line_offset_(p_root_node->token_->token_line_)
{
// self_symbol_ is always a constant, but can't be marked as such on construction
self_symbol_.second->MarkAsConstant();
script_block_symbol_.second->MarkAsConstant();

// NOTE: SLiMEidosBlock::BlockTypeForRootNode() above must be maintained in parallel with this method!
const std::vector<EidosASTNode *> &block_children = root_node_->children_;
int child_index = 0, n_children = (int)block_children.size();
Expand Down Expand Up @@ -1118,6 +1122,10 @@ SLiMEidosBlock::SLiMEidosBlock(slim_objectid_t p_id, const std::string &p_script
script_block_symbol_(EidosStringRegistry::GlobalStringIDForString(SLiMEidosScript::IDStringWithPrefix('s', p_id)), EidosValue_SP(new (gEidosValuePool->AllocateChunk()) EidosValue_Object_singleton(this, gSLiM_SLiMEidosBlock_Class))),
type_(p_type), block_id_(p_id), start_tick_(p_start), end_tick_(p_end), species_spec_(p_species_spec), ticks_spec_(p_ticks_spec), user_script_line_offset_(p_user_script_line_offset)
{
// self_symbol_ is always a constant, but can't be marked as such on construction
self_symbol_.second->MarkAsConstant();
script_block_symbol_.second->MarkAsConstant();

script_ = new EidosScript(p_script_string, p_user_script_line_offset);
// the caller should now call TokenizeAndParse() to complete initialization
}
Expand Down
3 changes: 3 additions & 0 deletions core/species.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ Species::Species(Community &p_community, slim_objectid_t p_species_id, const std
self_symbol_(EidosStringRegistry::GlobalStringIDForString(p_name), EidosValue_SP(new (gEidosValuePool->AllocateChunk()) EidosValue_Object_singleton(this, gSLiM_Species_Class))),
x_experiments_enabled_(false), model_type_(p_community.model_type_), community_(p_community), population_(*this), name_(p_name), species_id_(p_species_id)
{
// self_symbol_ is always a constant, but can't be marked as such on construction
self_symbol_.second->MarkAsConstant();

#ifdef SLIMGUI
// Pedigree recording is always enabled when running under SLiMgui, so that the various graphs all work
// However, as with tree-sequence recording, the fact that it is enabled is not user-visible unless the user enables it
Expand Down
6 changes: 6 additions & 0 deletions core/subpopulation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -841,6 +841,9 @@ Subpopulation::Subpopulation(Population &p_population, slim_objectid_t p_subpopu
, gui_premigration_size_(p_subpop_size)
#endif
{
// self_symbol_ is always a constant, but can't be marked as such on construction
self_symbol_.second->MarkAsConstant();

if (model_type_ == SLiMModelType::kModelTypeWF)
{
GenerateParentsToFit(/* p_initial_age */ -1, /* p_sex_ratio */ 0.0, /* p_allow_zero_size */ false, /* p_require_both_sexes */ true, /* p_record_in_treeseq */ p_record_in_treeseq, p_haploid, /* p_mean_parent_age */ -1.0F);
Expand Down Expand Up @@ -881,6 +884,9 @@ Subpopulation::Subpopulation(Population &p_population, slim_objectid_t p_subpopu
, gui_premigration_size_(p_subpop_size)
#endif
{
// self_symbol_ is always a constant, but can't be marked as such on construction
self_symbol_.second->MarkAsConstant();

if (model_type_ == SLiMModelType::kModelTypeWF)
{
GenerateParentsToFit(/* p_initial_age */ -1, /* p_sex_ratio */ p_sex_ratio, /* p_allow_zero_size */ false, /* p_require_both_sexes */ true, /* p_record_in_treeseq */ p_record_in_treeseq, p_haploid, /* p_mean_parent_age */ -1.0F);
Expand Down
9 changes: 9 additions & 0 deletions eidos/eidos_ast_node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ void EidosASTNode::_OptimizeConstants(void) const
{
try {
cached_literal_value_ = EidosInterpreter::NumericValueForString(token_->token_string_, token_);
cached_literal_value_->MarkAsConstant();
}
catch (...) { // NOLINT(*-empty-catch) : intentional empty catch
// if EidosInterpreter::NumericValueForString() raises, we just don't cache the value
Expand All @@ -102,11 +103,13 @@ void EidosASTNode::_OptimizeConstants(void) const
{
// This is taken from EidosInterpreter::Evaluate_String and needs to match exactly!
cached_literal_value_ = EidosValue_SP(new (gEidosValuePool->AllocateChunk()) EidosValue_String_singleton(token_->token_string_));
cached_literal_value_->MarkAsConstant();
}
else if (token_type == EidosTokenType::kTokenIdentifier)
{
// Cache values for built-in constants; these can't be changed, so this should be safe, and
// should be much faster than having to scan up through all the symbol tables recursively
// Note that these values are all constants already, so MarkAsConstant() is not needed.
if (token_->token_string_ == gEidosStr_F)
cached_literal_value_ = gStaticEidosValue_LogicalF;
else if (token_->token_string_ == gEidosStr_T)
Expand Down Expand Up @@ -135,7 +138,10 @@ void EidosASTNode::_OptimizeConstants(void) const
const EidosASTNode *child = children_[0];

if (child->cached_literal_value_)
{
cached_return_value_ = child->cached_literal_value_;
cached_return_value_->MarkAsConstant(); // should already be marked constant, actually
}
}
}
else if (token_type == EidosTokenType::kTokenLBrace)
Expand All @@ -150,7 +156,10 @@ void EidosASTNode::_OptimizeConstants(void) const
const EidosASTNode *child = children_[0];

if (child->cached_return_value_ && (child->token_->token_type_ == EidosTokenType::kTokenReturn))
{
cached_return_value_ = child->cached_return_value_;
cached_return_value_->MarkAsConstant(); // should already be marked constant, actually
}
}
}
}
Expand Down
8 changes: 8 additions & 0 deletions eidos/eidos_call_signature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,14 @@ EidosCallSignature *EidosCallSignature::AddArgWithDefault(EidosValueMask p_arg_m
EIDOS_TERMINATION << "ERROR (EidosCallSignature::AddArgWithDefault): (internal error) an object element type may only be supplied for an argument of object type." << EidosTerminate(nullptr);
}

// Default values should be marked constant, just to be safe. We just make a copy here;
// it's not worth trying to avoid that, since this is just startup overhead.
if (p_default_value)
{
p_default_value = p_default_value->CopyValues();
p_default_value->MarkAsConstant();
}

arg_masks_.emplace_back(p_arg_mask);
arg_names_.emplace_back(p_argument_name);
arg_name_IDs_.emplace_back(EidosStringRegistry::GlobalStringIDForString(p_argument_name));
Expand Down
2 changes: 1 addition & 1 deletion eidos/eidos_class_Object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ void EidosObject::SetProperty(EidosGlobalStringID p_property_id, const EidosValu

bool readonly = signature->read_only_;

// Check whether setting a constant was attempted; we can do this on behalf of all our subclasses
// Check whether setting a read-only property was attempted; we can do this on behalf of all our subclasses
if (readonly)
EIDOS_TERMINATION << "ERROR (EidosObject::SetProperty for " << Class()->ClassName() << "): attempt to set a new value for read-only property " << EidosStringRegistry::StringForGlobalStringID(p_property_id) << "." << EidosTerminate(nullptr);
else
Expand Down
61 changes: 54 additions & 7 deletions eidos/eidos_globals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1080,7 +1080,6 @@ void Eidos_WarmUp(void)
// Make the shared EidosValue pool
size_t maxEidosValueSize = sizeof(EidosValue_NULL);
maxEidosValueSize = std::max(maxEidosValueSize, sizeof(EidosValue_Logical));
maxEidosValueSize = std::max(maxEidosValueSize, sizeof(EidosValue_Logical_const));
maxEidosValueSize = std::max(maxEidosValueSize, sizeof(EidosValue_String));
maxEidosValueSize = std::max(maxEidosValueSize, sizeof(EidosValue_String_vector));
maxEidosValueSize = std::max(maxEidosValueSize, sizeof(EidosValue_String_singleton));
Expand All @@ -1097,7 +1096,6 @@ void Eidos_WarmUp(void)
// std::cout << "sizeof(EidosValue) == " << sizeof(EidosValue) << std::endl;
// std::cout << "sizeof(EidosValue_NULL) == " << sizeof(EidosValue_NULL) << std::endl;
// std::cout << "sizeof(EidosValue_Logical) == " << sizeof(EidosValue_Logical) << std::endl;
// std::cout << "sizeof(EidosValue_Logical_const) == " << sizeof(EidosValue_Logical_const) << std::endl;
// std::cout << "sizeof(EidosValue_String) == " << sizeof(EidosValue_String) << std::endl;
// std::cout << "sizeof(EidosValue_String_vector) == " << sizeof(EidosValue_String_vector) << std::endl;
// std::cout << "sizeof(EidosValue_String_singleton) == " << sizeof(EidosValue_String_singleton) << std::endl;
Expand All @@ -1117,44 +1115,91 @@ void Eidos_WarmUp(void)
// Make the shared EidosASTNode pool
gEidosASTNodePool = new EidosObjectPool("EidosObjectPool(EidosASTNode)", sizeof(EidosASTNode));

// Allocate global permanents
// Allocate global permanents; the first five are fundamental, and get created as statics very early.
// The other constants are all created here, and should all be marked as constant here.
gStaticEidosValueVOID = EidosValue_VOID::Static_EidosValue_VOID();

gStaticEidosValueNULL = EidosValue_NULL::Static_EidosValue_NULL();
gStaticEidosValueNULLInvisible = EidosValue_NULL::Static_EidosValue_NULL_Invisible();
gStaticEidosValue_LogicalT = EidosValue_Logical::Static_EidosValue_Logical_T();
gStaticEidosValue_LogicalF = EidosValue_Logical::Static_EidosValue_Logical_F();

gStaticEidosValue_Logical_ZeroVec = EidosValue_Logical_SP(new (gEidosValuePool->AllocateChunk()) EidosValue_Logical());
gStaticEidosValue_Logical_ZeroVec->MarkAsConstant();

gStaticEidosValue_Integer_ZeroVec = EidosValue_Int_SP(new (gEidosValuePool->AllocateChunk()) EidosValue_Int_vector());
gStaticEidosValue_Integer_ZeroVec->MarkAsConstant();

gStaticEidosValue_Float_ZeroVec = EidosValue_Float_SP(new (gEidosValuePool->AllocateChunk()) EidosValue_Float_vector());
gStaticEidosValue_String_ZeroVec = EidosValue_String_SP(new (gEidosValuePool->AllocateChunk()) EidosValue_String_vector());
gStaticEidosValue_Float_ZeroVec->MarkAsConstant();

gStaticEidosValue_LogicalT = EidosValue_Logical_const::Static_EidosValue_Logical_T();
gStaticEidosValue_LogicalF = EidosValue_Logical_const::Static_EidosValue_Logical_F();
gStaticEidosValue_String_ZeroVec = EidosValue_String_SP(new (gEidosValuePool->AllocateChunk()) EidosValue_String_vector());
gStaticEidosValue_String_ZeroVec->MarkAsConstant();

gStaticEidosValue_Integer0 = EidosValue_Int_SP(new (gEidosValuePool->AllocateChunk()) EidosValue_Int_singleton(0));
gStaticEidosValue_Integer0->MarkAsConstant();

gStaticEidosValue_Integer1 = EidosValue_Int_SP(new (gEidosValuePool->AllocateChunk()) EidosValue_Int_singleton(1));
gStaticEidosValue_Integer1->MarkAsConstant();

gStaticEidosValue_Integer2 = EidosValue_Int_SP(new (gEidosValuePool->AllocateChunk()) EidosValue_Int_singleton(2));
gStaticEidosValue_Integer2->MarkAsConstant();

gStaticEidosValue_Integer3 = EidosValue_Int_SP(new (gEidosValuePool->AllocateChunk()) EidosValue_Int_singleton(3));
gStaticEidosValue_Integer3->MarkAsConstant();

gStaticEidosValue_Float0 = EidosValue_Float_SP(new (gEidosValuePool->AllocateChunk()) EidosValue_Float_singleton(0.0));
gStaticEidosValue_Float0->MarkAsConstant();

gStaticEidosValue_Float0Point5 = EidosValue_Float_SP(new (gEidosValuePool->AllocateChunk()) EidosValue_Float_singleton(0.5));
gStaticEidosValue_Float0Point5->MarkAsConstant();

gStaticEidosValue_Float1 = EidosValue_Float_SP(new (gEidosValuePool->AllocateChunk()) EidosValue_Float_singleton(1.0));
gStaticEidosValue_Float1->MarkAsConstant();

gStaticEidosValue_Float10 = EidosValue_Float_SP(new (gEidosValuePool->AllocateChunk()) EidosValue_Float_singleton(10.0));
gStaticEidosValue_Float10->MarkAsConstant();

gStaticEidosValue_FloatINF = EidosValue_Float_SP(new (gEidosValuePool->AllocateChunk()) EidosValue_Float_singleton(std::numeric_limits<double>::infinity()));
gStaticEidosValue_FloatINF->MarkAsConstant();

gStaticEidosValue_FloatNAN = EidosValue_Float_SP(new (gEidosValuePool->AllocateChunk()) EidosValue_Float_singleton(std::numeric_limits<double>::quiet_NaN()));
gStaticEidosValue_FloatNAN->MarkAsConstant();

gStaticEidosValue_FloatE = EidosValue_Float_SP(new (gEidosValuePool->AllocateChunk()) EidosValue_Float_singleton(M_E));
gStaticEidosValue_FloatE->MarkAsConstant();

gStaticEidosValue_FloatPI = EidosValue_Float_SP(new (gEidosValuePool->AllocateChunk()) EidosValue_Float_singleton(M_PI));
gStaticEidosValue_FloatPI->MarkAsConstant();

gStaticEidosValue_StringEmpty = EidosValue_String_SP(new (gEidosValuePool->AllocateChunk()) EidosValue_String_singleton(""));
gStaticEidosValue_StringEmpty->MarkAsConstant();

gStaticEidosValue_StringSpace = EidosValue_String_SP(new (gEidosValuePool->AllocateChunk()) EidosValue_String_singleton(" "));
gStaticEidosValue_StringSpace->MarkAsConstant();

gStaticEidosValue_StringAsterisk = EidosValue_String_SP(new (gEidosValuePool->AllocateChunk()) EidosValue_String_singleton("*"));
gStaticEidosValue_StringAsterisk->MarkAsConstant();

gStaticEidosValue_StringDoubleAsterisk = EidosValue_String_SP(new (gEidosValuePool->AllocateChunk()) EidosValue_String_singleton("**"));
gStaticEidosValue_StringDoubleAsterisk->MarkAsConstant();

gStaticEidosValue_StringComma = EidosValue_String_SP(new (gEidosValuePool->AllocateChunk()) EidosValue_String_singleton(","));
gStaticEidosValue_StringComma->MarkAsConstant();

gStaticEidosValue_StringPeriod = EidosValue_String_SP(new (gEidosValuePool->AllocateChunk()) EidosValue_String_singleton("."));
gStaticEidosValue_StringPeriod->MarkAsConstant();

gStaticEidosValue_StringDoubleQuote = EidosValue_String_SP(new (gEidosValuePool->AllocateChunk()) EidosValue_String_singleton("\""));
gStaticEidosValue_StringDoubleQuote->MarkAsConstant();

gStaticEidosValue_String_ECMAScript = EidosValue_String_SP(new (gEidosValuePool->AllocateChunk()) EidosValue_String_singleton("ECMAScript"));
gStaticEidosValue_String_ECMAScript->MarkAsConstant();

gStaticEidosValue_String_indices = EidosValue_String_SP(new (gEidosValuePool->AllocateChunk()) EidosValue_String_singleton("indices"));
gStaticEidosValue_String_indices->MarkAsConstant();

gStaticEidosValue_String_average = EidosValue_String_SP(new (gEidosValuePool->AllocateChunk()) EidosValue_String_singleton("average"));
gStaticEidosValue_String_average->MarkAsConstant();

// Create the global class objects for all Eidos classes, from superclass to subclass
// This breaks encapsulation, kind of, but it needs to be done here, in order, so that superclass objects exist,
Expand All @@ -1170,6 +1215,7 @@ void Eidos_WarmUp(void)
// This has to be allocated after gEidosObject_Class has been initialized above; the other global permanents must be initialized
// before that point, however, since properties and method signatures may use some of those global permanent values
gStaticEidosValue_Object_ZeroVec = EidosValue_Object_SP(new (gEidosValuePool->AllocateChunk()) EidosValue_Object_vector(gEidosObject_Class));
gStaticEidosValue_Object_ZeroVec->MarkAsConstant();

// Set up the built-in function map, which is immutable
EidosInterpreter::CacheBuiltInFunctionMap();
Expand Down Expand Up @@ -1287,6 +1333,7 @@ EidosValue_SP Eidos_ValueForCommandLineExpression(std::string &p_value_expressio
EidosInterpreter interpreter(script, symbol_table, function_map, nullptr, std::cout, std::cerr); // we're at the command line, so we assume we're using stdout/stderr

value = interpreter.EvaluateInterpreterBlock(false, true); // do not print output, return the last statement value
value->MarkAsConstant();

return value;
}
Expand Down
2 changes: 0 additions & 2 deletions eidos/eidos_globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -1186,7 +1186,6 @@ class EidosValue;
class EidosValue_VOID;
class EidosValue_NULL;
class EidosValue_Logical;
class EidosValue_Logical_const;
class EidosValue_Int;
class EidosValue_Int_singleton;
class EidosValue_Int_vector;
Expand Down Expand Up @@ -1228,7 +1227,6 @@ typedef Eidos_intrusive_ptr<EidosValue> EidosValue_SP;
typedef Eidos_intrusive_ptr<EidosValue_VOID> EidosValue_VOID_SP;
typedef Eidos_intrusive_ptr<EidosValue_NULL> EidosValue_NULL_SP;
typedef Eidos_intrusive_ptr<EidosValue_Logical> EidosValue_Logical_SP;
typedef Eidos_intrusive_ptr<EidosValue_Logical_const> EidosValue_Logical_const_SP;
typedef Eidos_intrusive_ptr<EidosValue_Int> EidosValue_Int_SP;
typedef Eidos_intrusive_ptr<EidosValue_Int_singleton> EidosValue_Int_singleton_SP;
typedef Eidos_intrusive_ptr<EidosValue_Int_vector> EidosValue_Int_vector_SP;
Expand Down
Loading

0 comments on commit 0c8e4de

Please sign in to comment.