From 8594b6e2a94d470fc93e76ca3ac4619d0167f046 Mon Sep 17 00:00:00 2001 From: James Shubin Date: Wed, 21 Aug 2024 19:00:51 -0400 Subject: [PATCH] lang: funcs: Hint the struct_lookup functions better If we have static information, use it to help unification. --- lang/funcs/struct_lookup_func.go | 10 ++++++++++ lang/funcs/struct_lookup_optional_func.go | 10 ++++++++++ .../TestAstFunc2/structlookup3.txtar | 15 +++++++++++++++ 3 files changed, 35 insertions(+) create mode 100644 lang/interpret_test/TestAstFunc2/structlookup3.txtar diff --git a/lang/funcs/struct_lookup_func.go b/lang/funcs/struct_lookup_func.go index d63bac75..359b18bc 100644 --- a/lang/funcs/struct_lookup_func.go +++ b/lang/funcs/struct_lookup_func.go @@ -125,6 +125,16 @@ func (obj *StructLookupFunc) FuncInfer(partialType *types.Type, partialValues [] // This can happen at runtime too, but we save it here for Build()! obj.field = s // store for later + // Figure out more about the sig if any information is known statically. + if len(partialType.Ord) > 0 && partialType.Map[partialType.Ord[0]] != nil { + obj.Type = partialType.Map[partialType.Ord[0]] // assume this + if obj.Type.Kind == types.KindStruct && obj.Type.Map != nil { + if typ, exists := obj.Type.Map[s]; exists { + obj.Out = typ + } + } + } + // This isn't precise enough because we must guarantee that the field is // in the struct and that ?1 is actually a struct, but that's okay it is // something that we'll verify at build time! diff --git a/lang/funcs/struct_lookup_optional_func.go b/lang/funcs/struct_lookup_optional_func.go index 4c8c6f5b..a1176dc4 100644 --- a/lang/funcs/struct_lookup_optional_func.go +++ b/lang/funcs/struct_lookup_optional_func.go @@ -132,6 +132,16 @@ func (obj *StructLookupOptionalFunc) FuncInfer(partialType *types.Type, partialV // This can happen at runtime too, but we save it here for Build()! //obj.field = s // don't store for this optional lookup version! + // Figure out more about the sig if any information is known statically. + if len(partialType.Ord) > 0 && partialType.Map[partialType.Ord[0]] != nil { + obj.Type = partialType.Map[partialType.Ord[0]] // assume this + if obj.Type.Kind == types.KindStruct && obj.Type.Map != nil { + if typ, exists := obj.Type.Map[s]; exists { + obj.Out = typ + } + } + } + // This isn't precise enough because we must guarantee that the field is // in the struct and that ?1 is actually a struct, but that's okay it is // something that we'll verify at build time! (Or skip it for optional!) diff --git a/lang/interpret_test/TestAstFunc2/structlookup3.txtar b/lang/interpret_test/TestAstFunc2/structlookup3.txtar new file mode 100644 index 00000000..f6917fe4 --- /dev/null +++ b/lang/interpret_test/TestAstFunc2/structlookup3.txtar @@ -0,0 +1,15 @@ +-- main.mcl -- +import "fmt" + +$st = struct{ + field1 => "value1", + field2 => "value2", +} + +class test_struct_lookup($v1, $v2) { + test "test-${v1}-${v2}" {} +} + +include test_struct_lookup($st->field1, $st->field2) +-- OUTPUT -- +Vertex: test[test-value1-value2]