Skip to content

Commit 9953d0d

Browse files
committed
Basic method definition and invocation.
1 parent 44e993c commit 9953d0d

12 files changed

Lines changed: 241 additions & 44 deletions

File tree

CMakeLists.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -250,8 +250,8 @@ TESTSUITE ( aastep allowconnect-err and-or-not-synonyms arithmetic
250250
draw_string
251251
error-dupes exit exponential
252252
fprintf
253-
function-earlyreturn function-simple function-outputelem
254-
function-overloads function-redef
253+
function-earlyreturn function-method function-simple
254+
function-outputelem function-overloads function-redef
255255
geomath getattribute-camera getattribute-shader
256256
getsymbol-nonheap gettextureinfo
257257
group-outputs groupstring
@@ -273,7 +273,7 @@ TESTSUITE ( aastep allowconnect-err and-or-not-synonyms arithmetic
273273
oslc-err-format oslc-err-funcoverload
274274
oslc-err-intoverflow
275275
oslc-err-initlist-args oslc-err-initlist-return
276-
oslc-err-names oslc-err-noreturn oslc-err-notfunc
276+
oslc-err-method oslc-err-names oslc-err-noreturn oslc-err-notfunc
277277
oslc-err-outputparamvararray oslc-err-paramdefault
278278
oslc-err-struct-array-init oslc-err-struct-ctr
279279
oslc-err-struct-dup oslc-err-struct-print

src/include/osl_pvt.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -558,6 +558,10 @@ class Symbol {
558558
m_alias = other;
559559
}
560560

561+
/// Get a reference to whatever this symbol aliases.
562+
///
563+
const Symbol* alias () const { return m_alias; }
564+
561565
/// Return a string representation ("param", "global", etc.) of the
562566
/// SymType s.
563567
static const char *symtype_shortname (SymType s);

src/liboslcomp/ast.cpp

Lines changed: 99 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -325,14 +325,15 @@ ASTnamed_symbol::ASTnamed_symbol (NodeType node_type, OSLCompilerImpl *comp,
325325

326326

327327
bool
328-
ASTnamed_symbol::check_reserved (ustring name, OSLCompilerImpl *comp)
328+
ASTnamed_symbol::check_reserved (ustring name, OSLCompilerImpl *comp,
329+
int vflags)
329330
{
330331
if (Strutil::starts_with(name, "___")) {
331332
comp->error (comp->filename(), comp->lineno(),
332333
"'%s' : sorry, can't start with three underscores",
333334
name);
334335
return false;
335-
} else if (name == "this") {
336+
} else if (!(vflags & allow_this) && name == "this") {
336337
comp->error (comp->filename(), comp->lineno(),
337338
"'this' not allowed in this context");
338339
return false;
@@ -357,9 +358,9 @@ ASTnamed_symbol::previous_decl (ASTNode* node)
357358

358359
Symbol*
359360
ASTnamed_symbol::validate (ustring name, OSLCompilerImpl *comp,
360-
Validation vflags, int allowed)
361+
int vflags, int allowed)
361362
{
362-
check_reserved (name, comp);
363+
check_reserved (name, comp, vflags);
363364

364365
Symbol *f;
365366
bool shadow = vflags & warn_shadow;
@@ -381,19 +382,35 @@ ASTnamed_symbol::validate (ustring name, OSLCompilerImpl *comp,
381382
if (! f || f->symtype() == allowed)
382383
return f;
383384

384-
std::string e = Strutil::format ("'%s' already declared in this scope",
385-
name);
386-
e += previous_decl (f->node());
387-
385+
std::string msg;
386+
ASTNode* hint = f->node();
388387
if (shadow) {
389-
// special case: only a warning for param to mask global function
388+
// Downgrade to warning if param to mask global function
390389
shadow = f->scope() == 0 && f->symtype() == SymTypeFunction;
390+
391+
// also downgrade to warning if local variable shadowing a field
392+
if (!shadow && f->alias() && f->alias()->node()) {
393+
if (f->alias()->node()->typespec().is_structure() &&
394+
f->alias()->name() == Strutil::format("this.%s", name)) {
395+
msg = Strutil::format ("\"%s\" shadows a field with the same name",
396+
name);
397+
// FIXME: Would be nice to hint about where the field was
398+
// declared, but f->alias()->node() is the 'this.field' node.
399+
hint = nullptr;
400+
shadow = true;
401+
}
402+
}
391403
}
392404

405+
if (msg.empty())
406+
msg = Strutil::format ("'%s' already declared in this scope", name);
407+
408+
msg += previous_decl (hint);
409+
393410
if (shadow)
394-
comp->warning(comp->filename(), comp->lineno(), "%s", e);
411+
comp->warning(comp->filename(), comp->lineno(), "%s", msg);
395412
else
396-
comp->error(comp->filename(), comp->lineno(), "%s", e);
413+
comp->error(comp->filename(), comp->lineno(), "%s", msg);
397414
}
398415
return f;
399416
}
@@ -598,12 +615,14 @@ ASTvariable_declaration::ASTvariable_declaration (OSLCompilerImpl *comp,
598615
const TypeSpec &type,
599616
ustring name, ASTNode *init,
600617
bool isparam, bool ismeta,
601-
bool isoutput, bool initlist)
618+
bool isoutput, bool initlist,
619+
bool isthis)
602620
: ASTnamed_symbol (variable_declaration_node, comp, name, init, NULL /* meta */),
603621
m_isparam(isparam), m_isoutput(isoutput), m_ismetadata(ismeta),
604622
m_initlist(initlist)
605623
{
606-
if (! check_reserved ())
624+
int vflags = isthis ? allow_this : 0;
625+
if (! check_reserved (m_name, m_compiler, vflags))
607626
return;
608627

609628
if (m_initlist && init) {
@@ -614,7 +633,7 @@ ASTvariable_declaration::ASTvariable_declaration (OSLCompilerImpl *comp,
614633

615634
m_typespec = type;
616635
if (! m_ismetadata)
617-
validate (warn_function_clash);
636+
validate (vflags | warn_function_clash);
618637

619638
SymType symtype = isparam ? (isoutput ? SymTypeOutputParam : SymTypeParam)
620639
: SymTypeLocal;
@@ -638,6 +657,50 @@ ASTvariable_declaration::ASTvariable_declaration (OSLCompilerImpl *comp,
638657

639658

640659

660+
ASTvariable_declaration::ASTvariable_declaration (OSLCompilerImpl *comp,
661+
const TypeSpec &type,
662+
ASTNode *args)
663+
: ASTvariable_declaration(comp, type, ustring("this"), NULL,
664+
false, false, false, false, true)
665+
{
666+
// Push 'this' to front of given arguments
667+
concat(this, args);
668+
if (StructSpec* sspec = type.structure() ? type.structspec() : nullptr) {
669+
// Add the fields as accessible without 'this', warning about possible
670+
// shadowing/ambiguity as we go.
671+
for (int i = 0, n = sspec->numfields(); i < n; ++i) {
672+
const auto& field = sspec->field(i);
673+
bool conflict = false;
674+
for (ref next = args; next; next = next->next()) {
675+
ASSERT (next->nodetype() == variable_declaration_node);
676+
auto *arg = static_cast<ASTvariable_declaration*>(next.get());
677+
678+
if (arg->name() == field.name) {
679+
warning ("argument \"%s\" shadows a field with the same name",
680+
field.name);
681+
conflict = true;
682+
break;
683+
}
684+
}
685+
if (! conflict) {
686+
ustring qualname = ustring::format ("this.%s", field.name);
687+
ASSERT (m_compiler->symtab().find (qualname) != nullptr);
688+
ASSERT (!m_compiler->symtab().find (field.name) ||
689+
m_compiler->symtab().find (field.name)->scope() !=
690+
m_compiler->symtab().scopeid());
691+
692+
Symbol* qsym = m_compiler->symtab().find (qualname);
693+
Symbol *fsym = new Symbol (field.name, field.type,
694+
qsym->symtype (), this);
695+
fsym->alias (qsym);
696+
m_compiler->symtab().insert (fsym);
697+
}
698+
}
699+
}
700+
}
701+
702+
703+
641704
const char *
642705
ASTvariable_declaration::nodetypename () const
643706
{
@@ -675,10 +738,10 @@ ASTvariable_declaration::print (std::ostream &out, int indentlevel) const
675738

676739

677740

678-
ASTvariable_ref::ASTvariable_ref (OSLCompilerImpl *comp, ustring name)
741+
ASTvariable_ref::ASTvariable_ref (OSLCompilerImpl *comp, ustring name, bool allowthis)
679742
: ASTnamed_symbol (variable_ref_node, comp, name)
680743
{
681-
m_sym = validate (warn_function_exists);
744+
m_sym = validate (warn_function_exists | (allowthis ? allow_this : 0));
682745
if (m_sym)
683746
m_typespec = m_sym->typespec();
684747
}
@@ -1195,10 +1258,11 @@ ASTtype_constructor::childname (size_t i) const
11951258
ASTfunction_call::ASTfunction_call (OSLCompilerImpl *comp, ustring name,
11961259
ASTNode *args, FunctionSymbol *funcsym)
11971260
: ASTnamed_symbol (function_call_node, comp, name, args),
1198-
m_poly(funcsym), // Default - resolved symbol or null
1199-
m_argread(~1), // Default - all args are read except the first
1200-
m_argwrite(1), // Default - first arg only is written by the op
1201-
m_argtakesderivs(0) // Default - doesn't take derivs
1261+
m_poly(funcsym), // Default - resolved symbol or null
1262+
m_argread(~1), // Default - all args are read except the first
1263+
m_argwrite(1), // Default - first arg only is written by the op
1264+
m_argtakesderivs(0), // Default - doesn't take derivs
1265+
m_method(false)
12021266
{
12031267
m_sym = funcsym ? funcsym : validate (err_must_exist); // Look it up.
12041268
if (! m_sym || is_struct_ctr())
@@ -1212,10 +1276,24 @@ ASTfunction_call::ASTfunction_call (OSLCompilerImpl *comp, ustring name,
12121276

12131277

12141278

1279+
void
1280+
ASTfunction_call::method_from_function (ASTNode* thisRef)
1281+
{
1282+
ASSERT (m_method == false);
1283+
ASSERT (m_children.size() == 1);
1284+
m_method = true;
1285+
if (m_children[0])
1286+
thisRef->append(args().get());
1287+
1288+
m_children[0] = thisRef;
1289+
}
1290+
1291+
1292+
12151293
const char *
12161294
ASTfunction_call::childname (size_t i) const
12171295
{
1218-
return ustring::format ("param%d", (int)i).c_str();
1296+
return (i || !m_method ? ustring::format ("param%d", (int)i) : ustring("this")).c_str();
12191297
}
12201298

12211299

src/liboslcomp/ast.h

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -416,26 +416,28 @@ class ASTnamed_symbol : public ASTNode
416416
err_must_exist = 0, ///< Error when the named Symbol does not exist.
417417
check_clashes = 1, ///< If named Symbol exists error as a clash.
418418
warn_shadow = 2, ///< Warn if name shadows a known function.
419+
allow_this = 4, ///< Allow m_name to be 'this'
419420

420421
/// Convenient aliases of validation schemes.
421422
warn_function_exists = err_must_exist | warn_shadow,
422423
warn_function_clash = check_clashes | warn_shadow,
423424
};
424425

425426
/// Validate that m_name is a legal name.
426-
static bool check_reserved (ustring name, OSLCompilerImpl *comp);
427+
static bool check_reserved (ustring name, OSLCompilerImpl *comp,
428+
int allowThis = 0);
427429

428430
/// Validate that m_name is a legal name, and doesn't conflict with rules
429431
/// given in vflags allowing duplicate symbol if its SymType matches allowed.
430432
static Symbol* validate (ustring name, OSLCompilerImpl *comp,
431-
Validation vflags, int allowed = -1);
433+
int vflags, int allowed = -1);
432434

433435
protected:
434436
bool check_reserved () {
435437
return ASTnamed_symbol::check_reserved (m_name, m_compiler);
436438
}
437439

438-
Symbol* validate (Validation vflags, int allowed = -1) {
440+
Symbol* validate (int vflags, int allowed = -1) {
439441
return validate (m_name, m_compiler, vflags, allowed);
440442
}
441443

@@ -504,7 +506,11 @@ class ASTvariable_declaration : public ASTnamed_symbol
504506
ASTvariable_declaration (OSLCompilerImpl *comp, const TypeSpec &type,
505507
ustring name, ASTNode *init, bool isparam=false,
506508
bool ismeta=false, bool isoutput=false,
507-
bool initlist=false);
509+
bool initlist=false, bool isthis=false);
510+
511+
ASTvariable_declaration (OSLCompilerImpl *comp, const TypeSpec &type,
512+
ASTNode *args);
513+
508514
const char *nodetypename () const;
509515
const char *childname (size_t i) const;
510516
void print (std::ostream &out, int indentlevel=0) const;
@@ -551,7 +557,7 @@ class ASTvariable_declaration : public ASTnamed_symbol
551557
class ASTvariable_ref : public ASTnamed_symbol
552558
{
553559
public:
554-
ASTvariable_ref (OSLCompilerImpl *comp, ustring name);
560+
ASTvariable_ref (OSLCompilerImpl *comp, ustring name, bool allowthis);
555561
const char *nodetypename () const { return "variable_ref"; }
556562
const char *childname (size_t i) const { return ""; } // no children
557563
void print (std::ostream &out, int indentlevel=0) const;
@@ -954,6 +960,8 @@ class ASTfunction_call : public ASTnamed_symbol
954960
return (ASTfunction_declaration *) func()->node();
955961
}
956962

963+
void method_from_function(ASTNode* thisRef);
964+
957965
private:
958966
/// Handle all the special cases for built-ins. This includes
959967
/// irregular patterns of which args are read vs written, special
@@ -1027,10 +1035,13 @@ class ASTfunction_call : public ASTnamed_symbol
10271035
ustring formal, ustring actual,
10281036
Symbol *arrayindex = NULL);
10291037

1038+
protected:
1039+
10301040
FunctionSymbol *m_poly; ///< The specific polymorphic variant
10311041
unsigned int m_argread; ///< Bit field - which args are read
10321042
unsigned int m_argwrite; ///< Bit field - which args are written
10331043
unsigned int m_argtakesderivs; ///< Bit field - which args take derivs
1044+
bool m_method;
10341045
};
10351046

10361047

0 commit comments

Comments
 (0)