Skip to content

Commit fd19745

Browse files
committed
Merge branch 'feature/dictionary'
2 parents 4171d08 + e592aaf commit fd19745

File tree

6 files changed

+651
-249
lines changed

6 files changed

+651
-249
lines changed

changes.txt

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,16 @@ Prior to the release of 3.7.1, the following items still need urgent attention:
4949
New Features
5050
------------
5151

52+
- Array elements no longer have to be of the same type.
53+
54+
- Support for variable-size arrays has been added.
55+
56+
- A new data container, `dictionary`, has been added to support structured
57+
storage of data.
58+
59+
- Pseudo-dictionaries `local` and `global` have been added, allowing to
60+
specifically access local or global identifiers, respectively.
61+
5262
- A new special pigment pattern, `user_defined`, has been added to define the
5363
pigment colour directly in terms of a set of functions.
5464

@@ -89,9 +99,6 @@ New Features
8999
assignments. The main purpose is to allow macros to return a set of values
90100
rather than just a single one.
91101

92-
- `local()` and `global()` pseudo-functions have been added to specifically
93-
refer to a local or global identifier, respectively.
94-
95102
- The macro syntax has been extended to allow for optional parameters.
96103

97104
- Light sources' distance-based fading can now be set to obey an inverse-power

source/parser/parser.cpp

Lines changed: 85 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -198,12 +198,12 @@ void Parser::Run()
198198
if(i->second[0] == '\"')
199199
{
200200
string tmp(i->second, 1, i->second.length() - 2);
201-
Temp_Entry = Add_Symbol(1, const_cast<char *>(i->first.c_str()), STRING_ID_TOKEN);
201+
Temp_Entry = Add_Symbol(SYM_TABLE_GLOBAL, const_cast<char *>(i->first.c_str()), STRING_ID_TOKEN);
202202
Temp_Entry->Data = String_Literal_To_UCS2(const_cast<char *>(tmp.c_str()), false);
203203
}
204204
else
205205
{
206-
Temp_Entry = Add_Symbol(1, const_cast<char *>(i->first.c_str()), FLOAT_ID_TOKEN);
206+
Temp_Entry = Add_Symbol(SYM_TABLE_GLOBAL, const_cast<char *>(i->first.c_str()), FLOAT_ID_TOKEN);
207207
Temp_Entry->Data = Create_Float();
208208
*(reinterpret_cast<DBL *>(Temp_Entry->Data)) = atof(i->second.c_str());
209209
}
@@ -8556,7 +8556,7 @@ void Parser::Parse_Declare(bool is_local, bool after_hash)
85568556
}
85578557
else
85588558
{
8559-
Local_Index=1;
8559+
Local_Index = SYM_TABLE_GLOBAL;
85608560
}
85618561

85628562
LValue_Ok = true;
@@ -8608,9 +8608,16 @@ void Parser::Parse_Declare(bool is_local, bool after_hash)
86088608

