Skip to content

Commit 0afc301

Browse files
marsupiallgritz
authored andcommitted
C++11 style Initializer lists (#838)
This lets you have constructs like // pass a {} list as a triple, matrix, or struct void func (point p); func ({x, y, z}); // Assign {} to a struct if the types match up struct vec2 { float x, y; }; vec2 v = {a,b}; // Compact 'return' notation, it knows to construct the return type vec2 func (float a, float b) { return {a, b}; } Along the way, a number of steps: * Initialize struct array elements without going through a temporary. * Refactor codegen of aassign into single method. * Allow float <=> int conversions using "aassign" without going through a temporary. * Allow initializer lists as return types. * Allow initializer lists as function/constructor arguments. * C++11 style initializer lists. * Complete ASTcompound_initializer type check/binding. * Remove ASTNode typecheck_initlist & typecheck_struct_initializers. Everything now flows properly through ASTcompound_initializer. * Adapt to recent function-overload changes. Hide some implementation details that don't need to be public. * Error on ambiguity of arguments using init-lists. * Make warnings & errors involving initializer list arguments more obvious.
1 parent db85b9a commit 0afc301

23 files changed

Lines changed: 1043 additions & 234 deletions

File tree

CMakeLists.txt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -235,8 +235,8 @@ endmacro ()
235235
if (OSL_BUILD_TESTS)
236236
# List all the individual testsuite tests here, except those that need
237237
# special installed tests.
238-
TESTSUITE ( aastep allowconnect-err and-or-not-synonyms
239-
arithmetic array array-derivs array-range
238+
TESTSUITE ( aastep allowconnect-err and-or-not-synonyms arithmetic
239+
array array-derivs array-range array-aassign
240240
blackbody blendmath breakcont
241241
bug-array-heapoffsets
242242
bug-locallifetime bug-outputinit bug-param-duplicate bug-peep
@@ -256,7 +256,7 @@ TESTSUITE ( aastep allowconnect-err and-or-not-synonyms
256256
getsymbol-nonheap gettextureinfo
257257
group-outputs groupstring
258258
hash hashnoise hex hyperb
259-
ieee_fp if incdec initops intbits isconnected isconstant
259+
ieee_fp if incdec initlist initops intbits isconnected isconstant
260260
layers layers-Ciassign layers-entry layers-lazy
261261
layers-nonlazycopy layers-repeatedoutputs
262262
linearstep
@@ -272,6 +272,7 @@ TESTSUITE ( aastep allowconnect-err and-or-not-synonyms
272272
oslc-err-arrayindex oslc-err-closuremul oslc-err-field
273273
oslc-err-format oslc-err-funcoverload
274274
oslc-err-intoverflow oslc-err-noreturn oslc-err-notfunc
275+
oslc-err-initlist-args oslc-err-initlist-return
275276
oslc-err-outputparamvararray oslc-err-paramdefault
276277
oslc-err-struct-array-init oslc-err-struct-ctr
277278
oslc-err-struct-dup oslc-err-struct-print

src/liboslcomp/ast.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,12 @@ ASTvariable_declaration::ASTvariable_declaration (OSLCompilerImpl *comp,
498498
m_isparam(isparam), m_isoutput(isoutput), m_ismetadata(ismeta),
499499
m_initlist(initlist)
500500
{
501+
if (m_initlist && init) {
502+
// Typecheck the init list early.
503+
ASSERT (init->nodetype() == compound_initializer_node);
504+
static_cast<ASTcompound_initializer*>(init)->typecheck(type);
505+
}
506+
501507
m_typespec = type;
502508
Symbol *f = comp->symtab().clash (name);
503509
if (f && ! m_ismetadata) {
@@ -868,7 +874,8 @@ ASTreturn_statement::childname (size_t i) const
868874

869875
ASTcompound_initializer::ASTcompound_initializer (OSLCompilerImpl *comp,
870876
ASTNode *exprlist)
871-
: ASTNode (compound_initializer_node, comp, Nothing, exprlist)
877+
: ASTtype_constructor (compound_initializer_node, comp, TypeSpec(), exprlist),
878+
m_ctor(false)
872879
{
873880
}
874881

@@ -877,7 +884,7 @@ ASTcompound_initializer::ASTcompound_initializer (OSLCompilerImpl *comp,
877884
const char *
878885
ASTcompound_initializer::childname (size_t i) const
879886
{
880-
return "expression_list";
887+
return canconstruct() ? "args" : "expression_list";
881888
}
882889

883890

src/liboslcomp/ast.h

Lines changed: 55 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,8 @@ class ASTNode : public OIIO::RefCnt {
300300
/// Type check a list (whose head is given by 'arg' against the list
301301
/// of expected types given in encoded form by 'formals'.
302302
bool check_arglist (const char *funcname, ref arg,
303-
const char *formals, bool coerce=false);
303+
const char *formals, bool coerce=false,
304+
bool bind = true);
304305

305306
/// Follow a list of nodes, generating code for each in turn, and return
306307
/// the Symbol* for the last thing generated.
@@ -346,25 +347,23 @@ class ASTNode : public OIIO::RefCnt {
346347
bool copywholearrays, int intindex,
347348
bool paraminit);
348349

349-
// Helper: type check an initializer list -- either a single item to
350-
// a scalar, or a list to an array.
351-
void typecheck_initlist (ref init, TypeSpec type, string_view name);
352-
353350
// Helper: generate code for an initializer list -- either a single
354351
// item to a scalar, or a list to an array.
355352
void codegen_initlist (ref init, TypeSpec type, Symbol *sym);
356353

357-
// Special type checking for structure member initializers.
358-
// It's in the ASTNode base class because it's used from mutiple
359-
// subclasses.
360-
TypeSpec typecheck_struct_initializers (ref init, TypeSpec type,
361-
string_view name);
362-
363354
// Special code generation for structure initializers.
364355
// It's in the ASTNode base class because it's used from mutiple
365356
// subclasses.
366357
Symbol *codegen_struct_initializers (ref init, Symbol *sym,
367-
bool is_constructor=false);
358+
bool is_constructor=false,
359+
Symbol *arrayindex = nullptr);
360+
361+
// Codegen an array assignemnt: lval[index] = src
362+
// If no index is provided the constant i is used.
363+
// Will return either src or a temporary that was codegened.
364+
Symbol*
365+
codegen_aassign (TypeSpec elemtype, Symbol *src, Symbol *lval,
366+
Symbol* index, int i = 0);
368367

369368
// Helper for param_default_literals: generate the string that gives
370369
// the initialization of the literal value (and/or the default, if
@@ -707,15 +706,58 @@ class ASTreturn_statement : public ASTNode
707706

708707

709708

710-
class ASTcompound_initializer : public ASTNode
709+
class ASTtype_constructor : public ASTNode
711710
{
711+
protected:
712+
ASTtype_constructor (NodeType n, OSLCompilerImpl *c, TypeSpec t, ASTNode *a)
713+
: ASTNode (n, c, Nothing, a) { m_typespec = t; }
714+
715+
public:
716+
ASTtype_constructor (OSLCompilerImpl *comp, TypeSpec typespec,
717+
ASTNode *args)
718+
: ASTtype_constructor (type_constructor_node, comp, typespec, args) {}
719+
720+
const char *nodetypename () const { return "type_constructor"; }
721+
const char *childname (size_t i) const;
722+
Symbol *codegen (Symbol *dest = NULL);
723+
724+
ref args () const { return child (0); }
725+
726+
// Typecheck construction of expected against args()
727+
// Optionally ignoring errors and binding any init-list arguments to the
728+
// required type.
729+
TypeSpec typecheck (TypeSpec expected, bool error, bool bind = true);
730+
731+
// Typecheck construction of m_typespec against args()
732+
TypeSpec typecheck (TypeSpec expected) {
733+
return typecheck (m_typespec, true, true);
734+
}
735+
};
736+
737+
738+
class ASTcompound_initializer : public ASTtype_constructor
739+
{
740+
bool m_ctor;
741+
742+
TypeSpec typecheck (TypeSpec expected, unsigned mode);
743+
712744
public:
713745
ASTcompound_initializer (OSLCompilerImpl *comp, ASTNode *exprlist);
714746
const char *nodetypename () const { return "compound_initializer"; }
715747
const char *childname (size_t i) const;
716748
Symbol *codegen (Symbol *dest = NULL);
717749

718750
ref initlist () const { return child (0); }
751+
752+
bool canconstruct() const { return m_ctor; }
753+
void canconstruct(bool b) { m_ctor = b; }
754+
755+
TypeSpec typecheck (TypeSpec expected) {
756+
return typecheck(expected, 0);
757+
}
758+
759+
// Helper for typechecking an initlist or structure.
760+
class TypeAdjuster;
719761
};
720762

721763

@@ -840,26 +882,6 @@ class ASTtypecast_expression : public ASTNode
840882

841883

842884

843-
class ASTtype_constructor : public ASTNode
844-
{
845-
public:
846-
ASTtype_constructor (OSLCompilerImpl *comp, TypeSpec typespec,
847-
ASTNode *args)
848-
: ASTNode (type_constructor_node, comp, 0, args)
849-
{
850-
m_typespec = typespec;
851-
}
852-
853-
const char *nodetypename () const { return "type_constructor"; }
854-
const char *childname (size_t i) const;
855-
TypeSpec typecheck (TypeSpec expected);
856-
Symbol *codegen (Symbol *dest = NULL);
857-
858-
ref args () const { return child (0); }
859-
};
860-
861-
862-
863885
class ASTfunction_call : public ASTNode
864886
{
865887
public:

0 commit comments

Comments
 (0)