Commit 66d70ca82dd2f9ac31ba81771d187a69b1051874
1 parent
e95712ca
squeaknim doesn't depend on strutils anymore; generates proper sections
Showing
1 changed file
with
66 additions
and
4 deletions
src/squeaknim.nim
| 1 | 1 | ||
| 2 | -import macros, strutils | 2 | +import macros |
| 3 | +# Note: Since we combine -d:useNimRtl with this module, we cannot use strutils. | ||
| 4 | +# So we use our own helper procs here: | ||
| 5 | + | ||
| 6 | +proc toUpper(c: char): char = | ||
| 7 | + result = if c in {'a'..'z'}: chr(c.ord - 'a'.ord + 'A'.ord) else: c | ||
| 8 | + | ||
| 9 | +proc capitalize(s: string): string {.noSideEffect.} = | ||
| 10 | + result = toUpper(s[0]) & substr(s, 1) | ||
| 11 | + | ||
| 12 | +proc invalidFormatString() {.noinline.} = | ||
| 13 | + raise newException(ValueError, "invalid format string") | ||
| 14 | + | ||
| 15 | +proc addf(s: var string, formatstr: string, a: varargs[string, `$`]) = | ||
| 16 | + ## The same as ``add(s, formatstr % a)``, but more efficient. | ||
| 17 | + const PatternChars = {'a'..'z', 'A'..'Z', '0'..'9', '\128'..'\255', '_'} | ||
| 18 | + var i = 0 | ||
| 19 | + var num = 0 | ||
| 20 | + while i < len(formatstr): | ||
| 21 | + if formatstr[i] == '$': | ||
| 22 | + case formatstr[i+1] # again we use the fact that strings | ||
| 23 | + # are zero-terminated here | ||
| 24 | + of '#': | ||
| 25 | + if num >% a.high: invalidFormatString() | ||
| 26 | + add s, a[num] | ||
| 27 | + inc i, 2 | ||
| 28 | + inc num | ||
| 29 | + of '$': | ||
| 30 | + add s, '$' | ||
| 31 | + inc(i, 2) | ||
| 32 | + of '1'..'9', '-': | ||
| 33 | + var j = 0 | ||
| 34 | + inc(i) # skip $ | ||
| 35 | + var negative = formatstr[i] == '-' | ||
| 36 | + if negative: inc i | ||
| 37 | + while formatstr[i] in {'0'..'9'}: | ||
| 38 | + j = j * 10 + ord(formatstr[i]) - ord('0') | ||
| 39 | + inc(i) | ||
| 40 | + let idx = if not negative: j-1 else: a.len-j | ||
| 41 | + if idx >% a.high: invalidFormatString() | ||
| 42 | + add s, a[idx] | ||
| 43 | + else: | ||
| 44 | + invalidFormatString() | ||
| 45 | + else: | ||
| 46 | + add s, formatstr[i] | ||
| 47 | + inc(i) | ||
| 48 | + | ||
| 49 | +proc `%`(formatstr: string, a: openArray[string]): string = | ||
| 50 | + result = newStringOfCap(formatstr.len + a.len shl 4) | ||
| 51 | + addf(result, formatstr, a) | ||
| 52 | + | ||
| 53 | +proc `%`(formatstr, a: string): string = | ||
| 54 | + result = newStringOfCap(formatstr.len + a.len) | ||
| 55 | + addf(result, formatstr, [a]) | ||
| 56 | + | ||
| 57 | +proc format(formatstr: string, a: varargs[string, `$`]): string = | ||
| 58 | + result = newStringOfCap(formatstr.len + a.len) | ||
| 59 | + addf(result, formatstr, a) | ||
| 60 | + | ||
| 3 | 61 | ||
| 4 | const | 62 | const |
| 5 | pragmaPos = 4 | 63 | pragmaPos = 4 |
| @@ -29,7 +87,7 @@ template writeExternalLibrary*() = | @@ -29,7 +87,7 @@ template writeExternalLibrary*() = | ||
| 29 | category: '$1'! | 87 | category: '$1'! |
| 30 | 88 | ||
| 31 | !$1 class methodsFor: 'primitives' stamp: 'SqueakNim'! | 89 | !$1 class methodsFor: 'primitives' stamp: 'SqueakNim'! |
| 32 | -""", capitalize(dllName)) | 90 | +""", gPrefix & capitalize(dllName)) |
| 33 | 91 | ||
| 34 | template writeSmallTalkCode*(filename: string) = | 92 | template writeSmallTalkCode*(filename: string) = |
| 35 | ## You need to invoke this template to write the produced SmallTalk code to | 93 | ## You need to invoke this template to write the produced SmallTalk code to |
| @@ -72,7 +130,11 @@ macro exportSt*(body: stmt): stmt = | @@ -72,7 +130,11 @@ macro exportSt*(body: stmt): stmt = | ||
| 72 | # <apicall: long 'system' (char*) module: 'libSystem.dylib'> | 130 | # <apicall: long 'system' (char*) module: 'libSystem.dylib'> |
| 73 | # ^self externalCallFailed. | 131 | # ^self externalCallFailed. |
| 74 | result = body | 132 | result = body |
| 75 | - result[pragmaPos].add(ident"exportc", ident"dynlib", ident"cdecl") | 133 | + when defined(cpp): |
| 134 | + result[pragmaPos].add(ident"exportc", ident"dynlib", ident"cdecl", | ||
| 135 | + newColonExpr(ident"codegenDecl", newLit"""extern "C" $# $#$#""")) | ||
| 136 | + else: | ||
| 137 | + result[pragmaPos].add(ident"exportc", ident"dynlib", ident"cdecl") | ||
| 76 | let params = result[paramPos] | 138 | let params = result[paramPos] |
| 77 | let procName = $result[0] | 139 | let procName = $result[0] |
| 78 | var st = procName | 140 | var st = procName |
| @@ -101,7 +163,7 @@ macro exportSt*(body: stmt): stmt = | @@ -101,7 +163,7 @@ macro exportSt*(body: stmt): stmt = | ||
| 101 | apicall.add(mapTypeToC(typ)) | 163 | apicall.add(mapTypeToC(typ)) |
| 102 | inc counter | 164 | inc counter |
| 103 | apicall.add(") module: '" & dllName & "'>\n" & | 165 | apicall.add(") module: '" & dllName & "'>\n" & |
| 104 | - "\t^self externalCallFailed.\n") | 166 | + "\t^self externalCallFailed.\n!\n\n") |
| 105 | stCode.add(st & "\n\t\"Generated by NimSqueak\"\n\t" & apicall) | 167 | stCode.add(st & "\n\t\"Generated by NimSqueak\"\n\t" & apicall) |
| 106 | 168 | ||
| 107 | macro wrapObject*(typ: stmt): stmt = | 169 | macro wrapObject*(typ: stmt): stmt = |