{"id":9,"date":"2014-09-20T03:11:42","date_gmt":"2014-09-20T03:11:42","guid":{"rendered":"http:\/\/www.voidbred.com\/blog\/?p=9"},"modified":"2014-09-20T03:11:42","modified_gmt":"2014-09-20T03:11:42","slug":"implementing-objective-c-message-calling-in-nimrod-with-macros","status":"publish","type":"post","link":"http:\/\/www.voidbred.com\/blog\/2014\/09\/implementing-objective-c-message-calling-in-nimrod-with-macros\/","title":{"rendered":"Implementing Objective-C Message Calling in Nimrod With Macros"},"content":{"rendered":"<p>Okay, so our goal here is to add support for Objective-C from Nimrod.\u00a0 We&#8217;d like to be able to allocate and use Objective-C objects.\u00a0 So the way that Nimrod works, at least the parts we are interested in, is that first it does some lexer\/parser magic then creates an Abstract Syntax Tree, then from that tree it generates C code, then it runs the C code through a C compiler to generate a binary.<\/p>\n<p>There are a couple ways we could interface with Objective-C (objc).\u00a0 We could just ignore objc syntax and interface directly with the C interface to the runtime.\u00a0 We could be doing things like calling the C objc_msgSend function ourselves.\u00a0 Or we could find a way to inject objc syntax into our generated C source files and instead compile with an objc compiler.\u00a0 We&#8217;ll opt for the latter because in the future it would be neat to be able to define objc classes in Nimrod and it will be easier to debug if we are using the language directly instead of just tons of C function calls into the runtime.<\/p>\n<p>The first thing we&#8217;ll want to do is change from compiling with a C compiler to an objc compiler.\u00a0 Since objc is a super-set of C that should be easy to change and still be able to produce a valid binary.\u00a0 Luckily the Nimrod compiler has a flag that allows us to do this easily, namely &#8220;nimrod objc &lt;filename&gt;&#8221; instead of &#8220;nimrod c &lt;filename&gt;&#8221;.\u00a0 This makes the resulting code file be named with the &#8220;.m&#8221; suffix and be compiled with an objc compiler.<\/p>\n<p>Okay, now we are exporting objc code, now lets try to inject some objc code into the resulting .m file.\u00a0 Here again Nimrod provides us with a tool to do that with the <em>emit <\/em>pragma.\u00a0 {.emit: &#8220;&lt;code&gt;&#8221;.} sends code verbatim to the resulting file.\u00a0 The authors of Nimrod (Araq) put it in the langauge for exactly this purpose, interfacing with other C&#8217;ish languages.<\/p>\n<p>One thing to note about Nimrod is that while it allows macros on the AST it doesn&#8217;t allow us to use reader macros like common-lisp does.\u00a0 So we are stuck with the guidelines of the Nimrod language.\u00a0 It will be impossible to make &#8220;[NSDictionary alloc]&#8221; make sense in Nimrod because it would think that is an array and would be looking for the comma between NSDictionary and alloc.\u00a0 Also since the brackets already mean something we&#8217;ll need something special to distinguish objc message calls from arrays (eg [1,2,3,4,5]).\u00a0 I decided to use the syntax &#8220;o[NSDictionary, alloc]&#8221; to mean &#8220;[NSDictionary alloc]&#8221;\u00a0 Because of the prefix &#8216;o&#8217; literal we can hunt out the difference between an array and an objc message send.<\/p>\n<p>What I ended up doing was creating a Nimrod method that works on a statement, which is one or more expressions.\u00a0 That way it can crawl its way down the AST and perform manipulations to convert arrays prefixed with &#8216;o&#8217; into emit pragmas with the corresponding objc code.<\/p>\n<p>Here is a link to the code as it stands now: <a title=\"callobjc\" href=\"https:\/\/github.com\/clarkeaa\/nimrod-examples\/blob\/066879ca9d37d48772181aef9d2bf2366a21590c\/callobjc\/callobjc.nim\" target=\"_blank\">callobjc<\/a><\/p>\n<p>Notes on understanding the code:<\/p>\n<ul>\n<li>Recursive expansion of objc message sends don&#8217;t exist yet.\u00a0 Check out head it may be done by now.\u00a0 That&#8217;s why you see messages <em>alloc<\/em> and <em>init<\/em> on separate lines instead of idiomatic objc on the same line.<\/li>\n<li>{.compileTime.} pragma allows functions to be usable by macros<\/li>\n<li>macros operate on <span class=\"n\">PNimrodNode<\/span> which can be interchangeable with <em>stmt<\/em> and <em>expr<\/em> types.\u00a0 I don&#8217;t believe there are any static checks to verify that something is in fact a <em>stmt<\/em> vs <em>expr<\/em>.<\/li>\n<li>the combo of getAST(&lt;some template call&gt;) is shortcut to avoid building an AST by hand<\/li>\n<li>literals that prefix [] operators become children of the bracket operation.\u00a0 I found this out by using the lispRepr proc which is indispensable when developing macros in Nimrod.<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Okay, so our goal here is to add support for Objective-C from Nimrod.\u00a0 We&#8217;d like to be able to allocate and use Objective-C objects.\u00a0 So the way that Nimrod works, at least the parts we are interested in, is that first it does some lexer\/parser magic then creates an Abstract Syntax Tree, then from that&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[3,4],"_links":{"self":[{"href":"http:\/\/www.voidbred.com\/blog\/wp-json\/wp\/v2\/posts\/9"}],"collection":[{"href":"http:\/\/www.voidbred.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.voidbred.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.voidbred.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.voidbred.com\/blog\/wp-json\/wp\/v2\/comments?post=9"}],"version-history":[{"count":3,"href":"http:\/\/www.voidbred.com\/blog\/wp-json\/wp\/v2\/posts\/9\/revisions"}],"predecessor-version":[{"id":12,"href":"http:\/\/www.voidbred.com\/blog\/wp-json\/wp\/v2\/posts\/9\/revisions\/12"}],"wp:attachment":[{"href":"http:\/\/www.voidbred.com\/blog\/wp-json\/wp\/v2\/media?parent=9"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.voidbred.com\/blog\/wp-json\/wp\/v2\/categories?post=9"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.voidbred.com\/blog\/wp-json\/wp\/v2\/tags?post=9"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}