Skip to content

Commit 2687f80

Browse files
committed
Allow external method definitions in the style of C++.
1 parent 5dca01a commit 2687f80

File tree

4 files changed

+132
-24
lines changed

4 files changed

+132
-24
lines changed

src/liboslcomp/oslgram.y

Lines changed: 54 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ static ASTNode::ref implicit_this;
9797
// Define the nonterminals
9898
%type <n> shader_file
9999
%type <n> global_declarations_opt global_declarations global_declaration
100-
%type <n> shader_or_function_declaration
100+
%type <n> shader_or_function_declaration method_declaration
101101
%type <n> formal_params_opt formal_params formal_param
102102
%type <n> metadata_block_opt metadata metadatum
103103
%type <n> function_declaration
@@ -166,21 +166,21 @@ global_declarations
166166
global_declaration
167167
: shader_or_function_declaration { $$ = 0; }
168168
| struct_declaration { $$ = 0; }
169+
| method_declaration { $$ = 0; }
169170
;
170171

171172
shader_or_function_declaration
172173
: typespec_or_shadertype IDENTIFIER
173174
{
174175
if ($1 == ShadTypeUnknown) {
175176
// It's a function declaration, not a shader
177+
ASSERT (! typespec_stack.empty ());
176178
oslcompiler->symtab().push (); // new scope
177-
typespec_stack.push (oslcompiler->current_typespec());
178179
}
179180
}
180181
metadata_block_opt '('
181182
{
182-
if ($1 != ShadTypeUnknown)
183-
oslcompiler->declaring_shader_formals (true);
183+
oslcompiler->declaring_shader_formals ($1 != ShadTypeUnknown);
184184
}
185185
formal_params_opt ')'
186186
{
@@ -219,6 +219,49 @@ shader_or_function_declaration
219219
}
220220
;
221221

