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 | 62 | const |
| 5 | 63 | pragmaPos = 4 |
| ... | ... | @@ -29,7 +87,7 @@ template writeExternalLibrary*() = |
| 29 | 87 | category: '$1'! |
| 30 | 88 | |
| 31 | 89 | !$1 class methodsFor: 'primitives' stamp: 'SqueakNim'! |
| 32 | -""", capitalize(dllName)) | |
| 90 | +""", gPrefix & capitalize(dllName)) | |
| 33 | 91 | |
| 34 | 92 | template writeSmallTalkCode*(filename: string) = |
| 35 | 93 | ## You need to invoke this template to write the produced SmallTalk code to |
| ... | ... | @@ -72,7 +130,11 @@ macro exportSt*(body: stmt): stmt = |
| 72 | 130 | # <apicall: long 'system' (char*) module: 'libSystem.dylib'> |
| 73 | 131 | # ^self externalCallFailed. |
| 74 | 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 | 138 | let params = result[paramPos] |
| 77 | 139 | let procName = $result[0] |
| 78 | 140 | var st = procName |
| ... | ... | @@ -101,7 +163,7 @@ macro exportSt*(body: stmt): stmt = |
| 101 | 163 | apicall.add(mapTypeToC(typ)) |
| 102 | 164 | inc counter |
| 103 | 165 | apicall.add(") module: '" & dllName & "'>\n" & |
| 104 | - "\t^self externalCallFailed.\n") | |
| 166 | + "\t^self externalCallFailed.\n!\n\n") | |
| 105 | 167 | stCode.add(st & "\n\t\"Generated by NimSqueak\"\n\t" & apicall) |
| 106 | 168 | |
| 107 | 169 | macro wrapObject*(typ: stmt): stmt = | ... | ... |