Fix #125 - no more types import
This commit is contained in:
parent
4ece07969d
commit
f543124d7e
10 changed files with 99 additions and 88 deletions
|
|
@ -2,4 +2,4 @@
|
|||
The following modules are available to users of Nimterop.
|
||||
]##
|
||||
|
||||
import "."/[docs, cimport, build, types, plugin]
|
||||
import "."/[build, cimport, docs, plugin]
|
||||
|
|
|
|||
|
|
@ -17,8 +17,7 @@ All `{.compileTime.}` procs must be used in a compile time context, e.g. using:
|
|||
|
||||
import hashes, macros, os, strformat, strutils
|
||||
|
||||
import "."/[build, globals, paths, types]
|
||||
export types
|
||||
import "."/[build, globals, paths]
|
||||
|
||||
proc interpPath(dir: string): string=
|
||||
# TODO: more robust: needs a DirSep after "$projpath"
|
||||
|
|
@ -153,7 +152,7 @@ proc getToast(fullpaths: seq[string], recurse: bool = false, dynlib: string = ""
|
|||
|
||||
# see https://github.com/nimterop/nimterop/issues/69
|
||||
(result, ret) = execAction(cmd, die = false, cache = (not gStateCT.nocache),
|
||||
cacheKey = getCacheValue(fullpaths))
|
||||
cacheKey = getCacheValue(toastExe) & getCacheValue(fullpaths))
|
||||
doAssert ret == 0, getToastError(result)
|
||||
|
||||
macro cOverride*(body): untyped =
|
||||
|
|
|
|||
42
nimterop/enumtype.nim
Normal file
42
nimterop/enumtype.nim
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
import macros
|
||||
|
||||
macro defineEnum(typ: untyped): untyped =
|
||||
result = newNimNode(nnkStmtList)
|
||||
|
||||
# Enum mapped to distinct cint
|
||||
result.add quote do:
|
||||
type `typ`* = distinct cint
|
||||
|
||||
for i in ["+", "-", "*", "div", "mod", "shl", "shr", "or", "and", "xor", "<", "<=", "==", ">", ">="]:
|
||||
let
|
||||
ni = newIdentNode(i)
|
||||
typout = if i[0] in "<=>": newIdentNode("bool") else: typ # comparisons return bool
|
||||
if i[0] == '>': # cannot borrow `>` and `>=` from templates
|
||||
let
|
||||
nopp = if i.len == 2: newIdentNode("<=") else: newIdentNode("<")
|
||||
result.add quote do:
|
||||
proc `ni`*(x: `typ`, y: cint): `typout` = `nopp`(y, x)
|
||||
proc `ni`*(x: cint, y: `typ`): `typout` = `nopp`(y, x)
|
||||
proc `ni`*(x, y: `typ`): `typout` = `nopp`(y, x)
|
||||
else:
|
||||
result.add quote do:
|
||||
proc `ni`*(x: `typ`, y: cint): `typout` {.borrow.}
|
||||
proc `ni`*(x: cint, y: `typ`): `typout` {.borrow.}
|
||||
proc `ni`*(x, y: `typ`): `typout` {.borrow.}
|
||||
result.add quote do:
|
||||
proc `ni`*(x: `typ`, y: int): `typout` = `ni`(x, y.cint)
|
||||
proc `ni`*(x: int, y: `typ`): `typout` = `ni`(x.cint, y)
|
||||
|
||||
let
|
||||
divop = newIdentNode("/") # `/`()
|
||||
dlrop = newIdentNode("$") # `$`()
|
||||
notop = newIdentNode("not") # `not`()
|
||||
result.add quote do:
|
||||
proc `divop`*(x, y: `typ`): `typ` = `typ`((x.float / y.float).cint)
|
||||
proc `divop`*(x: `typ`, y: cint): `typ` = `divop`(x, `typ`(y))
|
||||
proc `divop`*(x: cint, y: `typ`): `typ` = `divop`(`typ`(x), y)
|
||||
proc `divop`*(x: `typ`, y: int): `typ` = `divop`(x, y.cint)
|
||||
proc `divop`*(x: int, y: `typ`): `typ` = `divop`(x.cint, y)
|
||||
|
||||
proc `dlrop`*(x: `typ`): string {.borrow.}
|
||||
proc `notop`*(x: `typ`): `typ` {.borrow.}
|
||||
|
|
@ -54,7 +54,7 @@ type
|
|||
constIdentifiers*: HashSet[string] # Const names for enum casting
|
||||
identifiers*: TableRef[string, string] # Symbols that have been declared so far indexed by nimName
|
||||
skippedSyms*: HashSet[string] # Symbols that have been skipped due to being unwrappable or
|
||||
# the user provided override is blank
|
||||
# the user provided override is blank
|
||||
|
||||
# Nim compiler objects
|
||||
constSection*, enumSection*, pragmaSection*, procSection*, typeSection*, varSection*: PNode
|
||||
|
|
@ -70,6 +70,9 @@ type
|
|||
# Controls whether or not the current expression
|
||||
# should validate idents against currently defined idents
|
||||
skipIdentValidation*: bool
|
||||
|
||||
# Top level header for wrapper output - include imported types, pragmas and other info
|
||||
wrapperHeader*: string
|
||||
else:
|
||||
# cimport.nim specific
|
||||
compile*: seq[string] # `cCompile()` list of files already processed
|
||||
|
|
|
|||
|
|
@ -1481,6 +1481,11 @@ proc addEnum(gState: State, node: TSNode) =
|
|||
if node.getName() == "type_definition" and node.len > 1:
|
||||
gState.addTypeTyped(node, ftname = name, offset = offset)
|
||||
|
||||
if gEnumMacro.nBl:
|
||||
# Add enum generation macro once
|
||||
gState.wrapperHeader &= gEnumMacro
|
||||
gEnumMacro = ""
|
||||
|
||||
proc addProc(gState: State, node, rnode: TSNode, commentNodes: seq[TSNode]) =
|
||||
# Add a proc
|
||||
#
|
||||
|
|
@ -1822,10 +1827,7 @@ proc setupPragmas(gState: State, root: TSNode, fullpath: string) =
|
|||
|
||||
proc initNim*(gState: State) =
|
||||
# Initialize for parseNim() one time
|
||||
gecho """import nimterop/types
|
||||
|
||||
{.push hint[ConvFromXtoItselfNotNeeded]: off.}
|
||||
"""
|
||||
gState.wrapperHeader = "{.push hint[ConvFromXtoItselfNotNeeded]: off.}\n"
|
||||
|
||||
# Track identifiers already rendered and corresponding PNodes
|
||||
gState.identifiers = newTable[string, string]()
|
||||
|
|
@ -1876,6 +1878,7 @@ proc printNim*(gState: State) =
|
|||
tree.add gState.varSection
|
||||
tree.add gState.procSection
|
||||
|
||||
gecho gState.wrapperHeader
|
||||
gecho tree.renderTree()
|
||||
|
||||
gecho "{.pop.}"
|
||||
|
|
@ -95,7 +95,7 @@ proc getNameInfo*(gState: State, node: TSNode, kind: NimSymKind, parent = ""):
|
|||
result.name = gState.getIdentifier(result.origname, kind, parent)
|
||||
if result.name.nBl:
|
||||
if kind == nskType:
|
||||
result.name = result.name.getType()
|
||||
result.name = gState.getType(result.name, parent)
|
||||
result.info = gState.getLineInfo(node)
|
||||
|
||||
proc getPtrType*(str: string): string =
|
||||
|
|
|
|||
|
|
@ -580,7 +580,7 @@ proc processTSNode(gState: State, node: TSNode, typeofNode: var PNode): PNode =
|
|||
of "sized_type_specifier", "primitive_type", "type_identifier":
|
||||
# Input -> int, unsigned int, long int, etc
|
||||
# Output -> cint, cuint, clong, etc
|
||||
let ty = getType(node.val)
|
||||
let ty = gState.getType(node.val, parent = node.getName())
|
||||
if ty.len > 0:
|
||||
# If ty is not empty, one of C's builtin types has been found
|
||||
result = gState.getExprIdent(ty, nskType, parent=node.getName())
|
||||
|
|
|
|||
|
|
@ -29,7 +29,13 @@ yield""".split(Whitespace).toHashSet()
|
|||
|
||||
# Types related
|
||||
|
||||
const
|
||||
# Enum macro read from file - written into wrapper when required
|
||||
gEnumMacroConst = staticRead(currentSourcePath.parentDir().parentDir() / "enumtype.nim")
|
||||
|
||||
var
|
||||
gEnumMacro* = gEnumMacroConst
|
||||
|
||||
gTypeMap* = {
|
||||
# char
|
||||
"char": "cchar",
|
||||
|
|
@ -107,13 +113,40 @@ var
|
|||
"long double": "clongdouble",
|
||||
|
||||
# Misc Nim types
|
||||
"Bool": "bool"
|
||||
"Bool": "bool",
|
||||
"ptrdiff_t": "ByteAddress"
|
||||
}.toTable()
|
||||
|
||||
# Nim type names that shouldn't need to be wrapped again
|
||||
gTypeMapValues* = toSeq(gTypeMap.values).toHashSet()
|
||||
|
||||
proc getType*(str: string): string =
|
||||
# Types to import from C/Nim if used in wrapper
|
||||
gTypeImport* = {
|
||||
"time_t": """
|
||||
import std/time_t as std_time_t
|
||||
type time_t* = Time
|
||||
""",
|
||||
|
||||
"time64_t": """
|
||||
import std/time_t as std_time64_t
|
||||
type time64_t* = Time
|
||||
""",
|
||||
|
||||
"wchar_t": """
|
||||
when defined(cpp):
|
||||
# http://www.cplusplus.com/reference/cwchar/wchar_t/
|
||||
# In C++, wchar_t is a distinct fundamental type (and thus it is
|
||||
# not defined in <cwchar> nor any other header).
|
||||
type wchar_t* {.importc.} = object
|
||||
else:
|
||||
type wchar_t* {.importc, header:"<cwchar>".} = object
|
||||
""",
|
||||
|
||||
"va_list": """
|
||||
type va_list* {.importc, header:"<stdarg.h>".} = object
|
||||
"""}.toTable()
|
||||
|
||||
proc getType*(gState: State, str, parent: string): string =
|
||||
if str == "void":
|
||||
return "object"
|
||||
|
||||
|
|
@ -121,6 +154,10 @@ proc getType*(str: string): string =
|
|||
|
||||
if gTypeMap.hasKey(result):
|
||||
result = gTypeMap[result]
|
||||
elif parent.nBl and gTypeImport.hasKey(result) and not gState.identifierNodes.hasKey(result):
|
||||
# Include C/Nim type imports once if a field/param and not already declared
|
||||
gState.wrapperHeader &= "\n" & gTypeImport[result]
|
||||
gTypeImport.del result
|
||||
|
||||
# Identifier related
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,8 @@
|
|||
|
||||
import strutils, os
|
||||
|
||||
import ".."/[setup, paths, types]
|
||||
include ".."/enumtype
|
||||
import ".."/[paths, setup]
|
||||
|
||||
static:
|
||||
treesitterSetup()
|
||||
|
|
|
|||
|
|
@ -1,74 +0,0 @@
|
|||
# see https://github.com/nimterop/nimterop/issues/79
|
||||
|
||||
import std/time_t as time_t_temp
|
||||
type
|
||||
time_t* = time_t_temp.Time
|
||||
time64_t* = time_t_temp.Time
|
||||
|
||||
when defined(cpp):
|
||||
# http://www.cplusplus.com/reference/cwchar/wchar_t/
|
||||
# In C++, wchar_t is a distinct fundamental type (and thus it is
|
||||
# not defined in <cwchar> nor any other header).
|
||||
type
|
||||
wchar_t* {.importc.} = object
|
||||
else:
|
||||
type
|
||||
wchar_t* {.importc, header:"<cwchar>".} = object
|
||||
|
||||
type
|
||||
ptrdiff_t* = ByteAddress
|
||||
|
||||
type
|
||||
va_list* {.importc, header:"<stdarg.h>".} = object
|
||||
|
||||
template enumOp*(op, typ, typout) =
|
||||
proc op*(x: typ, y: cint): typout {.borrow.}
|
||||
proc op*(x: cint, y: typ): typout {.borrow.}
|
||||
proc op*(x, y: typ): typout {.borrow.}
|
||||
|
||||
proc op*(x: typ, y: int): typout = op(x, y.cint)
|
||||
proc op*(x: int, y: typ): typout = op(x.cint, y)
|
||||
|
||||
template defineEnum*(typ) =
|
||||
# Create a `distinct cint` type for C enums since Nim enums
|
||||
# need to be in order and cannot have duplicates.
|
||||
type
|
||||
typ* = distinct cint
|
||||
|
||||
# Enum operations allowed
|
||||
enumOp(`+`, typ, typ)
|
||||
enumOp(`-`, typ, typ)
|
||||
enumOp(`*`, typ, typ)
|
||||
enumOp(`<`, typ, bool)
|
||||
enumOp(`<=`, typ, bool)
|
||||
enumOp(`==`, typ, bool)
|
||||
enumOp(`div`, typ, typ)
|
||||
enumOp(`mod`, typ, typ)
|
||||
|
||||
# These don't work with `enumOp()` for some reason
|
||||
proc `shl`*(x: typ, y: cint): typ {.borrow.}
|
||||
proc `shl`*(x: cint, y: typ): typ {.borrow.}
|
||||
proc `shl`*(x, y: typ): typ {.borrow.}
|
||||
|
||||
proc `shr`*(x: typ, y: cint): typ {.borrow.}
|
||||
proc `shr`*(x: cint, y: typ): typ {.borrow.}
|
||||
proc `shr`*(x, y: typ): typ {.borrow.}
|
||||
|
||||
proc `or`*(x: typ, y: cint): typ {.borrow.}
|
||||
proc `or`*(x: cint, y: typ): typ {.borrow.}
|
||||
proc `or`*(x, y: typ): typ {.borrow.}
|
||||
|
||||
proc `and`*(x: typ, y: cint): typ {.borrow.}
|
||||
proc `and`*(x: cint, y: typ): typ {.borrow.}
|
||||
proc `and`*(x, y: typ): typ {.borrow.}
|
||||
|
||||
proc `xor`*(x: typ, y: cint): typ {.borrow.}
|
||||
proc `xor`*(x: cint, y: typ): typ {.borrow.}
|
||||
proc `xor`*(x, y: typ): typ {.borrow.}
|
||||
|
||||
proc `/`*(x, y: typ): typ =
|
||||
return (x.float / y.float).cint.typ
|
||||
proc `/`*(x: typ, y: cint): typ = `/`(x, y.typ)
|
||||
proc `/`*(x: cint, y: typ): typ = `/`(x.typ, y)
|
||||
|
||||
proc `$`*(x: typ): string {.borrow.}
|
||||
Loading…
Add table
Add a link
Reference in a new issue