222+
method_declaration
223+
: typespec_or_shadertype typespec ':' ':' IDENTIFIER
224+
{
225+
// It's a method declaration, not a shader
226+
if ($1 != ShadTypeUnknown || typespec_stack.empty() ||
227+
(! oslcompiler->current_typespec().is_structure() &&
228+
! oslcompiler->current_typespec().is_triple())) {
229+
oslcompiler->error (oslcompiler->filename(),
230+
oslcompiler->lineno(),
231+
"Cannot declare a method for this type");
232+
}
233+
234+
oslcompiler->symtab().push (); // new scope
235+
typespec_stack.push (oslcompiler->current_typespec());
236+
}
237+
'(' formal_params_opt ')' metadata_block_opt
238+
{
239+
implicit_this = new ASTvariable_declaration(oslcompiler,
240+
typespec_stack.top(),
241+
$8);
242+
typespec_stack.pop ();
243+
$<n>$ = implicit_this.get();
244+
}
245+
function_body_or_just_decl
246+
{
247+
// Method declaration
248+
ASSERT ($1 == ShadTypeUnknown);
249+
oslcompiler->symtab().pop (); // restore scope
250+
ASTfunction_declaration *f;
251+
f = new ASTfunction_declaration (oslcompiler,
252+
typespec_stack.top(),
253+
ustring($5),
254+
$<n>11 /*arguments*/,
255+
$12 /*statements*/,
256+
$10 /*meta*/);
257+
implicit_this = nullptr;
258+
typespec_stack.pop ();
259+
oslcompiler->remember_function_decl (f);
260+
f->sourceline (@2.first_line);
261+
$$ = f;
262+
}
263+
;
264+
222265
formal_params_opt
223266
: formal_params
224267
| /* empty */ { $$ = 0; }
@@ -581,12 +624,14 @@ typespec_or_shadertype
581624
: simple_typename
582625
{
583626
oslcompiler->current_typespec (TypeSpec (osllextype ($1)));
584-
$$ = 0;
627+
typespec_stack.push (oslcompiler->current_typespec ());
628+
$$ = ShadTypeUnknown;
585629
}
586630
| CLOSURE simple_typename
587631
{
588632
oslcompiler->current_typespec (TypeSpec (osllextype ($2), true));
589-
$$ = 0;
633+
typespec_stack.push (oslcompiler->current_typespec ());
634+
$$ = ShadTypeUnknown;
590635
}
591636
| IDENTIFIER /* struct name or shader type name */
592637
{
@@ -601,9 +646,10 @@ typespec_or_shadertype
601646
$$ = ShadTypeVolume;
602647
else {
603648
Symbol *s = oslcompiler->symtab().find (name);
604-
if (s && s->is_structure())
649+
if (s && s->is_structure()) {
605650
oslcompiler->current_typespec (TypeSpec ("", s->typespec().structure()));
606-
else {
651+
typespec_stack.push (oslcompiler->current_typespec ());
652+
} else {
607653
oslcompiler->current_typespec (TypeSpec (TypeDesc::UNKNOWN));
608654
oslcompiler->error (oslcompiler->filename(),
609655
oslcompiler->lineno(),

src/liboslcomp/typecheck.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -912,6 +912,9 @@ TypeSpec
912912
ASTfunction_call::typecheck_all_poly (TypeSpec expected, bool coerceargs,
913913
bool equivreturn)
914914
{
915+
if (m_name == "custom_method1")
916+
m_name = "custom_method1";
917+
915918
for (FunctionSymbol *poly = func(); poly; poly = poly->nextpoly()) {
916919
const char *code = poly->argcodes().c_str();
917920
int advance;

testsuite/function-method/ref/out.txt

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,26 @@
1-
test.osl:16: warning: argument "f" shadows a field with the same name
2-
test.osl:22: warning: argument "f" shadows a field with the same name
3-
test.osl:27: warning: "f" shadows a field with the same name
1+
test.osl:13: warning: argument "f" shadows a field with the same name
2+
test.osl:19: warning: argument "f" shadows a field with the same name
3+
test.osl:36: warning: "f" shadows a field with the same name
44
Compiled test.osl -> test.oso
55
emethod::test: (42) (2)
66
emethod::test: (42) (46)
77
emethod::testchain: 28
88
emethod::testchain: 24
99
emethod::testchain: 16
1010
emethod::testchain: 0
11+
emethod::predecl: (40) (40) (2)
1112
emethod::shadowed: (40) (3.14)
1213
emethod::shadowed2: 40 22.4 6.28
1314
emethod::shadowed: (40) (6.28)
1415
unshadowed 5
1516
unshadowed *
17+
custom_method0(c{1 1 1})
18+
custom_method0(v{2 2 2})
19+
custom_method1(c{1 1 1}, c{3 3 3})
20+
c.custom_method1 = 4 4 4
21+
custom_method1(v{2 2 2}, f2)
22+
vo = 4 4 4
23+
custom_method3: 101 2 3
24+
c1.custom_method3: 34 (101 2 3)
25+
custom_method3: 101 1 1
1626

testsuite/function-method/test.osl

Lines changed: 62 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
void unshadowed(int i) { printf("unshadowed %d\n", i); }
2-
void unshadowed() { printf("unshadowed *\n"); }
3-
41
struct emethod {
52
float f;
63

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

26-
float shadowed2(float ff) {
27-
float f = 32.4;
28-
f -= 10;
29-
printf("emethod::shadowed2: %g %g %g\n", this.f, f, ff);
30-
shadowed(ff);
31-
unshadowed(5);
32-
unshadowed();
33-
return f;
34-
}
23+
vector predecl(float ff);
3524
};
3625

26+
vector emethod::predecl(float ff) {
27+
f -= ff;
28+
printf("emethod::predecl: (%g) (%g) (%g)\n", this.f, f, ff);
29+
return vector(6,7,8);
30+
}
31+
32+
void unshadowed(int i) { printf("unshadowed %d\n", i); }
33+
void unshadowed() { printf("unshadowed *\n"); }
34+
35+
float emethod::shadowed2(float ff) {
36+
float f = 32.4;
37+
f -= 10;
38+
printf("emethod::shadowed2: %g %g %g\n", this.f, f, ff);
39+
shadowed(ff);
40+
unshadowed(5);
41+
unshadowed();
42+
return f;
43+
}
44+
45+
float color::custom_method3(color c, color b) [[ string description = "MB" ]] {
46+
this[0] += 100;
47+
printf("custom_method3: %g\n", this);
48+
return this[1] + 32.0;
49+
}
50+
51+
color custom_method0(color c) {
52+
printf("custom_method0(c{%g})\n", c);
53+
return c;
54+
}
55+
56+
vector custom_method0(vector v) {
57+
printf("custom_method0(v{%g})\n", v);
58+
return v;
59+
}
60+
61+
color custom_method1(color c, color b) {
62+
printf("custom_method1(c{%g}, c{%g})\n", c, b);
63+
return c + b;
64+
}
65+
66+
vector custom_method1(vector v, float b) {
67+
printf("custom_method1(v{%g}, f%g)\n", v, b);
68+
return v + vector(b);
69+
}
3770

3871
shader test ()
3972
{
4073
emethod e = { 42 };
4174
e.test(2);
4275
e.test2(2);
4376
emethod(2+4+8+16).testchain(2).testchain(4).testchain(8).testchain(16);
44-
e.f -= 2;
77+
e.predecl(2.0);
4578
e.shadowed(3.14);
4679
e.shadowed2(6.28);
80+
81+
color c = 1;
82+
vector vo = 2;
83+
84+
c.custom_method0();
85+
vo.custom_method0();
86+
87+
printf("c.custom_method1 = %g\n", c.custom_method1(color(3)));
88+
89+
vo = vo.custom_method1(2.0);
90+
printf("vo = %g\n", vo);
91+
92+
color c1 = color(1,2,3);
93+
printf("c1.custom_method3: %g (%g)\n", c1.custom_method3(c,c), c1);
94+
95+
custom_method3(c,c,c);
4796
}

0 commit comments

Comments
 (0)