diff --git a/src/squeaknim.nim b/src/squeaknim.nim index 410e9e4..271a963 100644 --- a/src/squeaknim.nim +++ b/src/squeaknim.nim @@ -88,24 +88,33 @@ template writeExternalLibrary*() = "!$1 class methodsFor: 'primitives' stamp: 'SqueakNim'!\C", gPrefix & capitalize(dllName), capitalize(dllName)) -template writeSmallTalkCode*(filename: string) = - ## You need to invoke this template to write the produced SmallTalk code to +template writeSmalltalkCode*(filename: string) = + ## You need to invoke this template to write the produced Smalltalk code to ## a file. static: writeFile(filename, stCode) -proc mapTypeToC(symbolicType: NimNode): string {.compileTime.} = - if symbolicType.kind == nnkEmpty: return "void" +proc mapTypeToC(symbolicType: NimNode; isResultType: bool): string {.compileTime.} = + if symbolicType.kind == nnkEmpty and isResultType: return "void" let t = symbolicType.getType if symbolicType.kind == nnkSym and t.typeKind == ntyObject: return gPrefix & $symbolicType case t.typeKind of ntyPtr, ntyVar: + if t.typeKind == ntyVar and isResultType: + quit "cannot wrap 'var T' as a result type" expectKind t, nnkBracketExpr - result = mapTypeToC(t[1]) & "*" + let base = t[1] + if base.getType.typeKind == ntyArray: + expectKind base, nnkBracketExpr + result = mapTypeToC(base[2], isResultType) & "*" + else: + result = mapTypeToC(base, isResultType) & "*" of ntyArray: + if isResultType: + quit "cannot wrap array as a result type" expectKind t, nnkBracketExpr - result = mapTypeToC(t[2]) & "*" + result = mapTypeToC(t[2], isResultType) & "*" of ntyCString: result = "char*" of ntyPointer: result = "void*" of ntyInt: result = intType @@ -145,7 +154,7 @@ macro exportSt*(body: stmt): stmt = else: st.add(": " & ident) # return type: - var apicall = " 0: apicall.add(" ") st.addf(" $1: $1", name) - apicall.add(mapTypeToC(typ)) + apicall.add(mapTypeToC(typ, false)) inc counter apicall.add(") module: '" & dllName & "'>\C" & "\t^self externalCallFailed\C!\C\C") stCode.add(st & "\C\t\"Generated by NimSqueak\"\C\t" & apicall) -macro wrapObject*(typ: stmt): stmt = - ## Declares a SmallTalk wrapper class. +macro wrapObject*(typ: stmt; wrapFields=false): stmt = + ## Declares a Smalltalk wrapper class. var t = typ.getType() if t.typeKind == ntyTypeDesc: expectKind t, nnkBracketExpr @@ -177,9 +186,10 @@ macro wrapObject*(typ: stmt): stmt = t = t[1] expectKind t, nnkRecList var fields = "" - for i in 0.. < t.len: - expectKind t[i], nnkSym - fields.addf "\t\t($# '$#')\C", $t[i], mapTypeToC(t[i]) + if $wrapFields == "true": + for i in 0.. < t.len: + expectKind t[i], nnkSym + fields.addf "\t\t($# '$#')\C", $t[i], mapTypeToC(t[i], false) let st = ("ExternalStructure subclass: #$1\C" & "\tinstanceVariableNames: ''\C" & diff --git a/tests/Test1.nim b/tests/Test1.nim index 71e7a71..76dcf7b 100644 --- a/tests/Test1.nim +++ b/tests/Test1.nim @@ -29,4 +29,4 @@ proc foo*(a, b: Vector3, c: int): cstring {.exportSt.} = result = "x plus y plus c " & $(a.x + b.y + c.float) # Write the Smalltalk code to file -writeSmallTalkCode("Test1.st") +writeSmalltalkCode("Test1.st")