Skip to content

Commit 5039065

Browse files
committed
Add support for dictionary data container.
1 parent ba30980 commit 5039065

File tree

8 files changed

+342
-131
lines changed

8 files changed

+342
-131
lines changed

changes.txt

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

52+
- A new data container, `dictionary`, has been added to support structured
53+
storage of data.
54+
5255
- A new pattern, `potential`, has been added to define a pattern based on the
5356
potential field of a blob or isosurface object.
5457

source/base/version.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
#define OFFICIAL_VERSION_STRING "3.7.1"
4646
#define OFFICIAL_VERSION_NUMBER 371
4747

48-
#define POV_RAY_PRERELEASE "alpha.8790387"
48+
#define POV_RAY_PRERELEASE "x.dictionary.8790760"
4949

5050
#if (POV_RAY_IS_AUTOBUILD == 1) && ((POV_RAY_IS_OFFICIAL == 1) || (POV_RAY_IS_SEMI_OFFICIAL == 1))
5151
#ifdef POV_RAY_PRERELEASE

source/parser/parser.cpp

Lines changed: 50 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8662,7 +8662,14 @@ void Parser::Parse_Declare(bool is_local, bool after_hash)
86628662
CASE (IDENTIFIER_TOKEN)
86638663
POV_PARSER_ASSERT(!Token.is_array_elem);
86648664
allow_redefine = true; // should actually be irrelevant downstream, thanks to Previous==IDENTIFIER_TOKEN
8665-
Temp_Entry = Add_Symbol (Local_Index,Token.Token_String,IDENTIFIER_TOKEN);
8665+
if (Token.is_dictionary_elem)
8666+
{
8667+
if (is_local && (Token.context != Table_Index))
8668+
Error ("Cannot use '#local' to assign a non-local array or dictionary element.");
8669+
Temp_Entry = Add_Symbol (Token.table, Token.Token_String, IDENTIFIER_TOKEN);
8670+
}
8671+
else
8672+
Temp_Entry = Add_Symbol (Local_Index, Token.Token_String, IDENTIFIER_TOKEN);
86668673
numberPtr = &(Temp_Entry->Token_Number);
86678674
dataPtr = &(Temp_Entry->Data);
86688675
Previous = Token.Token_Id;
@@ -8700,11 +8707,11 @@ void Parser::Parse_Declare(bool is_local, bool after_hash)
87008707
CASE4 (PIGMENT_MAP_ID_TOKEN, MEDIA_ID_TOKEN, STRING_ID_TOKEN, INTERIOR_ID_TOKEN)
87018708
CASE4 (DENSITY_MAP_ID_TOKEN, ARRAY_ID_TOKEN, DENSITY_ID_TOKEN, UV_ID_TOKEN)
87028709
CASE4 (VECTOR_4D_ID_TOKEN, RAINBOW_ID_TOKEN, FOG_ID_TOKEN, SKYSPHERE_ID_TOKEN)
8703-
CASE2 (MATERIAL_ID_TOKEN, SPLINE_ID_TOKEN )
8704-
if (is_local && (Token.Table_Index != Table_Index))
8710+
CASE3 (MATERIAL_ID_TOKEN, SPLINE_ID_TOKEN, DICTIONARY_ID_TOKEN)
8711+
if (is_local && (Token.context != Table_Index))
87058712
{
8706-
if (Token.is_array_elem)
8707-
Error("Cannot use '#local' to assign a non-local array element.");
8713+
if (Token.is_array_elem || Token.is_dictionary_elem)
8714+
Error ("Cannot use '#local' to assign a non-local array or dictionary element.");
87088715
allow_redefine = true; // should actually be irrelevant downstream, thanks to Previous==IDENTIFIER_TOKEN
87098716
Temp_Entry = Add_Symbol (Local_Index,Token.Token_String,IDENTIFIER_TOKEN);
87108717
numberPtr = &(Temp_Entry->Token_Number);
@@ -8733,10 +8740,10 @@ void Parser::Parse_Declare(bool is_local, bool after_hash)
87338740
{
87348741
case VECTOR_ID_TOKEN:
87358742
case FLOAT_ID_TOKEN:
8736-
if (is_local && (Token.Table_Index != Table_Index))
8743+
if (is_local && (Token.context != Table_Index))
87378744
{
8738-
if (Token.is_array_elem)
8739-
Error("Cannot use '#local' to assign a non-local array element.");
8745+
if (Token.is_array_elem || Token.is_dictionary_elem)
8746+
Error("Cannot use '#local' to assign a non-local array or dictionary element.");
87408747
allow_redefine = true; // should actually be irrelevant downstream, thanks to Previous==IDENTIFIER_TOKEN
87418748
Temp_Entry = Add_Symbol (Local_Index,Token.Token_String,IDENTIFIER_TOKEN);
87428749
numberPtr = &(Temp_Entry->Token_Number);
@@ -8766,7 +8773,7 @@ void Parser::Parse_Declare(bool is_local, bool after_hash)
87668773
// the resulting value.
87678774
// We do this by assigning the resulting value to a dummy symbol entry.
87688775
allow_redefine = true; // should actually be irrelevant downstream, thanks to Previous=IDENTIFIER_TOKEN
8769-
Temp_Entry = Create_Entry (0, "", DUMMY_SYMBOL_TOKEN);
8776+
Temp_Entry = Create_Entry ("", DUMMY_SYMBOL_TOKEN, false);
87708777
numberPtr = &(Temp_Entry->Token_Number);
87718778
dataPtr = &(Temp_Entry->Data);
87728779
optional = true;
@@ -8853,7 +8860,7 @@ void Parser::Parse_Declare(bool is_local, bool after_hash)
88538860
}
88548861
else if (larrayDeclare)
88558862
{
8856-
SYM_ENTRY *rvalue = Create_Entry (0, "", DUMMY_SYMBOL_TOKEN);
8863+
SYM_ENTRY *rvalue = Create_Entry ("", DUMMY_SYMBOL_TOKEN, false);
88578864
if (!Parse_RValue (IDENTIFIER_TOKEN, &(rvalue->Token_Number), &(rvalue->Data), NULL, false, false, true, true, false, MAX_NUMBER_OF_TABLES) ||
88588865
(rvalue->Token_Number != ARRAY_ID_TOKEN))
88598866
Expectation_Error("array RValue");
@@ -8879,7 +8886,7 @@ void Parser::Parse_Declare(bool is_local, bool after_hash)
88798886
*dataPtr = Copy_Identifier(a->DataPtrs[i], a->Type);
88808887
}
88818888

8882-
Destroy_Entry (0, rvalue);
8889+
Destroy_Entry (rvalue, false);
88838890
}
88848891
else
88858892
{
@@ -8944,7 +8951,7 @@ void Parser::Parse_Declare(bool is_local, bool after_hash)
89448951
for (vector<LValue>::iterator i = lvalues.begin(); i != lvalues.end(); ++i)
89458952
{
89468953
if ((i->symEntry != NULL) && (i->symEntry->Token_Number == DUMMY_SYMBOL_TOKEN))
8947-
Destroy_Entry (0, i->symEntry);
8954+
Destroy_Entry (i->symEntry, false);
89488955
}
89498956

89508957
if ( after_hash )
@@ -8955,6 +8962,18 @@ void Parser::Parse_Declare(bool is_local, bool after_hash)
89558962
}
89568963
}
89578964

