|
9 | 9 |
|
10 | 10 | namespace Slang
|
11 | 11 | {
|
| 12 | + |
| 13 | + /// Should the given `decl` nested in `parentDecl` be treated as a static rather than instance declaration? |
| 14 | + bool isEffectivelyStatic( |
| 15 | + Decl* decl, |
| 16 | + ContainerDecl* parentDecl) |
| 17 | + { |
| 18 | + // Things at the global scope are always "members" of their module. |
| 19 | + // |
| 20 | + if(parentDecl->As<ModuleDecl>()) |
| 21 | + return false; |
| 22 | + |
| 23 | + // Anything explicitly marked `static` and not at module scope |
| 24 | + // counts as a static rather than instance declaration. |
| 25 | + // |
| 26 | + if(decl->HasModifier<HLSLStaticModifier>()) |
| 27 | + return true; |
| 28 | + |
| 29 | + // Next we need to deal with cases where a declaration is |
| 30 | + // effectively `static` even if the language doesn't make |
| 31 | + // the user say so. Most languages make the default assumption |
| 32 | + // that nested types are `static` even if they don't say |
| 33 | + // so (Java is an exception here, perhaps due to some |
| 34 | + // influence from the Scandanavian OOP tradition of Beta/gbeta). |
| 35 | + // |
| 36 | + if(dynamic_cast<AggTypeDecl*>(decl)) |
| 37 | + return true; |
| 38 | + if(dynamic_cast<SimpleTypeDecl*>(decl)) |
| 39 | + return true; |
| 40 | + |
| 41 | + // Things nested inside functions may have dependencies |
| 42 | + // on values from the enclosing scope, but this needs to |
| 43 | + // be dealt with via "capture" so they are also effectively |
| 44 | + // `static` |
| 45 | + // |
| 46 | + if(dynamic_cast<FunctionDeclBase*>(parentDecl)) |
| 47 | + return true; |
| 48 | + |
| 49 | + // Type constraint declarations are used in member-reference |
| 50 | + // context as a form of casting operation, so we treat them |
| 51 | + // as if they are instance members. This is a bit of a hack, |
| 52 | + // but it achieves the result we want until we have an |
| 53 | + // explicit representation of up-cast operations in the |
| 54 | + // AST. |
| 55 | + // |
| 56 | + if(decl->As<TypeConstraintDecl>()) |
| 57 | + return false; |
| 58 | + |
| 59 | + return false; |
| 60 | + } |
| 61 | + |
| 62 | + /// Should the given `decl` be treated as a static rather than instance declaration? |
| 63 | + bool isEffectivelyStatic( |
| 64 | + Decl* decl) |
| 65 | + { |
| 66 | + // For the purposes of an ordinary declaration, when determining if |
| 67 | + // it is static or per-instance, the "parent" declaration we really |
| 68 | + // care about is the next outer non-generic declaration. |
| 69 | + // |
| 70 | + // TODO: This idiom of getting the "next outer non-generic declaration" |
| 71 | + // comes up just enough that we should probably have a convenience |
| 72 | + // function for it. |
| 73 | + |
| 74 | + auto parentDecl = decl->ParentDecl; |
| 75 | + if(auto genericDecl = parentDecl->As<GenericDecl>()) |
| 76 | + parentDecl = genericDecl->ParentDecl; |
| 77 | + |
| 78 | + return isEffectivelyStatic(decl, parentDecl); |
| 79 | + } |
| 80 | + |
12 | 81 | // A flat representation of basic types (scalars, vectors and matrices)
|
13 | 82 | // that can be used as lookup key in caches
|
14 | 83 | struct BasicTypeKey
|
@@ -416,6 +485,22 @@ namespace Slang
|
416 | 485 | expr->declRef = declRef;
|
417 | 486 | return expr;
|
418 | 487 | }
|
| 488 | + else if(isEffectivelyStatic(declRef.getDecl())) |
| 489 | + { |
| 490 | + // Extract the type of the baseExpr |
| 491 | + auto baseExprType = baseExpr->type.type; |
| 492 | + RefPtr<SharedTypeExpr> baseTypeExpr = new SharedTypeExpr(); |
| 493 | + baseTypeExpr->base.type = baseExprType; |
| 494 | + baseTypeExpr->type = new TypeType(baseExprType); |
| 495 | + |
| 496 | + auto expr = new StaticMemberExpr(); |
| 497 | + expr->loc = loc; |
| 498 | + expr->type = type; |
| 499 | + expr->BaseExpression = baseTypeExpr; |
| 500 | + expr->name = declRef.GetName(); |
| 501 | + expr->declRef = declRef; |
| 502 | + return expr; |
| 503 | + } |
419 | 504 | else
|
420 | 505 | {
|
421 | 506 | // If the base expression wasn't a type, then this
|
@@ -2246,6 +2331,13 @@ namespace Slang
|
2246 | 2331 | return false;
|
2247 | 2332 | }
|
2248 | 2333 |
|
| 2334 | + if(satisfyingMemberDeclRef.getDecl()->HasModifier<HLSLStaticModifier>() |
| 2335 | + != requiredMemberDeclRef.getDecl()->HasModifier<HLSLStaticModifier>()) |
| 2336 | + { |
| 2337 | + // A `static` method can't satisfy a non-`static` requirement and vice versa. |
| 2338 | + return false; |
| 2339 | + } |
| 2340 | + |
2249 | 2341 | // TODO: actually implement matching here. For now we'll
|
2250 | 2342 | // just pretend that things are satisfied in order to make progress..
|
2251 | 2343 | witnessTable->requirementDictionary.Add(
|
|
0 commit comments