86098609
EXPECT_ONE
86108610
CASE (IDENTIFIER_TOKEN)
8611-
POV_PARSER_ASSERT(!Token.is_array_elem);
8611+
POV_PARSER_ASSERT(!Token.is_array_elem || Token.is_mixed_array_elem);
86128612
allow_redefine = true; // should actually be irrelevant downstream, thanks to Previous==IDENTIFIER_TOKEN
8613-
Temp_Entry = Add_Symbol (Local_Index,Token.Token_String,IDENTIFIER_TOKEN);
8613+
if (Token.is_array_elem || Token.is_dictionary_elem)
8614+
{
8615+
if (is_local && (Token.context != Table_Index))
8616+
Error ("Cannot use '#local' to assign a non-local array or dictionary element.");
8617+
Temp_Entry = Add_Symbol (Token.table, Token.Token_String, IDENTIFIER_TOKEN);
8618+
}
8619+
else
8620+
Temp_Entry = Add_Symbol (Local_Index, Token.Token_String, IDENTIFIER_TOKEN);
86148621
numberPtr = &(Temp_Entry->Token_Number);
86158622
dataPtr = &(Temp_Entry->Data);
86168623
Previous = Token.Token_Id;
@@ -8648,11 +8655,11 @@ void Parser::Parse_Declare(bool is_local, bool after_hash)
86488655
CASE4 (PIGMENT_MAP_ID_TOKEN, MEDIA_ID_TOKEN, STRING_ID_TOKEN, INTERIOR_ID_TOKEN)
86498656
CASE4 (DENSITY_MAP_ID_TOKEN, ARRAY_ID_TOKEN, DENSITY_ID_TOKEN, UV_ID_TOKEN)
86508657
CASE4 (VECTOR_4D_ID_TOKEN, RAINBOW_ID_TOKEN, FOG_ID_TOKEN, SKYSPHERE_ID_TOKEN)
8651-
CASE2 (MATERIAL_ID_TOKEN, SPLINE_ID_TOKEN )
8652-
if (is_local && (Token.Table_Index != Table_Index))
8658+
CASE3 (MATERIAL_ID_TOKEN, SPLINE_ID_TOKEN, DICTIONARY_ID_TOKEN)
8659+
if (is_local && (Token.context != Table_Index))
86538660
{
8654-
if (Token.is_array_elem)
8655-
Error("Cannot use '#local' to assign a non-local array element.");
8661+
if (Token.is_array_elem || Token.is_dictionary_elem)
8662+
Error ("Cannot use '#local' to assign a non-local array or dictionary element.");
86568663
allow_redefine = true; // should actually be irrelevant downstream, thanks to Previous==IDENTIFIER_TOKEN
86578664
Temp_Entry = Add_Symbol (Local_Index,Token.Token_String,IDENTIFIER_TOKEN);
86588665
numberPtr = &(Temp_Entry->Token_Number);
@@ -8661,7 +8668,7 @@ void Parser::Parse_Declare(bool is_local, bool after_hash)
86618668
}
86628669
else
86638670
{
8664-
allow_redefine = !Token.is_array_elem;
8671+
allow_redefine = !Token.is_array_elem || Token.is_mixed_array_elem;
86658672
numberPtr = Token.NumberPtr;
86668673
dataPtr = Token.DataPtr;
86678674
Previous = Token.Token_Id;
@@ -8681,10 +8688,10 @@ void Parser::Parse_Declare(bool is_local, bool after_hash)
86818688
{
86828689
case VECTOR_ID_TOKEN:
86838690
case FLOAT_ID_TOKEN:
8684-
if (is_local && (Token.Table_Index != Table_Index))
8691+
if (is_local && (Token.context != Table_Index))
86858692
{
8686-
if (Token.is_array_elem)
8687-
Error("Cannot use '#local' to assign a non-local array element.");
8693+
if (Token.is_array_elem || Token.is_dictionary_elem)
8694+
Error("Cannot use '#local' to assign a non-local array or dictionary element.");
86888695
allow_redefine = true; // should actually be irrelevant downstream, thanks to Previous==IDENTIFIER_TOKEN
86898696
Temp_Entry = Add_Symbol (Local_Index,Token.Token_String,IDENTIFIER_TOKEN);
86908697
numberPtr = &(Temp_Entry->Token_Number);
@@ -8693,7 +8700,7 @@ void Parser::Parse_Declare(bool is_local, bool after_hash)
86938700
}
86948701
else
86958702
{
8696-
allow_redefine = !Token.is_array_elem;
8703+
allow_redefine = !Token.is_array_elem || Token.is_mixed_array_elem;
86978704
numberPtr = Token.NumberPtr;
86988705
dataPtr = Token.DataPtr;
86998706
Previous = Token.Function_Id;
@@ -8714,7 +8721,7 @@ void Parser::Parse_Declare(bool is_local, bool after_hash)
87148721
// the resulting value.
87158722
// We do this by assigning the resulting value to a dummy symbol entry.
87168723
allow_redefine = true; // should actually be irrelevant downstream, thanks to Previous=IDENTIFIER_TOKEN
8717-
Temp_Entry = Create_Entry (0, "", DUMMY_SYMBOL_TOKEN);
8724+
Temp_Entry = Create_Entry ("", DUMMY_SYMBOL_TOKEN, false);
87188725
numberPtr = &(Temp_Entry->Token_Number);
87198726
dataPtr = &(Temp_Entry->Data);
87208727
optional = true;
@@ -8801,14 +8808,14 @@ void Parser::Parse_Declare(bool is_local, bool after_hash)
88018808
}
88028809
else if (larrayDeclare)
88038810
{
8804-
SYM_ENTRY *rvalue = Create_Entry (0, "", DUMMY_SYMBOL_TOKEN);
8811+
SYM_ENTRY *rvalue = Create_Entry ("", DUMMY_SYMBOL_TOKEN, false);
88058812
if (!Parse_RValue (IDENTIFIER_TOKEN, &(rvalue->Token_Number), &(rvalue->Data), NULL, false, false, true, true, false, MAX_NUMBER_OF_TABLES) ||
88068813
(rvalue->Token_Number != ARRAY_ID_TOKEN))
88078814
Expectation_Error("array RValue");
88088815
POV_ARRAY *a = reinterpret_cast<POV_ARRAY *>(rvalue->Data);
8809-
if (lvalues.size() > a->Total)
8816+
if (lvalues.size() > a->DataPtrs.size())
88108817
Error ("array size mismatch");
8811-
if (a->DataPtrs == NULL)
8818+
if (a->DataPtrs.empty())
88128819
Error ("cannot assign from uninitialized array");
88138820

88148821
for (int i = 0; i < lvalues.size(); ++i)
@@ -8827,7 +8834,7 @@ void Parser::Parse_Declare(bool is_local, bool after_hash)
88278834
*dataPtr = Copy_Identifier(a->DataPtrs[i], a->Type);
88288835
}
88298836

8830-
Destroy_Entry (0, rvalue);
8837+
Destroy_Entry (rvalue, false);
88318838
}
88328839
else
88338840
{
@@ -8892,7 +8899,7 @@ void Parser::Parse_Declare(bool is_local, bool after_hash)
88928899
for (vector<LValue>::iterator i = lvalues.begin(); i != lvalues.end(); ++i)
88938900
{
88948901
if ((i->symEntry != NULL) && (i->symEntry->Token_Number == DUMMY_SYMBOL_TOKEN))
8895-
Destroy_Entry (0, i->symEntry);
8902+
Destroy_Entry (i->symEntry, false);
88968903
}
88978904

88988905
if ( after_hash )
@@ -8903,6 +8910,18 @@ void Parser::Parse_Declare(bool is_local, bool after_hash)
89038910
}
89048911
}
89058912

