jcburley / gostd2joker Goto Github PK
View Code? Open in Web Editor NEWTemporary repo for prototype tool
Temporary repo for prototype tool
E.g. net.MX
is converted to its underlying type, so the information on MX
itself is lost to the generated Joker code.
So, instead of getting back an array of (pointers/references to) MX
objects, Joker code sees an array of maps with the underlying (struct) type's field names, converted to keywords, as keys.
For quick and dirty low-level conversion, this might be okay at first, but we should think carefully about the long term here to ensure that, if Joker ever does support proper types/classes/objects/etc., either existing Joker code (that references returned objects without regard to formal types) will continue to work, or we'll be okay with "breaking" such code.
(If we wrap the code people care about in higher-level Joker std
wrappers, and support only those, we can change those implementations if and when the underlying interfaces change, and avoid breaking user expectations.)
Currently, gostd2joker
is trying out converting byte
to Byte
, relying on a (largely-untested) branch on my joker
fork to add the Byte
type to Joker.
However, as of this writing, I haven't figured out how to actually construct a value of type Byte
in order to test IPv4
and similar functions.
Either a Byte.
(or new Byte
) or similar constructor is needed, automatic conversion is needed, or -- perhaps the simplest approach, which probably complicates gostd2joker
and/or generate-std.joke
somewhat -- Int
should be used instead.
E.g. a return type of *int
suggests that the underlying value could be changed by Joker code, but currently the generated Joker code basically ignores the *
and returns the underlying type (int
in this case).
In some cases (e.g. the return type for net.LookupMX()
), this is probably okay, as the underlying API is using a pointer just to save some time/space and doesn't seem to offer any utility to its caller changing the copy.
The error
object (as a return value) is now handled specially, so it can be nil
without causing a crash due to being dereferenced to access its .Error()
method.
Other pointers, however, are not checked for nil
before being dereferenced.
In the case of LookupMX
, this is likely not an issue, because none of the pointers in the []*MX
(first) returned value will be nil
(as confirmed by analyzing the code) -- the returned vector itself will be nil
(which is already handled by gostd2joker
) or each element of the array fully populated.
But that might not be the case for all APIs.
No processing/tracking of import
statements (in the Go code being processed) is done.
Therefore, unqualified references to types, functions, etc., are implicitly qualified based on the package
statement for the file (since that's how the code-reading API being used organizes things). Thus, top-level imports (e.g. import ( _ "some-package" )
) won't be searched.
Further, qualified references are treated as referring to the concrete packages to which they'd belong, in the absence of any import
that renames them.
E.g.:
user=> (require '[joker.go.net.mail :as m])
nil
user=> (m/ParseAddress "<[email protected]> James Craig Burley")
panic: runtime error: invalid memory address or nil pointer dereference [recovered]
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x8 pc=0x7b6311]
goroutine 1 [running]:
main.processReplCommand.func1(0xc0006fab40)
/home/craig/.go/src/github.com/candid82/joker/main.go:120 +0x2e5
panic(0x8ea6a0, 0xf2c4f0)
/usr/local/go.1.11.2/src/runtime/panic.go:513 +0x1b9
github.com/candid82/joker/std/go/net/mail.parseAddress(0xc0004d6630, 0x29, 0x1, 0x0)
/home/craig/.go/src/github.com/candid82/joker/std/go/net/mail/mail_native.go:14 +0xe1
github.com/candid82/joker/std/go/net/mail.glob..func1(0xc00076e7d0, 0x1, 0x1, 0xc00076e7d0, 0xc00076e7c0)
/home/craig/.go/src/github.com/candid82/joker/std/go/net/mail/a_mail.go:18 +0x6a
github.com/candid82/joker/core.Proc.Call(0xb4b4e0, 0xc00076e7d0, 0x1, 0x1, 0xc00076e7d0, 0x1)
/home/craig/.go/src/github.com/candid82/joker/core/object.go:739 +0x44
github.com/candid82/joker/core.(*CallExpr).Eval(0xc000852000, 0x0, 0x0, 0x0)
/home/craig/.go/src/github.com/candid82/joker/core/eval.go:274 +0x125
github.com/candid82/joker/core.Eval(0xbbef60, 0xc000852000, 0x0, 0x0, 0x0)
/home/craig/.go/src/github.com/candid82/joker/core/eval.go:107 +0x9b
main.processReplCommand(0xc000629c60, 0x2, 0xc000629c28, 0xc0006fab40, 0x0)
/home/craig/.go/src/github.com/candid82/joker/main.go:146 +0x1e5
main.repl(0x2)
/home/craig/.go/src/github.com/candid82/joker/main.go:180 +0x4a0
main.main()
/home/craig/.go/src/github.com/candid82/joker/main.go:636 +0xa0d
$
E.g. consider this generated-code snippet for net/url
:
func parse(rawurl string) Object {
res1, res2 := url.Parse(rawurl)
res := EmptyVector
map1 := EmptyArrayMap()
map1.Add(MakeKeyword("Scheme"), MakeString((*res1).Scheme))
map1.Add(MakeKeyword("Opaque"), MakeString((*res1).Opaque))
map2 := EmptyArrayMap()
map2.Add(MakeKeyword("username"), MakeString((*(*res1).User).username))
map2.Add(MakeKeyword("password"), MakeString((*(*res1).User).password))
map2.Add(MakeKeyword("passwordSet"), MakeBool((*(*res1).User).passwordSet))
map1.Add(MakeKeyword("User"), map2)
map1.Add(MakeKeyword("Host"), MakeString((*res1).Host))
...
map2
building cannot be compiled because:
# github.com/candid82/joker/std/go/net/url
std/go/net/url/url_native.go:17:62: (*(*res1).User).username undefined (cannot refer to unexported field or method username)
std/go/net/url/url_native.go:18:62: (*(*res1).User).password undefined (cannot refer to unexported field or method password)
std/go/net/url/url_native.go:19:63: (*(*res1).User).passwordSet undefined (cannot refer to unexported field or method passwordSet)
Last I checked, some of the generated *_native.go
code had two copies of code to generate a single returned value.
Investigate.
E.g.:
type A struct {
B *B
}
type B struct {
A *A
}
An example of this is found in http.Request
and http.Response
, which refer to each other (via pointers/references).
When converting named types such as structs, a single function should be emitted to perform any potentially length conversion, and the wrapper functions changed to call that single function.
Consider this code:
func interfaceByIndex(index int) Object {
res1, res2 := net.InterfaceByIndex(index)
res := EmptyVector
map1 := EmptyArrayMap()
map1.Add(MakeKeyword("Index"), MakeInt((*res1).Index))
map1.Add(MakeKeyword("MTU"), MakeInt((*res1).MTU))
map1.Add(MakeKeyword("Name"), MakeString((*res1).Name))
vec2 := EmptyVector
for _, el2 := range (*res1).HardwareAddr {
vec2 = vec2.Conjoin(MakeInt(el2))
}
map1.Add(MakeKeyword("HardwareAddr"), vec2)
map1.Add(MakeKeyword("Flags"), MakeInt((*res1).Flags))
res.Conjoin(map1)
res.Conjoin(string(res2))
return res
}
The block beginning with map1
appears several times in different wrapper functions. It should be implemented in a single function, e.g. func interface(res Interface) (map Object) { ... }
, and called by the above code, e.g. map1 := interface(el1)
. That would probably (unless Go optimizes this away itself) reduce code size noticeably, as more APIs are implemented.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.