-
Notifications
You must be signed in to change notification settings - Fork 226
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add 'importbin' statement #584
Conversation
linter/internal/types/build_graph.go
Outdated
@@ -217,6 +217,8 @@ func calcTP(node ast.Node, varAt map[ast.Node]*common.Variable, g *typeGraph) ty | |||
return tpRef(g.getExprPlaceholder(imported)) | |||
case *ast.ImportStr: | |||
return tpRef(stringType) | |||
case *ast.ImportBin: | |||
return tpRef(anyArrayType) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wasn't confident on this line - is this correct? Is there a better value to return?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's correct, but it would be better to return an array of numbers specifically. We can add another hardcoded type for this (alongside anyArrayType):
- Here you can add a new type id:
anyArrayType - Here you actually define it:
go-jsonnet/linter/internal/types/graph.go
Line 131 in 74b3a1b
g._placeholders[anyArrayType] = concreteTP(TypeDesc{ - Here's another place which could benefit from it:
arrayOfNumber := anyArrayType
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the hints. Added numberArrayType
and a testcase.
Good stuff. We need C++ support before documenting this, but it's not a blocker for merging this here. |
Strategically, I'm tempted to say we could merge this without C++ support and document that as an explicit limitation of the C++ implementation. What do you think? |
return *c.data | ||
} | ||
|
||
// MakeContents creates Contents from a string. | ||
func MakeContents(s string) Contents { | ||
data := []byte(s) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It suddenly occurred to me that this probably breaks the 'repeated MakeContents(foo) produces the exact same Contents' rule. Might need to change the Contents representation to store both a []byte pointer and a string pointer, or improve the 'is the same' check.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
False alarm? I think there's no problem here, and we're good to proceed.
More info: I think we get a different Contents
even when called with the same string, ie:
foo := "foo"
a, b := MakeContents(foo), MakeContents(foo)
a != b
... because of the above line of code ... but afaics this is ok.
Afaics the intended semantics (enforced by importCache.importData()
) are that Importer.Import
returns a copy of the same Contents
object for the same foundAt
value -- not a new Contents
object made from the same string (subtle difference).
ie: Importer.Import() is meant to do this:
// Good example
func (i *myimporter) ImportData(from, path string) (contents Contents, foundAt string, err error) {
foundAt = i.resolvePath(from, path)
if contents = i.cache[foundAt]; contents == nil {
contents = MakeContents(i.readContents(foundAt))
// Important! Return (a copy of) the same `Contents` for a given `foundAt`
i.cache[foundAt] = contents
}
return
}
Not this:
// Wrong/bad example
func (i *myimporter) ImportData(from, path string) (contents Contents, foundAt string, err error) {
foundAt = i.resolvePath(from, path)
var stringData string
if stringData, ok = i.dataCache[foundAt]; !ok {
stringData = i.readContents(foundAt)
i.dataCache[foundAt] = stringData
}
// Wrong! Now we have a 'new' Contents object for the same `foundAt`
contents = MakeContents(stringData)
return
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, exactly. We enforce that it's the same Contents object.
(It encourages efficient caching by avoiding unnecessary copies and we can quickly compare pointers for equality instead of going over the whole string).
Here are the options I see: |
Add `importbin` statement. Similar to `importstr` but the result is an array of numbers (all integers 0-255).
Add `numberArrayType` specialised type for cases where we know we have an array of numbers. Use in some stdlib functions and `importbin`.
C++ PR: google/jsonnet#976 I note there's a Rust PR already in flight too CertainLach/jrsonnet#77. The Rust implementation looks very nice. As a long-term support plan, I vote for dropping the C++ library in favour of the Rust-produced C bindings. We can discuss which project (go or Rust) produces the 'official' /usr/bin/jsonnet CLI tool. |
Add
importbin
statement. Similar toimportstr
but the result is an array of numbers (all integers 0-255).