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