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.
|
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 hashes, macros, os, strformat, strutils
|
||||||
|
|
||||||
import "."/[build, globals, paths, types]
|
import "."/[build, globals, paths]
|
||||||
export types
|
|
||||||
|
|
||||||
proc interpPath(dir: string): string=
|
proc interpPath(dir: string): string=
|
||||||
# TODO: more robust: needs a DirSep after "$projpath"
|
# 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
|
# see https://github.com/nimterop/nimterop/issues/69
|
||||||
(result, ret) = execAction(cmd, die = false, cache = (not gStateCT.nocache),
|
(result, ret) = execAction(cmd, die = false, cache = (not gStateCT.nocache),
|
||||||
cacheKey = getCacheValue(fullpaths))
|
cacheKey = getCacheValue(toastExe) & getCacheValue(fullpaths))
|
||||||
doAssert ret == 0, getToastError(result)
|
doAssert ret == 0, getToastError(result)
|
||||||
|
|
||||||
macro cOverride*(body): untyped =
|
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
|
constIdentifiers*: HashSet[string] # Const names for enum casting
|
||||||
identifiers*: TableRef[string, string] # Symbols that have been declared so far indexed by nimName
|
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
|
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
|
# Nim compiler objects
|
||||||
constSection*, enumSection*, pragmaSection*, procSection*, typeSection*, varSection*: PNode
|
constSection*, enumSection*, pragmaSection*, procSection*, typeSection*, varSection*: PNode
|
||||||
|
|
@ -70,6 +70,9 @@ type
|
||||||
# Controls whether or not the current expression
|
# Controls whether or not the current expression
|
||||||
# should validate idents against currently defined idents
|
# should validate idents against currently defined idents
|
||||||
skipIdentValidation*: bool
|
skipIdentValidation*: bool
|
||||||
|
|
||||||
|
# Top level header for wrapper output - include imported types, pragmas and other info
|
||||||
|
wrapperHeader*: string
|
||||||
else:
|
else:
|
||||||
# cimport.nim specific
|
# cimport.nim specific
|
||||||
compile*: seq[string] # `cCompile()` list of files already processed
|
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:
|
if node.getName() == "type_definition" and node.len > 1:
|
||||||
gState.addTypeTyped(node, ftname = name, offset = offset)
|
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]) =
|
proc addProc(gState: State, node, rnode: TSNode, commentNodes: seq[TSNode]) =
|
||||||
# Add a proc
|
# Add a proc
|
||||||
#
|
#
|
||||||
|
|
@ -1822,10 +1827,7 @@ proc setupPragmas(gState: State, root: TSNode, fullpath: string) =
|
||||||
|
|
||||||
proc initNim*(gState: State) =
|
proc initNim*(gState: State) =
|
||||||
# Initialize for parseNim() one time
|
# Initialize for parseNim() one time
|
||||||
gecho """import nimterop/types
|
gState.wrapperHeader = "{.push hint[ConvFromXtoItselfNotNeeded]: off.}\n"
|
||||||
|
|
||||||
{.push hint[ConvFromXtoItselfNotNeeded]: off.}
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Track identifiers already rendered and corresponding PNodes
|
# Track identifiers already rendered and corresponding PNodes
|
||||||
gState.identifiers = newTable[string, string]()
|
gState.identifiers = newTable[string, string]()
|
||||||
|
|
@ -1876,6 +1878,7 @@ proc printNim*(gState: State) =
|
||||||
tree.add gState.varSection
|
tree.add gState.varSection
|
||||||
tree.add gState.procSection
|
tree.add gState.procSection
|
||||||
|
|
||||||
|
gecho gState.wrapperHeader
|
||||||
gecho tree.renderTree()
|
gecho tree.renderTree()
|
||||||
|
|
||||||
gecho "{.pop.}"
|
gecho "{.pop.}"
|
||||||
|
|
@ -95,7 +95,7 @@ proc getNameInfo*(gState: State, node: TSNode, kind: NimSymKind, parent = ""):
|
||||||
result.name = gState.getIdentifier(result.origname, kind, parent)
|
result.name = gState.getIdentifier(result.origname, kind, parent)
|
||||||
if result.name.nBl:
|
if result.name.nBl:
|
||||||
if kind == nskType:
|
if kind == nskType:
|
||||||
result.name = result.name.getType()
|
result.name = gState.getType(result.name, parent)
|
||||||
result.info = gState.getLineInfo(node)
|
result.info = gState.getLineInfo(node)
|
||||||
|
|
||||||
proc getPtrType*(str: string): string =
|
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":
|
of "sized_type_specifier", "primitive_type", "type_identifier":
|
||||||
# Input -> int, unsigned int, long int, etc
|
# Input -> int, unsigned int, long int, etc
|
||||||
# Output -> cint, cuint, clong, 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.len > 0:
|
||||||
# If ty is not empty, one of C's builtin types has been found
|
# If ty is not empty, one of C's builtin types has been found
|
||||||
result = gState.getExprIdent(ty, nskType, parent=node.getName())
|
result = gState.getExprIdent(ty, nskType, parent=node.getName())
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,13 @@ yield""".split(Whitespace).toHashSet()
|
||||||
|
|
||||||
# Types related
|
# Types related
|
||||||
|
|
||||||
|
const
|
||||||
|
# Enum macro read from file - written into wrapper when required
|
||||||
|
gEnumMacroConst = staticRead(currentSourcePath.parentDir().parentDir() / "enumtype.nim")
|
||||||
|
|
||||||
var
|
var
|
||||||
|
gEnumMacro* = gEnumMacroConst
|
||||||
|
|
||||||
gTypeMap* = {
|
gTypeMap* = {
|
||||||
# char
|
# char
|
||||||
"char": "cchar",
|
"char": "cchar",
|
||||||
|
|
@ -107,13 +113,40 @@ var
|
||||||
"long double": "clongdouble",
|
"long double": "clongdouble",
|
||||||
|
|
||||||
# Misc Nim types
|
# Misc Nim types
|
||||||
"Bool": "bool"
|
"Bool": "bool",
|
||||||
|
"ptrdiff_t": "ByteAddress"
|
||||||
}.toTable()
|
}.toTable()
|
||||||
|
|
||||||
# Nim type names that shouldn't need to be wrapped again
|
# Nim type names that shouldn't need to be wrapped again
|
||||||
gTypeMapValues* = toSeq(gTypeMap.values).toHashSet()
|
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":
|
if str == "void":
|
||||||
return "object"
|
return "object"
|
||||||
|
|
||||||
|
|
@ -121,6 +154,10 @@ proc getType*(str: string): string =
|
||||||
|
|
||||||
if gTypeMap.hasKey(result):
|
if gTypeMap.hasKey(result):
|
||||||
result = gTypeMap[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
|
# Identifier related
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,8 @@
|
||||||
|
|
||||||
import strutils, os
|
import strutils, os
|
||||||
|
|
||||||
import ".."/[setup, paths, types]
|
include ".."/enumtype
|
||||||
|
import ".."/[paths, setup]
|
||||||
|
|
||||||
static:
|
static:
|
||||||
treesitterSetup()
|
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