Skip to content

Commit

Permalink
Allow external method definitions in the style of C++.
Browse files Browse the repository at this point in the history
  • Loading branch information
marsupial committed Dec 29, 2017
1 parent 5dca01a commit 2687f80
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 24 deletions.
62 changes: 54 additions & 8 deletions src/liboslcomp/oslgram.y
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ static ASTNode::ref implicit_this;
// Define the nonterminals
%type <n> shader_file
%type <n> global_declarations_opt global_declarations global_declaration
%type <n> shader_or_function_declaration
%type <n> shader_or_function_declaration method_declaration
%type <n> formal_params_opt formal_params formal_param
%type <n> metadata_block_opt metadata metadatum
%type <n> function_declaration
Expand Down Expand Up @@ -166,21 +166,21 @@ global_declarations
global_declaration
: shader_or_function_declaration { $$ = 0; }
| struct_declaration { $$ = 0; }
| method_declaration { $$ = 0; }
;

shader_or_function_declaration
: typespec_or_shadertype IDENTIFIER
{
if ($1 == ShadTypeUnknown) {
// It's a function declaration, not a shader
ASSERT (! typespec_stack.empty ());
oslcompiler->symtab().push (); // new scope
typespec_stack.push (oslcompiler->current_typespec());
}
}
metadata_block_opt '('
{
if ($1 != ShadTypeUnknown)
oslcompiler->declaring_shader_formals (true);
oslcompiler->declaring_shader_formals ($1 != ShadTypeUnknown);
}
formal_params_opt ')'
{
Expand Down Expand Up @@ -219,6 +219,49 @@ shader_or_function_declaration
}
;

method_declaration
: typespec_or_shadertype typespec ':' ':' IDENTIFIER
{
// It's a method declaration, not a shader
if ($1 != ShadTypeUnknown || typespec_stack.empty() ||
(! oslcompiler->current_typespec().is_structure() &&
! oslcompiler->current_typespec().is_triple())) {
oslcompiler->error (oslcompiler->filename(),
oslcompiler->lineno(),
"Cannot declare a method for this type");
}

oslcompiler->symtab().push (); // new scope
typespec_stack.push (oslcompiler->current_typespec());
}
'(' formal_params_opt ')' metadata_block_opt
{
implicit_this = new ASTvariable_declaration(oslcompiler,
typespec_stack.top(),
$8);
typespec_stack.pop ();
$<n>$ = implicit_this.get();
}
function_body_or_just_decl
{
// Method declaration
ASSERT ($1 == ShadTypeUnknown);
oslcompiler->symtab().pop (); // restore scope
ASTfunction_declaration *f;
f = new ASTfunction_declaration (oslcompiler,
typespec_stack.top(),
ustring($5),
$<n>11 /*arguments*/,
$12 /*statements*/,
$10 /*meta*/);
implicit_this = nullptr;
typespec_stack.pop ();
oslcompiler->remember_function_decl (f);
f->sourceline (@2.first_line);
$$ = f;
}
;

