Skip to content

Commit

Permalink
Add support for dictionary data container.
Browse files Browse the repository at this point in the history
  • Loading branch information
c-lipka committed Sep 17, 2016
1 parent ba30980 commit 5039065
Show file tree
Hide file tree
Showing 8 changed files with 342 additions and 131 deletions.
3 changes: 3 additions & 0 deletions changes.txt
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ Prior to the release of 3.7.1, the following items still need urgent attention:
New Features
------------

- A new data container, `dictionary`, has been added to support structured
storage of data.

- A new pattern, `potential`, has been added to define a pattern based on the
potential field of a blob or isosurface object.

Expand Down
2 changes: 1 addition & 1 deletion source/base/version.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
#define OFFICIAL_VERSION_STRING "3.7.1"
#define OFFICIAL_VERSION_NUMBER 371

#define POV_RAY_PRERELEASE "alpha.8790387"
#define POV_RAY_PRERELEASE "x.dictionary.8790760"

#if (POV_RAY_IS_AUTOBUILD == 1) && ((POV_RAY_IS_OFFICIAL == 1) || (POV_RAY_IS_SEMI_OFFICIAL == 1))
#ifdef POV_RAY_PRERELEASE
Expand Down
69 changes: 50 additions & 19 deletions source/parser/parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8662,7 +8662,14 @@ void Parser::Parse_Declare(bool is_local, bool after_hash)
CASE (IDENTIFIER_TOKEN)
POV_PARSER_ASSERT(!Token.is_array_elem);
allow_redefine = true; // should actually be irrelevant downstream, thanks to Previous==IDENTIFIER_TOKEN
Temp_Entry = Add_Symbol (Local_Index,Token.Token_String,IDENTIFIER_TOKEN);
if (Token.is_dictionary_elem)
{
if (is_local && (Token.context != Table_Index))
Error ("Cannot use '#local' to assign a non-local array or dictionary element.");
Temp_Entry = Add_Symbol (Token.table, Token.Token_String, IDENTIFIER_TOKEN);
}
else
Temp_Entry = Add_Symbol (Local_Index, Token.Token_String, IDENTIFIER_TOKEN);
numberPtr = &(Temp_Entry->Token_Number);
dataPtr = &(Temp_Entry->Data);
Previous = Token.Token_Id;
Expand Down Expand Up @@ -8700,11 +8707,11 @@ void Parser::Parse_Declare(bool is_local, bool after_hash)
CASE4 (PIGMENT_MAP_ID_TOKEN, MEDIA_ID_TOKEN, STRING_ID_TOKEN, INTERIOR_ID_TOKEN)
CASE4 (DENSITY_MAP_ID_TOKEN, ARRAY_ID_TOKEN, DENSITY_ID_TOKEN, UV_ID_TOKEN)
CASE4 (VECTOR_4D_ID_TOKEN, RAINBOW_ID_TOKEN, FOG_ID_TOKEN, SKYSPHERE_ID_TOKEN)
CASE2 (MATERIAL_ID_TOKEN, SPLINE_ID_TOKEN )
if (is_local && (Token.Table_Index != Table_Index))
CASE3 (MATERIAL_ID_TOKEN, SPLINE_ID_TOKEN, DICTIONARY_ID_TOKEN)
if (is_local && (Token.context != Table_Index))
{
if (Token.is_array_elem)
Error("Cannot use '#local' to assign a non-local array element.");
if (Token.is_array_elem || Token.is_dictionary_elem)
Error ("Cannot use '#local' to assign a non-local array or dictionary element.");
allow_redefine = true; // should actually be irrelevant downstream, thanks to Previous==IDENTIFIER_TOKEN
Temp_Entry = Add_Symbol (Local_Index,Token.Token_String,IDENTIFIER_TOKEN);
numberPtr = &(Temp_Entry->Token_Number);
Expand Down Expand Up @@ -8733,10 +8740,10 @@ void Parser::Parse_Declare(bool is_local, bool after_hash)
{
case VECTOR_ID_TOKEN:
case FLOAT_ID_TOKEN:
if (is_local && (Token.Table_Index != Table_Index))
if (is_local && (Token.context != Table_Index))
{
if (Token.is_array_elem)
Error("Cannot use '#local' to assign a non-local array element.");
if (Token.is_array_elem || Token.is_dictionary_elem)
Error("Cannot use '#local' to assign a non-local array or dictionary element.");
allow_redefine = true; // should actually be irrelevant downstream, thanks to Previous==IDENTIFIER_TOKEN
Temp_Entry = Add_Symbol (Local_Index,Token.Token_String,IDENTIFIER_TOKEN);
numberPtr = &(Temp_Entry->Token_Number);
Expand Down Expand Up @@ -8766,7 +8773,7 @@ void Parser::Parse_Declare(bool is_local, bool after_hash)
// the resulting value.
// We do this by assigning the resulting value to a dummy symbol entry.
allow_redefine = true; // should actually be irrelevant downstream, thanks to Previous=IDENTIFIER_TOKEN
Temp_Entry = Create_Entry (0, "", DUMMY_SYMBOL_TOKEN);
Temp_Entry = Create_Entry ("", DUMMY_SYMBOL_TOKEN, false);
numberPtr = &(Temp_Entry->Token_Number);
dataPtr = &(Temp_Entry->Data);
optional = true;
Expand Down Expand Up @@ -8853,7 +8860,7 @@ void Parser::Parse_Declare(bool is_local, bool after_hash)
}
else if (larrayDeclare)
{
SYM_ENTRY *rvalue = Create_Entry (0, "", DUMMY_SYMBOL_TOKEN);
SYM_ENTRY *rvalue = Create_Entry ("", DUMMY_SYMBOL_TOKEN, false);
if (!Parse_RValue (IDENTIFIER_TOKEN, &(rvalue->Token_Number), &(rvalue->Data), NULL, false, false, true, true, false, MAX_NUMBER_OF_TABLES) ||
(rvalue->Token_Number != ARRAY_ID_TOKEN))
Expectation_Error("array RValue");
Expand All @@ -8879,7 +8886,7 @@ void Parser::Parse_Declare(bool is_local, bool after_hash)
*dataPtr = Copy_Identifier(a->DataPtrs[i], a->Type);
}

Destroy_Entry (0, rvalue);
Destroy_Entry (rvalue, false);
}
else
{
Expand Down Expand Up @@ -8944,7 +8951,7 @@ void Parser::Parse_Declare(bool is_local, bool after_hash)
for (vector<LValue>::iterator i = lvalues.begin(); i != lvalues.end(); ++i)
{
if ((i->symEntry != NULL) && (i->symEntry->Token_Number == DUMMY_SYMBOL_TOKEN))
Destroy_Entry (0, i->symEntry);
Destroy_Entry (i->symEntry, false);
}

if ( after_hash )
Expand All @@ -8955,6 +8962,18 @@ void Parser::Parse_Declare(bool is_local, bool after_hash)
}
}

