Skip to content

Commit 0531579

Browse files
committed
Allow external method definitions in the style of C++.
1 parent ca27778 commit 0531579

File tree

3 files changed

+129
-24
lines changed

3 files changed

+129
-24
lines changed

src/liboslcomp/oslgram.y

+54-8
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
{
@@ -220,6 +220,49 @@ shader_or_function_declaration
220220
}
221221
;
222222

223+
method_declaration
224+
: typespec_or_shadertype typespec ':' ':' IDENTIFIER
225+
{
226+
// It's a method declaration, not a shader
227+
if ($1 != ShadTypeUnknown || typespec_stack.empty() ||
228+
(! oslcompiler->current_typespec().is_structure() &&
229+
! oslcompiler->current_typespec().is_triple())) {
230+
oslcompiler->error (oslcompiler->filename(),
231+
oslcompiler->lineno(),
232+
"Cannot declare a method for this type");
233+
}
234+
235+
oslcompiler->symtab().push (); // new scope
236+
typespec_stack.push (oslcompiler->current_typespec());
237+
}
238+
'(' formal_params_opt ')' metadata_block_opt
239+
{
240+
implicit_this = new ASTvariable_declaration(oslcompiler,
241+
typespec_stack.top(),
242+
$8);
243+
typespec_stack.pop ();
244+
$<n>$ = implicit_this.get();
245+
}
246+
function_body_or_just_decl
247+
{
248+
// Method declaration
249+
ASSERT ($1 == ShadTypeUnknown);
250+
oslcompiler->symtab().pop (); // restore scope
251+
ASTfunction_declaration *f;
252+
f = new ASTfunction_declaration (oslcompiler,
253+
typespec_stack.top(),
254+
ustring($5),
255+
$<n>11 /*arguments*/,
256+
$12 /*statements*/,
257+
$10 /*meta*/);
258+
implicit_this = nullptr;
259+
typespec_stack.pop ();
260+
oslcompiler->remember_function_decl (f);
261+
f->sourceline (@2.first_line);
262+
$$ = f;
263+
}
264+
;
265+
223266
formal_params_opt
224267
: formal_params
225268
| /* empty */ { $$ = 0; }
@@ -586,12 +629,14 @@ typespec_or_shadertype
586629
: simple_typename
587630
{
588631
oslcompiler->current_typespec (TypeSpec (osllextype ($1)));
589-
$$ = 0;
632+
typespec_stack.push (oslcompiler->current_typespec ());
633+
$$ = ShadTypeUnknown;
590634
}
591635
| CLOSURE simple_typename
592636
{
593637
oslcompiler->current_typespec (TypeSpec (osllextype ($2), true));
594-
$$ = 0;
638+
typespec_stack.push (oslcompiler->current_typespec ());
639+
$$ = ShadTypeUnknown;
595640
}
596641
| IDENTIFIER /* struct name or shader type name */
597642
{
@@ -606,9 +651,10 @@ typespec_or_shadertype
606651
$$ = ShadTypeVolume;
607652
else {
608653
Symbol *s = oslcompiler->symtab().find (name);
609-
if (s && s->is_structure())
654+
if (s && s->is_structure()) {
610655
oslcompiler->current_typespec (TypeSpec ("", s->typespec().structure()));
611-
else {
656+
typespec_stack.push (oslcompiler->current_typespec ());
657+
} else {
612658
oslcompiler->current_typespec (TypeSpec (TypeDesc::UNKNOWN));
613659
oslcompiler->error (oslcompiler->filename(),
614660
oslcompiler->lineno(),

testsuite/function-method/ref/out.txt

+13-3
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

+62-13
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)