Skip to content

Commit e0df57d

Browse files
committed
Refactor ASTNodes who have both a Symbol and name into common base class ASTnamed_symbol.
1 parent d35e681 commit e0df57d

5 files changed

Lines changed: 237 additions & 105 deletions

File tree

src/liboslcomp/ast.cpp

Lines changed: 125 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,109 @@ ASTNode::type_c_str (const TypeSpec &type) const
251251

252252

253253

254+
ASTnamed_symbol::ASTnamed_symbol (NodeType node_type, OSLCompilerImpl *comp,
255+
ustring name)
256+
: ASTNode (node_type, comp, Nothing), m_name(name), m_sym(nullptr)
257+
{
258+
}
259+
260+
261+
262+
ASTnamed_symbol::ASTnamed_symbol (NodeType node_type, OSLCompilerImpl *comp,
263+
ustring name, ASTNode *a)
264+
: ASTNode (node_type, comp, Nothing, a), m_name(name), m_sym(nullptr)
265+
{
266+
}
267+
268+
269+
270+
ASTnamed_symbol::ASTnamed_symbol (NodeType node_type, OSLCompilerImpl *comp,
271+
ustring name, ASTNode *a, ASTNode *b)
272+
: ASTNode (node_type, comp, Nothing, a, b), m_name(name), m_sym(nullptr)
273+
{
274+
}
275+
276+
277+
278+
ASTnamed_symbol::ASTnamed_symbol (NodeType node_type, OSLCompilerImpl *comp,
279+
ustring name, ASTNode *a, ASTNode *b,
280+
ASTNode *c)
281+
: ASTNode (node_type, comp, Nothing, a, b, c), m_name(name), m_sym(nullptr)
282+
{
283+
}
284+
285+
286+
287+
void
288+
ASTnamed_symbol::check_reserved (ustring name, OSLCompilerImpl *comp)
289+
{
290+
if (Strutil::starts_with(name, "___")) {
291+
comp->error (comp->filename(), comp->lineno(),
292+
"'%s' : sorry, can't start with three underscores",
293+
name);
294+
}
295+
}
296+
297+
298+
299+
std::string
300+
ASTnamed_symbol::previous_decl (ASTNode* node)
301+
{
302+
if (! node)
303+
return "";
304+
305+
return Strutil::format ("\n\t\tprevious declaration was at %s:%d",
306+
OIIO::Filesystem::filename(node->sourcefile().string()),
307+
node->sourceline());
308+
}
309+
310+
311+
312+
Symbol*
313+
ASTnamed_symbol::validate (ustring name, OSLCompilerImpl *comp,
314+
Validation vflags, int allowed)
315+
{
316+
check_reserved (name, comp);
317+
318+
Symbol *f;
319+
bool shadow = vflags & warn_shadow;
320+
if (! (vflags & check_clashes)) {
321+
f = comp->symtab().find (name);
322+
if (! f) {
323+
comp->error (comp->filename(), comp->lineno(),
324+
"'%s' was not declared in this scope", name);
325+
// FIXME -- would be fun to troll through the symtab and try to
326+
// find the things that almost matched and offer suggestions.
327+
}
328+
else if (shadow && f->symtype() == SymTypeFunction) {
329+
comp->error (comp->filename(), comp->lineno(),
330+
"function '%s' can't be used as a variable", name);
331+
}
332+
} else {
333+
f = comp->symtab().clash (name);
334+
// If no symbol, or symbol matches allowed type: no clash.
335+
if (! f || f->symtype() == allowed)
336+
return f;
337+
338+
std::string e = Strutil::format ("'%s' already declared in this scope",
339+
name);
340+
e += previous_decl (f->node());
341+
342+
if (shadow) {
343+
// special case: only a warning for param to mask global function
344+
shadow = f->scope() == 0 && f->symtype() == SymTypeFunction;
345+
}
346+
347+
if (shadow)
348+
comp->warning(comp->filename(), comp->lineno(), "%s", e);
349+
else
350+
comp->error(comp->filename(), comp->lineno(), "%s", e);
351+
}
352+
return f;
353+
}
354+
355+
356+
254357
ASTshader_declaration::ASTshader_declaration (OSLCompilerImpl *comp,
255358
int stype, ustring name, ASTNode *form,
256359
ASTNode *stmts, ASTNode *meta)
@@ -305,22 +408,11 @@ ASTshader_declaration::shadertypename () const
305408
ASTfunction_declaration::ASTfunction_declaration (OSLCompilerImpl *comp,
306409
TypeSpec type, ustring name,
307410
ASTNode *form, ASTNode *stmts, ASTNode *meta)
308-
: ASTNode (function_declaration_node, comp, 0, meta, form, stmts),
309-
m_name(name), m_sym(NULL), m_is_builtin(false)
411+
: ASTnamed_symbol (function_declaration_node, comp, name, meta, form, stmts),
412+
m_is_builtin(false)
310413
{
311414
m_typespec = type;
312-
Symbol *f = comp->symtab().clash (name);
313-
if (f && f->symtype() != SymTypeFunction) {
314-
error ("\"%s\" already declared in this scope as a ", name.c_str(),
315-
f->typespec().string().c_str());
316-
// FIXME -- print the file and line of the other definition
317-
f = NULL;
318-
}
319-
320-
if (name[0] == '_' && name[1] == '_' && name[2] == '_') {
321-
error ("\"%s\" : sorry, can't start with three underscores",
322-
name.c_str());
323-
}
415+
Symbol* sym = validate (check_clashes, SymTypeFunction);
324416

325417
std::string argcodes = oslcompiler->code_from_type (m_typespec);
326418
for (ASTNode *arg = form; arg; arg = arg->nextptr()) {
@@ -337,8 +429,8 @@ ASTfunction_declaration::ASTfunction_declaration (OSLCompilerImpl *comp,
337429
v->name().c_str());
338430
}
339431

340-
if (stmts && f && f->symtype() == SymTypeFunction) {
341-
for (FunctionSymbol* poly = static_cast<FunctionSymbol*>(f); poly;
432+
if (stmts && sym && sym->symtype() == SymTypeFunction) {
433+
for (FunctionSymbol* poly = static_cast<FunctionSymbol*>(sym); poly;
342434
poly = poly->nextpoly ()) {
343435
// If the argcodes match, only one should have statements.
344436
// If there is no ASTNode for the poly, must be a builtin, and has
@@ -351,11 +443,7 @@ ASTfunction_declaration::ASTfunction_declaration (OSLCompilerImpl *comp,
351443
type_c_str(type), m_name,
352444
argcodes.size() <= 1 ? "" :
353445
m_compiler->typelist_from_code(argcodes.c_str()+1),
354-
other ? Strutil::format (
355-
"\n\t\tprevious declaration was at %s:%d",
356-
OIIO::Filesystem::filename(other->sourcefile().string()),
357-
other->sourceline())
358-
: std::string());
446+
previous_decl (other));
359447
// Set m_sym to the function that is being overwritten.
360448
m_sym = poly;
361449
return;
@@ -364,7 +452,8 @@ ASTfunction_declaration::ASTfunction_declaration (OSLCompilerImpl *comp,
364452
}
365453

366454
m_sym = new FunctionSymbol (name, type, this);
367-
func()->nextpoly ((FunctionSymbol *)f);
455+
if (sym && sym->symtype() == SymTypeFunction)
456+
func()->nextpoly ((FunctionSymbol *)sym);
368457

369458
func()->argcodes (ustring (argcodes));
370459
oslcompiler->symtab().insert (m_sym);
@@ -438,31 +527,16 @@ ASTvariable_declaration::ASTvariable_declaration (OSLCompilerImpl *comp,
438527
ustring name, ASTNode *init,
439528
bool isparam, bool ismeta,
440529
bool isoutput, bool initlist)
441-
: ASTNode (variable_declaration_node, comp, 0, init, NULL /* meta */),
442-
m_name(name), m_sym(NULL),
530+
: ASTnamed_symbol (variable_declaration_node, comp, name, init, NULL /* meta */),
443531
m_isparam(isparam), m_isoutput(isoutput), m_ismetadata(ismeta),
444532
m_initlist(initlist)
445533
{
446534
m_typespec = type;
447-
Symbol *f = comp->symtab().clash (name);
448-
if (f && ! m_ismetadata) {
449-
std::string e = Strutil::format ("\"%s\" already declared in this scope", name.c_str());
450-
if (f->node()) {
451-
std::string filename = OIIO::Filesystem::filename(f->node()->sourcefile().string());
452-
e += Strutil::format ("\n\t\tprevious declaration was at %s:%d",
453-
filename, f->node()->sourceline());
454-
}
455-
if (f->scope() == 0 && f->symtype() == SymTypeFunction && isparam) {
456-
// special case: only a warning for param to mask global function
457-
warning ("%s", e.c_str());
458-
} else {
459-
error ("%s", e.c_str());
460-
}
461-
}
462-
if (name[0] == '_' && name[1] == '_' && name[2] == '_') {
463-
error ("\"%s\" : sorry, can't start with three underscores",
464-
name.c_str());
465-
}
535+
if (! m_ismetadata)
536+
validate (warn_function_clash);
537+
else
538+
check_reserved ();
539+
466540
SymType symtype = isparam ? (isoutput ? SymTypeOutputParam : SymTypeParam)
467541
: SymTypeLocal;
468542
// Sneaky debugging aid: a local that starts with "__debug_tmp__"
@@ -523,20 +597,11 @@ ASTvariable_declaration::print (std::ostream &out, int indentlevel) const
523597

524598

525599
ASTvariable_ref::ASTvariable_ref (OSLCompilerImpl *comp, ustring name)
526-
: ASTNode (variable_ref_node, comp), m_name(name), m_sym(NULL)
600+
: ASTnamed_symbol (variable_ref_node, comp, name)
527601
{
528-
m_sym = comp->symtab().find (name);
529-
if (! m_sym) {
530-
error ("'%s' was not declared in this scope", name.c_str());
531-
// FIXME -- would be fun to troll through the symtab and try to
532-
// find the things that almost matched and offer suggestions.
533-
return;
534-
}
535-
if (m_sym->symtype() == SymTypeFunction) {
536-
error ("function '%s' can't be used as a variable", name.c_str());
537-
return;
538-
}
539-
m_typespec = m_sym->typespec();
602+
m_sym = validate (warn_function_exists);
603+
if (m_sym)
604+
m_typespec = m_sym->typespec();
540605
}
541606

542607

@@ -1049,25 +1114,18 @@ ASTtype_constructor::childname (size_t i) const
10491114

10501115
ASTfunction_call::ASTfunction_call (OSLCompilerImpl *comp, ustring name,
10511116
ASTNode *args, FunctionSymbol *funcsym)
1052-
: ASTNode (function_call_node, comp, 0, args), m_name(name),
1053-
m_sym(funcsym ? funcsym : comp->symtab().find (name)), // Look it up.
1117+
: ASTnamed_symbol (function_call_node, comp, name, args),
10541118
m_poly(funcsym), // Default - resolved symbol or null
10551119
m_argread(~1), // Default - all args are read except the first
10561120
m_argwrite(1), // Default - first arg only is written by the op
10571121
m_argtakesderivs(0) // Default - doesn't take derivs
10581122
{
1059-
if (! m_sym) {
1060-
error ("function '%s' was not declared in this scope", name);
1061-
// FIXME -- would be fun to troll through the symtab and try to
1062-
// find the things that almost matched and offer suggestions.
1123+
m_sym = funcsym ? funcsym : validate (err_must_exist); // Look it up.
1124+
if (! m_sym || is_struct_ctr())
10631125
return;
1064-
}
1065-
if (is_struct_ctr()) {
1066-
return; // It's a struct constructor
1067-
}
10681126
if (m_sym->symtype() != SymTypeFunction) {
10691127
error ("'%s' is not a function", name.c_str());
1070-
m_sym = NULL;
1128+
m_sym = nullptr;
10711129
return;
10721130
}
10731131
}

0 commit comments

Comments
 (0)