bool Parser::PassParameterByReference (int callingContext)
{
if (Token.is_dictionary_elem)
{
return true;
}
else
{
return (Token.context <= callingContext);
}
}

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)
{
EXPRESS Local_Express;
Expand Down Expand Up @@ -8987,14 +9006,13 @@ bool Parser::Parse_RValue (int Previous, int *NumberPtr, void **DataPtr, SYM_ENT
CASE4 (SLOPE_MAP_ID_TOKEN,NORMAL_MAP_ID_TOKEN,TEXTURE_MAP_ID_TOKEN,ARRAY_ID_TOKEN)
CASE4 (PIGMENT_MAP_ID_TOKEN, MEDIA_ID_TOKEN,INTERIOR_ID_TOKEN,DENSITY_ID_TOKEN)
CASE4 (DENSITY_MAP_ID_TOKEN, RAINBOW_ID_TOKEN, FOG_ID_TOKEN, SKYSPHERE_ID_TOKEN)
CASE2 (MATERIAL_ID_TOKEN, STRING_ID_TOKEN)
if ((ParFlag) && (Token.Table_Index <= old_table_index))
CASE3 (MATERIAL_ID_TOKEN, STRING_ID_TOKEN, DICTIONARY_ID_TOKEN)
if ((ParFlag) && PassParameterByReference (old_table_index))
{
// pass by reference
New_Par = reinterpret_cast<POV_PARAM *>(POV_MALLOC(sizeof(POV_PARAM),"parameter"));
New_Par->NumberPtr = Token.NumberPtr;
New_Par->DataPtr = Token.DataPtr;
New_Par->Table_Index = Token.Table_Index;
*NumberPtr = PARAMETER_ID_TOKEN;
*DataPtr = reinterpret_cast<void *>(New_Par);
}
Expand Down Expand Up @@ -9078,7 +9096,7 @@ bool Parser::Parse_RValue (int Previous, int *NumberPtr, void **DataPtr, SYM_ENT
if ((Token.Token_Id==FUNCT_ID_TOKEN) || (Token.Token_Id==VECTFUNCT_ID_TOKEN) || (Token.Token_Id==SPLINE_ID_TOKEN) ||
(Token.Token_Id==UV_ID_TOKEN) || (Token.Token_Id==VECTOR_4D_ID_TOKEN) || (Token.Token_Id==COLOUR_ID_TOKEN))
{
symbol_entry = Find_Symbol(Token.Table_Index, Token.Token_String);
symbol_entry = Find_Symbol (Token.table, Token.Token_String);
if (symbol_entry)
Acquire_Entry_Reference(symbol_entry);
}
Expand All @@ -9102,7 +9120,7 @@ bool Parser::Parse_RValue (int Previous, int *NumberPtr, void **DataPtr, SYM_ENT
Error("Identifier expected, incomplete function call or spline call found instead.");

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

*NumberPtr = PARAMETER_ID_TOKEN;
*DataPtr = reinterpret_cast<void *>(New_Par);
Expand Down Expand Up @@ -9164,7 +9181,7 @@ bool Parser::Parse_RValue (int Previous, int *NumberPtr, void **DataPtr, SYM_ENT
}
}
if (symbol_entry)
Release_Entry_Reference(Token.Table_Index, symbol_entry);
Release_Entry_Reference (Token.table, symbol_entry);

// allow #declares again
Ok_To_Declare = true;
Expand Down Expand Up @@ -9407,6 +9424,14 @@ bool Parser::Parse_RValue (int Previous, int *NumberPtr, void **DataPtr, SYM_ENT
EXIT
END_CASE

CASE (DICTIONARY_TOKEN)
Temp_Data = reinterpret_cast<void *>(Create_Sym_Table (true));
*NumberPtr = DICTIONARY_ID_TOKEN;
Test_Redefine (Previous,NumberPtr,*DataPtr, allow_redefine);
*DataPtr = Temp_Data;
EXIT
END_CASE

OTHERWISE
UNGET
Local_Object = Parse_Object ();
Expand Down Expand Up @@ -9527,6 +9552,9 @@ void Parser::Destroy_Ident_Data(void *Data, int Type)
}
POV_FREE(a);
break;
case DICTIONARY_ID_TOKEN:
Destroy_Sym_Table (reinterpret_cast<SYM_TABLE *>(Data));
break;
case PARAMETER_ID_TOKEN:
POV_FREE(Data);
break;
Expand Down Expand Up @@ -10602,6 +10630,9 @@ void *Parser::Copy_Identifier (void *Data, int Type)
}
New = reinterpret_cast<void *>(na);
break;
case DICTIONARY_ID_TOKEN:
New = reinterpret_cast<void *>(Copy_Sym_Table (reinterpret_cast<SYM_TABLE *>(Data)));
break;
case FUNCT_ID_TOKEN:
case VECTFUNCT_ID_TOKEN:
New = reinterpret_cast<void *>(fnVMContext->functionvm->CopyFunction((FUNCTION_PTR )Data));
Expand Down
34 changes: 25 additions & 9 deletions source/parser/parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,10 @@ struct BetaFlags

class Parser : public SceneTask
{
private:

struct SYM_TABLE;

public:

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

struct LValue
Expand Down Expand Up @@ -276,7 +282,6 @@ class Parser : public SceneTask
{
int *NumberPtr;
void **DataPtr;
int Table_Index;
};

struct DATA_FILE
Expand Down Expand Up @@ -327,6 +332,7 @@ class Parser : public SceneTask
void Parse_Declare (bool is_local, bool after_hash);
void Parse_Matrix (MATRIX Matrix);
void Destroy_Ident_Data (void *Data, int Type);
bool PassParameterByReference (int oldTableIndex);
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);
const char *Get_Token_String (TOKEN Token_Id);
void Test_Redefine(TOKEN Previous, TOKEN *NumberPtr, void *Data, bool allow_redefine = true);
Expand Down Expand Up @@ -368,12 +374,14 @@ class Parser : public SceneTask
void pre_init_tokenizer (void);
void Initialize_Tokenizer (void);
void Terminate_Tokenizer (void);
SYM_ENTRY *Add_Symbol (SYM_TABLE *table, const char *Name,TOKEN Number);
SYM_ENTRY *Add_Symbol (int Index,const char *Name,TOKEN Number);
POV_ARRAY *Parse_Array_Declare (void);
SYM_ENTRY *Create_Entry (int Index,const char *Name,TOKEN Number);
SYM_ENTRY *Create_Entry (const char *Name, TOKEN Number, bool copyName);
SYM_ENTRY *Copy_Entry (const SYM_ENTRY *);
void Acquire_Entry_Reference (SYM_ENTRY *Entry);
void Release_Entry_Reference (int Index, SYM_ENTRY *Entry);
SYM_ENTRY *Destroy_Entry (int Index,SYM_ENTRY *Entry);
void Release_Entry_Reference (SYM_TABLE *table, SYM_ENTRY *Entry);
SYM_ENTRY *Destroy_Entry (SYM_ENTRY *Entry, bool destroyName);
bool Parse_Ifdef_Param ();
int Parse_For_Param (char**, DBL*, DBL*);

Expand Down Expand Up @@ -521,6 +529,7 @@ class Parser : public SceneTask
struct SYM_TABLE
{
SYM_ENTRY *Table[SYM_TABLE_SIZE];
bool namesAreCopies;
};

SYM_TABLE *Tables[MAX_NUMBER_OF_TABLES];
Expand Down Expand Up @@ -574,7 +583,7 @@ class Parser : public SceneTask

CS_ENTRY *Cond_Stack;
int CS_Index;
bool Skipping, Inside_Ifdef, Inside_MacroDef, Parsing_Directive;
bool Skipping, Inside_Ifdef, Inside_MacroDef, Parsing_Directive, parseRawIdentifiers;
IdentifierMode Inside_IdentFn;

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]
Expand Down Expand Up @@ -677,20 +686,27 @@ class Parser : public SceneTask
inline void End_String_Fast (void);
bool Read_Float (void);
void Read_Symbol (void);
SYM_ENTRY *Find_Symbol (int Index, const char *s);
SYM_ENTRY *Find_Symbol (const SYM_TABLE *table, const char *s, int hash);
SYM_ENTRY *Find_Symbol (const SYM_TABLE *table, const char *s);
SYM_ENTRY *Find_Symbol (int index, const char *s);
SYM_ENTRY *Find_Symbol (const char *s);
void Skip_Tokens (COND_TYPE cond);
void Break (void);

int get_hash_value (const char *s);
inline void Write_Token (TOKEN Token_Id, int col);
inline void Write_Token (TOKEN Token_Id, int col, SYM_TABLE *table = NULL);
void Destroy_Table (int index);
void init_sym_tables (void);
void Add_Sym_Table ();
SYM_TABLE *Create_Sym_Table (bool copyNames);
void Destroy_Sym_Table (SYM_TABLE *);
SYM_TABLE *Copy_Sym_Table (const SYM_TABLE *);
void Remove_Symbol (SYM_TABLE *table, const char *Name, bool is_array_elem, void **DataPtr, int ttype);
void Remove_Symbol (int Index, const char *Name, bool is_array_elem, void **DataPtr, int ttype);
Macro *Parse_Macro(void);
void Invoke_Macro(void);
void Return_From_Macro(void);
void Add_Entry (SYM_TABLE *table, SYM_ENTRY *Table_Entry);
void Add_Entry (int Index,SYM_ENTRY *Table_Entry);
void Parse_Initalizer (int Sub, int Base, POV_ARRAY *a);

Expand Down

0 comments on commit 5039065

Please sign in to comment.