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 = | ... | ... |