8913+
bool Parser::PassParameterByReference (int callingContext)
8914+
{
8915+
if (Token.is_dictionary_elem)
8916+
{
8917+
return true;
8918+
}
8919+
else
8920+
{
8921+
return (Token.context <= callingContext);
8922+
}
8923+
}
8924+
89068925
bool Parser::Parse_RValue (int Previous, int *NumberPtr, void **DataPtr, SYM_ENTRY *sym, bool ParFlag, bool SemiFlag, bool is_local, bool allow_redefine, bool allowUndefined, int old_table_index)
89078926
{
89088927
EXPRESS Local_Express;
@@ -8928,21 +8947,21 @@ bool Parser::Parse_RValue (int Previous, int *NumberPtr, void **DataPtr, SYM_ENT
89288947
bool callable_identifier;
89298948
bool had_callable_identifier;
89308949
SYM_ENTRY* symbol_entry;
8950+
SYM_TABLE* symbol_entry_table;
89318951

89328952
EXPECT_ONE
89338953
CASE4 (NORMAL_ID_TOKEN, FINISH_ID_TOKEN, TEXTURE_ID_TOKEN, OBJECT_ID_TOKEN)
89348954
CASE4 (COLOUR_MAP_ID_TOKEN, TRANSFORM_ID_TOKEN, CAMERA_ID_TOKEN, PIGMENT_ID_TOKEN)
89358955
CASE4 (SLOPE_MAP_ID_TOKEN,NORMAL_MAP_ID_TOKEN,TEXTURE_MAP_ID_TOKEN,ARRAY_ID_TOKEN)
89368956
CASE4 (PIGMENT_MAP_ID_TOKEN, MEDIA_ID_TOKEN,INTERIOR_ID_TOKEN,DENSITY_ID_TOKEN)
89378957
CASE4 (DENSITY_MAP_ID_TOKEN, RAINBOW_ID_TOKEN, FOG_ID_TOKEN, SKYSPHERE_ID_TOKEN)
8938-
CASE2 (MATERIAL_ID_TOKEN, STRING_ID_TOKEN)
8939-
if ((ParFlag) && (Token.Table_Index <= old_table_index))
8958+
CASE3 (MATERIAL_ID_TOKEN, STRING_ID_TOKEN, DICTIONARY_ID_TOKEN)
8959+
if ((ParFlag) && PassParameterByReference (old_table_index))
89408960
{
89418961
// pass by reference
89428962
New_Par = reinterpret_cast<POV_PARAM *>(POV_MALLOC(sizeof(POV_PARAM),"parameter"));
89438963
New_Par->NumberPtr = Token.NumberPtr;
89448964
New_Par->DataPtr = Token.DataPtr;
8945-
New_Par->Table_Index = Token.Table_Index;
89468965
*NumberPtr = PARAMETER_ID_TOKEN;
89478966
*DataPtr = reinterpret_cast<void *>(New_Par);
89488967
}
@@ -9024,9 +9043,12 @@ bool Parser::Parse_RValue (int Previous, int *NumberPtr, void **DataPtr, SYM_ENT
90249043
if ((Token.Token_Id==FUNCT_ID_TOKEN) || (Token.Token_Id==VECTFUNCT_ID_TOKEN) || (Token.Token_Id==SPLINE_ID_TOKEN) ||
90259044
(Token.Token_Id==UV_ID_TOKEN) || (Token.Token_Id==VECTOR_4D_ID_TOKEN) || (Token.Token_Id==COLOUR_ID_TOKEN))
90269045
{
9027-
symbol_entry = Find_Symbol(Token.Table_Index, Token.Token_String);
9046+
symbol_entry = Find_Symbol (Token.table, Token.Token_String);
90289047
if (symbol_entry)
9048+
{
9049+
symbol_entry_table = Token.table;
90299050
Acquire_Entry_Reference(symbol_entry);
9051+
}
90309052
}
90319053
else
90329054
{
@@ -9048,7 +9070,7 @@ bool Parser::Parse_RValue (int Previous, int *NumberPtr, void **DataPtr, SYM_ENT
90489070
Error("Identifier expected, incomplete function call or spline call found instead.");
90499071

90509072
// only one identifier token has been found so pass it by reference
9051-
if (((Temp_Count==-1) || (Temp_Count==TOKEN_OVERFLOW_RESET_COUNT)) && (Token.Table_Index <= old_table_index))
9073+
if (((Temp_Count==-1) || (Temp_Count==TOKEN_OVERFLOW_RESET_COUNT)) && PassParameterByReference (old_table_index))
90529074
{
90539075
// It is important that functions are passed by value and not by reference! [trf]
90549076
if(!(ParFlag) || (ParFlag && function_identifier))
@@ -9065,7 +9087,6 @@ bool Parser::Parse_RValue (int Previous, int *NumberPtr, void **DataPtr, SYM_ENT
90659087
New_Par = reinterpret_cast<POV_PARAM *>(POV_MALLOC(sizeof(POV_PARAM),"parameter"));
90669088
New_Par->NumberPtr = Token.NumberPtr;
90679089
New_Par->DataPtr = Token.DataPtr;
9068-
New_Par->Table_Index = Token.Table_Index;
90699090

90709091
*NumberPtr = PARAMETER_ID_TOKEN;
90719092
*DataPtr = reinterpret_cast<void *>(New_Par);
@@ -9110,7 +9131,7 @@ bool Parser::Parse_RValue (int Previous, int *NumberPtr, void **DataPtr, SYM_ENT
91109131
}
91119132
}
91129133
if (symbol_entry)
9113-
Release_Entry_Reference(Token.Table_Index, symbol_entry);
9134+
Release_Entry_Reference (symbol_entry_table, symbol_entry);
91149135

91159136
// allow #declares again
91169137
Ok_To_Declare = true;
@@ -9329,6 +9350,13 @@ bool Parser::Parse_RValue (int Previous, int *NumberPtr, void **DataPtr, SYM_ENT
93299350
*DataPtr = Temp_Data;
93309351
END_CASE
93319352

9353+
CASE (DICTIONARY_TOKEN)
9354+
Temp_Data = reinterpret_cast<void *>(Parse_Dictionary_Declare());
9355+
*NumberPtr = DICTIONARY_ID_TOKEN;
9356+
Test_Redefine (Previous,NumberPtr,*DataPtr, allow_redefine);
9357+
*DataPtr = Temp_Data;
9358+
END_CASE
9359+
93329360
OTHERWISE
93339361
UNGET
93349362
Local_Object = Parse_Object ();
@@ -9438,15 +9466,20 @@ void Parser::Destroy_Ident_Data(void *Data, int Type)
94389466
break;
94399467
case ARRAY_ID_TOKEN:
94409468
a = reinterpret_cast<POV_ARRAY *>(Data);
9441-
if(a->DataPtrs != NULL)
9469+
if(!a->DataPtrs.empty())
94429470
{
9443-
for(i=0; i<a->Total; i++)
9471+
for(i=0; i<a->DataPtrs.size(); i++)
94449472
{
9445-
Destroy_Ident_Data(a->DataPtrs[i], a->Type);
9473+
if (a->Types.empty())
9474+
Destroy_Ident_Data (a->DataPtrs[i], a->Type);
9475+
else
9476+
Destroy_Ident_Data (a->DataPtrs[i], a->Types[i]);
94469477
}
9447-
POV_FREE(a->DataPtrs);
94489478
}
9449-
POV_FREE(a);
9479+
delete a;
9480+
break;
9481+
case DICTIONARY_ID_TOKEN:
9482+
Destroy_Sym_Table (reinterpret_cast<SYM_TABLE *>(Data));
94509483
break;
94519484
case PARAMETER_ID_TOKEN:
94529485
POV_FREE(Data);
@@ -10519,16 +10552,30 @@ void *Parser::Copy_Identifier (void *Data, int Type)
1051910552
POV_MEMMOVE(reinterpret_cast<void *>(New), reinterpret_cast<void *>(Data), len * sizeof(UCS2));
1052010553
break;
1052110554
case ARRAY_ID_TOKEN:
10522-
a=reinterpret_cast<POV_ARRAY *>(Data);
10523-
na=reinterpret_cast<POV_ARRAY *>(POV_MALLOC(sizeof(POV_ARRAY),"array"));
10524-
*na=*a;
10525-
na->DataPtrs = reinterpret_cast<void **>(POV_MALLOC(sizeof(void *)*(a->Total),"array"));
10526-
for (i=0; i<a->Total; i++)
10555+
a = reinterpret_cast<POV_ARRAY *>(Data);
10556+
na = new POV_ARRAY;
10557+
na->Dims = a->Dims;
10558+
na->Type = a->Type;
10559+
na->resizable = a->resizable;
10560+
for (i = 0; i < 5; ++i)
10561+
{
10562+
na->Sizes[i] = a->Sizes[i];
10563+
na->Mags[i] = a->Mags[i];
10564+
}
10565+
na->DataPtrs.resize(a->DataPtrs.size());
10566+
na->Types = a->Types;
10567+
for (i=0; i<a->DataPtrs.size(); i++)
1052710568
{
10528-
na->DataPtrs[i] = reinterpret_cast<void *>(Copy_Identifier (a->DataPtrs[i],a->Type));
10569+
if (a->Types.empty())
10570+
na->DataPtrs[i] = reinterpret_cast<void *>(Copy_Identifier (a->DataPtrs[i],a->Type));
10571+
else
10572+
na->DataPtrs[i] = reinterpret_cast<void *>(Copy_Identifier (a->DataPtrs[i], a->Types[i]));
1052910573
}
1053010574
New = reinterpret_cast<void *>(na);
1053110575
break;
10576+
case DICTIONARY_ID_TOKEN:
10577+
New = reinterpret_cast<void *>(Copy_Sym_Table (reinterpret_cast<SYM_TABLE *>(Data)));
10578+
break;
1053210579
case FUNCT_ID_TOKEN:
1053310580
case VECTFUNCT_ID_TOKEN:
1053410581
New = reinterpret_cast<void *>(fnVMContext->functionvm->CopyFunction((FUNCTION_PTR )Data));

0 commit comments

Comments
 (0)