8965+
bool Parser::PassParameterByReference (int callingContext)
8966+
{
8967+
if (Token.is_dictionary_elem)
8968+
{
8969+
return true;
8970+
}
8971+
else
8972+
{
8973+
return (Token.context <= callingContext);
8974+
}
8975+
}
8976+
89588977
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)
89598978
{
89608979
EXPRESS Local_Express;
@@ -8987,14 +9006,13 @@ bool Parser::Parse_RValue (int Previous, int *NumberPtr, void **DataPtr, SYM_ENT
89879006
CASE4 (SLOPE_MAP_ID_TOKEN,NORMAL_MAP_ID_TOKEN,TEXTURE_MAP_ID_TOKEN,ARRAY_ID_TOKEN)
89889007
CASE4 (PIGMENT_MAP_ID_TOKEN, MEDIA_ID_TOKEN,INTERIOR_ID_TOKEN,DENSITY_ID_TOKEN)
89899008
CASE4 (DENSITY_MAP_ID_TOKEN, RAINBOW_ID_TOKEN, FOG_ID_TOKEN, SKYSPHERE_ID_TOKEN)
8990-
CASE2 (MATERIAL_ID_TOKEN, STRING_ID_TOKEN)
8991-
if ((ParFlag) && (Token.Table_Index <= old_table_index))
9009+
CASE3 (MATERIAL_ID_TOKEN, STRING_ID_TOKEN, DICTIONARY_ID_TOKEN)
9010+
if ((ParFlag) && PassParameterByReference (old_table_index))
89929011
{
89939012
// pass by reference
89949013
New_Par = reinterpret_cast<POV_PARAM *>(POV_MALLOC(sizeof(POV_PARAM),"parameter"));
89959014
New_Par->NumberPtr = Token.NumberPtr;
89969015
New_Par->DataPtr = Token.DataPtr;
8997-
New_Par->Table_Index = Token.Table_Index;
89989016
*NumberPtr = PARAMETER_ID_TOKEN;
89999017
*DataPtr = reinterpret_cast<void *>(New_Par);
90009018
}
@@ -9078,7 +9096,7 @@ bool Parser::Parse_RValue (int Previous, int *NumberPtr, void **DataPtr, SYM_ENT
90789096
if ((Token.Token_Id==FUNCT_ID_TOKEN) || (Token.Token_Id==VECTFUNCT_ID_TOKEN) || (Token.Token_Id==SPLINE_ID_TOKEN) ||
90799097
(Token.Token_Id==UV_ID_TOKEN) || (Token.Token_Id==VECTOR_4D_ID_TOKEN) || (Token.Token_Id==COLOUR_ID_TOKEN))
90809098
{
9081-
symbol_entry = Find_Symbol(Token.Table_Index, Token.Token_String);
9099+
symbol_entry = Find_Symbol (Token.table, Token.Token_String);
90829100
if (symbol_entry)
90839101
Acquire_Entry_Reference(symbol_entry);
90849102
}
@@ -9102,7 +9120,7 @@ bool Parser::Parse_RValue (int Previous, int *NumberPtr, void **DataPtr, SYM_ENT
91029120
Error("Identifier expected, incomplete function call or spline call found instead.");
91039121

91049122
// only one identifier token has been found so pass it by reference
9105-
if (((Temp_Count==-1) || (Temp_Count==TOKEN_OVERFLOW_RESET_COUNT)) && (Token.Table_Index <= old_table_index))
9123+
if (((Temp_Count==-1) || (Temp_Count==TOKEN_OVERFLOW_RESET_COUNT)) && PassParameterByReference (old_table_index))
91069124
{
91079125
// It is important that functions are passed by value and not by reference! [trf]
91089126
if(!(ParFlag) || (ParFlag && function_identifier))
@@ -9119,7 +9137,6 @@ bool Parser::Parse_RValue (int Previous, int *NumberPtr, void **DataPtr, SYM_ENT
91199137
New_Par = reinterpret_cast<POV_PARAM *>(POV_MALLOC(sizeof(POV_PARAM),"parameter"));
91209138
New_Par->NumberPtr = Token.NumberPtr;
91219139
New_Par->DataPtr = Token.DataPtr;
9122-
New_Par->Table_Index = Token.Table_Index;
91239140

91249141
*NumberPtr = PARAMETER_ID_TOKEN;
91259142
*DataPtr = reinterpret_cast<void *>(New_Par);
@@ -9164,7 +9181,7 @@ bool Parser::Parse_RValue (int Previous, int *NumberPtr, void **DataPtr, SYM_ENT
91649181
}
91659182
}
91669183
if (symbol_entry)
9167-
Release_Entry_Reference(Token.Table_Index, symbol_entry);
9184+
Release_Entry_Reference (Token.table, symbol_entry);
91689185

91699186
// allow #declares again
91709187
Ok_To_Declare = true;
@@ -9407,6 +9424,14 @@ bool Parser::Parse_RValue (int Previous, int *NumberPtr, void **DataPtr, SYM_ENT
94079424
EXIT
94089425
END_CASE
94099426

9427+
CASE (DICTIONARY_TOKEN)
9428+
Temp_Data = reinterpret_cast<void *>(Create_Sym_Table (true));
9429+
*NumberPtr = DICTIONARY_ID_TOKEN;
9430+
Test_Redefine (Previous,NumberPtr,*DataPtr, allow_redefine);
9431+
*DataPtr = Temp_Data;
9432+
EXIT
9433+
END_CASE
9434+
94109435
OTHERWISE
94119436
UNGET
94129437
Local_Object = Parse_Object ();
@@ -9527,6 +9552,9 @@ void Parser::Destroy_Ident_Data(void *Data, int Type)
95279552
}
95289553
POV_FREE(a);
95299554
break;
9555+
case DICTIONARY_ID_TOKEN:
9556+
Destroy_Sym_Table (reinterpret_cast<SYM_TABLE *>(Data));
9557+
break;
95309558
case PARAMETER_ID_TOKEN:
95319559
POV_FREE(Data);
95329560
break;
@@ -10602,6 +10630,9 @@ void *Parser::Copy_Identifier (void *Data, int Type)
1060210630
}
1060310631
New = reinterpret_cast<void *>(na);
1060410632
break;
10633+
case DICTIONARY_ID_TOKEN:
10634+
New = reinterpret_cast<void *>(Copy_Sym_Table (reinterpret_cast<SYM_TABLE *>(Data)));
10635+
break;
1060510636
case FUNCT_ID_TOKEN:
1060610637
case VECTFUNCT_ID_TOKEN:
1060710638
New = reinterpret_cast<void *>(fnVMContext->functionvm->CopyFunction((FUNCTION_PTR )Data));

source/parser/parser.h

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,10 @@ struct BetaFlags
196196

197197
class Parser : public SceneTask
198198
{
199+
private:
200+
201+
struct SYM_TABLE;
202+
199203
public:
200204

201205
class DebugTextStreamBuffer : public TextStreamBuffer
@@ -221,15 +225,17 @@ class Parser : public SceneTask
221225
TOKEN Function_Id; ///< token type ID, in case Token_Id is an identifier ID
222226
pov_base::ITextStream::FilePos Token_File_Pos; ///< location of this token in the scene or include file (line number & file position)
223227
int Token_Col_No; ///< location of this token in the scene or include file (column)
224-
int Table_Index;
228+
int context; ///< context the token is local to (i.e., table index)
225229
char *Token_String; ///< reference to token value (if it is a string literal) or character sequence comprising the token
226230
DBL Token_Float; ///< token value (if it is a float literal)
227231
int Unget_Token, End_Of_File;
228232
pov_base::ITextStream *FileHandle; ///< location of this token in the scene or include file (file)
229233
void *Data; ///< reference to token value (if it is a non-float identifier)
230234
int *NumberPtr;
231235
void **DataPtr;
232-
bool is_array_elem; ///< true if token is actually an array element reference
236+
SYM_TABLE *table; ///< table or dictionary the token references an element of
237+
bool is_array_elem : 1; ///< true if token is actually an array element reference
238+
bool is_dictionary_elem : 1; ///< true if token is actually a dictionary element reference
233239
};
234240

235241
struct LValue
@@ -276,7 +282,6 @@ class Parser : public SceneTask
276282
{
277283
int *NumberPtr;
278284
void **DataPtr;
279-
int Table_Index;
280285
};
281286

282287
struct DATA_FILE
@@ -327,6 +332,7 @@ class Parser : public SceneTask
327332
void Parse_Declare (bool is_local, bool after_hash);
328333
void Parse_Matrix (MATRIX Matrix);
329334
void Destroy_Ident_Data (void *Data, int Type);
335+
bool PassParameterByReference (int oldTableIndex);
330336
bool 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);
331337
const char *Get_Token_String (TOKEN Token_Id);
332338
void Test_Redefine(TOKEN Previous, TOKEN *NumberPtr, void *Data, bool allow_redefine = true);
@@ -368,12 +374,14 @@ class Parser : public SceneTask
368374
void pre_init_tokenizer (void);
369375
void Initialize_Tokenizer (void);
370376
void Terminate_Tokenizer (void);
377+
SYM_ENTRY *Add_Symbol (SYM_TABLE *table, const char *Name,TOKEN Number);
371378
SYM_ENTRY *Add_Symbol (int Index,const char *Name,TOKEN Number);
372379
POV_ARRAY *Parse_Array_Declare (void);
373-
SYM_ENTRY *Create_Entry (int Index,const char *Name,TOKEN Number);
380+
SYM_ENTRY *Create_Entry (const char *Name, TOKEN Number, bool copyName);
381+
SYM_ENTRY *Copy_Entry (const SYM_ENTRY *);
374382
void Acquire_Entry_Reference (SYM_ENTRY *Entry);
375-
void Release_Entry_Reference (int Index, SYM_ENTRY *Entry);
376-
SYM_ENTRY *Destroy_Entry (int Index,SYM_ENTRY *Entry);
383+
void Release_Entry_Reference (SYM_TABLE *table, SYM_ENTRY *Entry);
384+
SYM_ENTRY *Destroy_Entry (SYM_ENTRY *Entry, bool destroyName);
377385
bool Parse_Ifdef_Param ();
378386
int Parse_For_Param (char**, DBL*, DBL*);
379387

@@ -521,6 +529,7 @@ class Parser : public SceneTask
521529
struct SYM_TABLE
522530
{
523531
SYM_ENTRY *Table[SYM_TABLE_SIZE];
532+
bool namesAreCopies;
524533
};
525534

526535
SYM_TABLE *Tables[MAX_NUMBER_OF_TABLES];
@@ -574,7 +583,7 @@ class Parser : public SceneTask
574583

575584
CS_ENTRY *Cond_Stack;
576585
int CS_Index;
577-
bool Skipping, Inside_Ifdef, Inside_MacroDef, Parsing_Directive;
586+
bool Skipping, Inside_Ifdef, Inside_MacroDef, Parsing_Directive, parseRawIdentifiers;
578587
IdentifierMode Inside_IdentFn;
579588

580589
int Got_EOF; // WARNING: Changes to the use of this variable are very dangerous as it is used in many places assuming certain non-obvious side effects! [trf]
@@ -677,20 +686,27 @@ class Parser : public SceneTask
677686
inline void End_String_Fast (void);
678687
bool Read_Float (void);
679688
void Read_Symbol (void);
680-
SYM_ENTRY *Find_Symbol (int Index, const char *s);
689+
SYM_ENTRY *Find_Symbol (const SYM_TABLE *table, const char *s, int hash);
690+
SYM_ENTRY *Find_Symbol (const SYM_TABLE *table, const char *s);
691+
SYM_ENTRY *Find_Symbol (int index, const char *s);
681692
SYM_ENTRY *Find_Symbol (const char *s);
682693
void Skip_Tokens (COND_TYPE cond);
683694
void Break (void);
684695

685696
int get_hash_value (const char *s);
686-
inline void Write_Token (TOKEN Token_Id, int col);
697+
inline void Write_Token (TOKEN Token_Id, int col, SYM_TABLE *table = NULL);
687698
void Destroy_Table (int index);
688699
void init_sym_tables (void);
689700
void Add_Sym_Table ();
701+
SYM_TABLE *Create_Sym_Table (bool copyNames);
702+
void Destroy_Sym_Table (SYM_TABLE *);
703+
SYM_TABLE *Copy_Sym_Table (const SYM_TABLE *);
704+
void Remove_Symbol (SYM_TABLE *table, const char *Name, bool is_array_elem, void **DataPtr, int ttype);
690705
void Remove_Symbol (int Index, const char *Name, bool is_array_elem, void **DataPtr, int ttype);
691706
Macro *Parse_Macro(void);
692707
void Invoke_Macro(void);
693708
void Return_From_Macro(void);
709+
void Add_Entry (SYM_TABLE *table, SYM_ENTRY *Table_Entry);
694710
void Add_Entry (int Index,SYM_ENTRY *Table_Entry);
695711
void Parse_Initalizer (int Sub, int Base, POV_ARRAY *a);
696712

0 commit comments

Comments
 (0)