formal_params_opt
: formal_params
| /* empty */ { $$ = 0; }
Expand Down Expand Up @@ -581,12 +624,14 @@ typespec_or_shadertype
: simple_typename
{
oslcompiler->current_typespec (TypeSpec (osllextype ($1)));
$$ = 0;
typespec_stack.push (oslcompiler->current_typespec ());
$$ = ShadTypeUnknown;
}
| CLOSURE simple_typename
{
oslcompiler->current_typespec (TypeSpec (osllextype ($2), true));
$$ = 0;
typespec_stack.push (oslcompiler->current_typespec ());
$$ = ShadTypeUnknown;
}
| IDENTIFIER /* struct name or shader type name */
{
Expand All @@ -601,9 +646,10 @@ typespec_or_shadertype
$$ = ShadTypeVolume;
else {
Symbol *s = oslcompiler->symtab().find (name);
if (s && s->is_structure())
if (s && s->is_structure()) {
oslcompiler->current_typespec (TypeSpec ("", s->typespec().structure()));
else {
typespec_stack.push (oslcompiler->current_typespec ());
} else {
oslcompiler->current_typespec (TypeSpec (TypeDesc::UNKNOWN));
oslcompiler->error (oslcompiler->filename(),
oslcompiler->lineno(),
Expand Down
3 changes: 3 additions & 0 deletions src/liboslcomp/typecheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -912,6 +912,9 @@ TypeSpec
ASTfunction_call::typecheck_all_poly (TypeSpec expected, bool coerceargs,
bool equivreturn)
{
if (m_name == "custom_method1")
m_name = "custom_method1";

for (FunctionSymbol *poly = func(); poly; poly = poly->nextpoly()) {
const char *code = poly->argcodes().c_str();
int advance;
Expand Down
16 changes: 13 additions & 3 deletions testsuite/function-method/ref/out.txt
Original file line number Diff line number Diff line change
@@ -1,16 +1,26 @@
test.osl:16: warning: argument "f" shadows a field with the same name
test.osl:22: warning: argument "f" shadows a field with the same name
test.osl:27: warning: "f" shadows a field with the same name
test.osl:13: warning: argument "f" shadows a field with the same name
test.osl:19: warning: argument "f" shadows a field with the same name
test.osl:36: warning: "f" shadows a field with the same name
Compiled test.osl -> test.oso
emethod::test: (42) (2)
emethod::test: (42) (46)
emethod::testchain: 28
emethod::testchain: 24
emethod::testchain: 16
emethod::testchain: 0
emethod::predecl: (40) (40) (2)
emethod::shadowed: (40) (3.14)
emethod::shadowed2: 40 22.4 6.28
emethod::shadowed: (40) (6.28)
unshadowed 5
unshadowed *
custom_method0(c{1 1 1})
custom_method0(v{2 2 2})
custom_method1(c{1 1 1}, c{3 3 3})
c.custom_method1 = 4 4 4
custom_method1(v{2 2 2}, f2)
vo = 4 4 4
custom_method3: 101 2 3
c1.custom_method3: 34 (101 2 3)
custom_method3: 101 1 1

75 changes: 62 additions & 13 deletions testsuite/function-method/test.osl
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
void unshadowed(int i) { printf("unshadowed %d\n", i); }
void unshadowed() { printf("unshadowed *\n"); }

struct emethod {
float f;

Expand All @@ -23,25 +20,77 @@ struct emethod {
printf("emethod::shadowed: (%g) (%g)\n", this.f, f);
}

float shadowed2(float ff) {
float f = 32.4;
f -= 10;
printf("emethod::shadowed2: %g %g %g\n", this.f, f, ff);
shadowed(ff);
unshadowed(5);
unshadowed();
return f;
}
vector predecl(float ff);
};

vector emethod::predecl(float ff) {
f -= ff;
printf("emethod::predecl: (%g) (%g) (%g)\n", this.f, f, ff);
return vector(6,7,8);
}

void unshadowed(int i) { printf("unshadowed %d\n", i); }
void unshadowed() { printf("unshadowed *\n"); }

float emethod::shadowed2(float ff) {
float f = 32.4;
f -= 10;
printf("emethod::shadowed2: %g %g %g\n", this.f, f, ff);
shadowed(ff);
unshadowed(5);
unshadowed();
return f;
}

float color::custom_method3(color c, color b) [[ string description = "MB" ]] {
this[0] += 100;
printf("custom_method3: %g\n", this);
return this[1] + 32.0;
}

color custom_method0(color c) {
printf("custom_method0(c{%g})\n", c);
return c;
}

vector custom_method0(vector v) {
printf("custom_method0(v{%g})\n", v);
return v;
}

color custom_method1(color c, color b) {
printf("custom_method1(c{%g}, c{%g})\n", c, b);
return c + b;
}

vector custom_method1(vector v, float b) {
printf("custom_method1(v{%g}, f%g)\n", v, b);
return v + vector(b);
}

shader test ()
{
emethod e = { 42 };
e.test(2);
e.test2(2);
emethod(2+4+8+16).testchain(2).testchain(4).testchain(8).testchain(16);
e.f -= 2;
e.predecl(2.0);
e.shadowed(3.14);
e.shadowed2(6.28);

color c = 1;
vector vo = 2;

c.custom_method0();
vo.custom_method0();

printf("c.custom_method1 = %g\n", c.custom_method1(color(3)));

vo = vo.custom_method1(2.0);
printf("vo = %g\n", vo);

color c1 = color(1,2,3);
printf("c1.custom_method3: %g (%g)\n", c1.custom_method3(c,c), c1);

custom_method3(c,c,c);
}

0 comments on commit 2687f80

Please sign in to comment.