Commit 0dff195779e5a8b7e5f9f6d278a2c4a6a2cebb7b
Merge branch 'master' of gitlab.3dicc.com:3dicc/squeaknim
Showing
2 changed files
with
24 additions
and
14 deletions
src/squeaknim.nim
@@ -88,24 +88,33 @@ template writeExternalLibrary*() = | @@ -88,24 +88,33 @@ template writeExternalLibrary*() = | ||
88 | "!$1 class methodsFor: 'primitives' stamp: 'SqueakNim'!\C", | 88 | "!$1 class methodsFor: 'primitives' stamp: 'SqueakNim'!\C", |
89 | gPrefix & capitalize(dllName), capitalize(dllName)) | 89 | gPrefix & capitalize(dllName), capitalize(dllName)) |
90 | 90 | ||
91 | -template writeSmallTalkCode*(filename: string) = | ||
92 | - ## You need to invoke this template to write the produced SmallTalk code to | 91 | +template writeSmalltalkCode*(filename: string) = |
92 | + ## You need to invoke this template to write the produced Smalltalk code to | ||
93 | ## a file. | 93 | ## a file. |
94 | static: | 94 | static: |
95 | writeFile(filename, stCode) | 95 | writeFile(filename, stCode) |
96 | 96 | ||
97 | -proc mapTypeToC(symbolicType: NimNode): string {.compileTime.} = | ||
98 | - if symbolicType.kind == nnkEmpty: return "void" | 97 | +proc mapTypeToC(symbolicType: NimNode; isResultType: bool): string {.compileTime.} = |
98 | + if symbolicType.kind == nnkEmpty and isResultType: return "void" | ||
99 | let t = symbolicType.getType | 99 | let t = symbolicType.getType |
100 | if symbolicType.kind == nnkSym and t.typeKind == ntyObject: | 100 | if symbolicType.kind == nnkSym and t.typeKind == ntyObject: |
101 | return gPrefix & $symbolicType | 101 | return gPrefix & $symbolicType |
102 | case t.typeKind | 102 | case t.typeKind |
103 | of ntyPtr, ntyVar: | 103 | of ntyPtr, ntyVar: |
104 | + if t.typeKind == ntyVar and isResultType: | ||
105 | + quit "cannot wrap 'var T' as a result type" | ||
104 | expectKind t, nnkBracketExpr | 106 | expectKind t, nnkBracketExpr |
105 | - result = mapTypeToC(t[1]) & "*" | 107 | + let base = t[1] |
108 | + if base.getType.typeKind == ntyArray: | ||
109 | + expectKind base, nnkBracketExpr | ||
110 | + result = mapTypeToC(base[2], isResultType) & "*" | ||
111 | + else: | ||
112 | + result = mapTypeToC(base, isResultType) & "*" | ||
106 | of ntyArray: | 113 | of ntyArray: |
114 | + if isResultType: | ||
115 | + quit "cannot wrap array as a result type" | ||
107 | expectKind t, nnkBracketExpr | 116 | expectKind t, nnkBracketExpr |
108 | - result = mapTypeToC(t[2]) & "*" | 117 | + result = mapTypeToC(t[2], isResultType) & "*" |
109 | of ntyCString: result = "char*" | 118 | of ntyCString: result = "char*" |
110 | of ntyPointer: result = "void*" | 119 | of ntyPointer: result = "void*" |
111 | of ntyInt: result = intType | 120 | of ntyInt: result = intType |
@@ -145,7 +154,7 @@ macro exportSt*(body: stmt): stmt = | @@ -145,7 +154,7 @@ macro exportSt*(body: stmt): stmt = | ||
145 | else: | 154 | else: |
146 | st.add(": " & ident) | 155 | st.add(": " & ident) |
147 | # return type: | 156 | # return type: |
148 | - var apicall = "<cdecl: " & mapTypeToC(params[0]) & " '" & | 157 | + var apicall = "<cdecl: " & mapTypeToC(params[0], true) & " '" & |
149 | procName & "' (" | 158 | procName & "' (" |
150 | var counter = 0 | 159 | var counter = 0 |
151 | # parameter types: | 160 | # parameter types: |
@@ -158,14 +167,14 @@ macro exportSt*(body: stmt): stmt = | @@ -158,14 +167,14 @@ macro exportSt*(body: stmt): stmt = | ||
158 | if counter > 0: | 167 | if counter > 0: |
159 | apicall.add(" ") | 168 | apicall.add(" ") |
160 | st.addf(" $1: $1", name) | 169 | st.addf(" $1: $1", name) |
161 | - apicall.add(mapTypeToC(typ)) | 170 | + apicall.add(mapTypeToC(typ, false)) |
162 | inc counter | 171 | inc counter |
163 | apicall.add(") module: '" & dllName & "'>\C" & | 172 | apicall.add(") module: '" & dllName & "'>\C" & |
164 | "\t^self externalCallFailed\C!\C\C") | 173 | "\t^self externalCallFailed\C!\C\C") |
165 | stCode.add(st & "\C\t\"Generated by NimSqueak\"\C\t" & apicall) | 174 | stCode.add(st & "\C\t\"Generated by NimSqueak\"\C\t" & apicall) |
166 | 175 | ||
167 | -macro wrapObject*(typ: stmt): stmt = | ||
168 | - ## Declares a SmallTalk wrapper class. | 176 | +macro wrapObject*(typ: stmt; wrapFields=false): stmt = |
177 | + ## Declares a Smalltalk wrapper class. | ||
169 | var t = typ.getType() | 178 | var t = typ.getType() |
170 | if t.typeKind == ntyTypeDesc: | 179 | if t.typeKind == ntyTypeDesc: |
171 | expectKind t, nnkBracketExpr | 180 | expectKind t, nnkBracketExpr |
@@ -177,9 +186,10 @@ macro wrapObject*(typ: stmt): stmt = | @@ -177,9 +186,10 @@ macro wrapObject*(typ: stmt): stmt = | ||
177 | t = t[1] | 186 | t = t[1] |
178 | expectKind t, nnkRecList | 187 | expectKind t, nnkRecList |
179 | var fields = "" | 188 | var fields = "" |
180 | - for i in 0.. < t.len: | ||
181 | - expectKind t[i], nnkSym | ||
182 | - fields.addf "\t\t($# '$#')\C", $t[i], mapTypeToC(t[i]) | 189 | + if $wrapFields == "true": |
190 | + for i in 0.. < t.len: | ||
191 | + expectKind t[i], nnkSym | ||
192 | + fields.addf "\t\t($# '$#')\C", $t[i], mapTypeToC(t[i], false) | ||
183 | 193 | ||
184 | let st = ("ExternalStructure subclass: #$1\C" & | 194 | let st = ("ExternalStructure subclass: #$1\C" & |
185 | "\tinstanceVariableNames: ''\C" & | 195 | "\tinstanceVariableNames: ''\C" & |
tests/Test1.nim
@@ -29,4 +29,4 @@ proc foo*(a, b: Vector3, c: int): cstring {.exportSt.} = | @@ -29,4 +29,4 @@ proc foo*(a, b: Vector3, c: int): cstring {.exportSt.} = | ||
29 | result = "x plus y plus c " & $(a.x + b.y + c.float) | 29 | result = "x plus y plus c " & $(a.x + b.y + c.float) |
30 | 30 | ||
31 | # Write the Smalltalk code to file | 31 | # Write the Smalltalk code to file |
32 | -writeSmallTalkCode("Test1.st") | 32 | +writeSmalltalkCode("Test1.st") |