Commit 66d70ca82dd2f9ac31ba81771d187a69b1051874

Authored by Andreas Rumpf
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 =
... ...