Skip to content

Commit

Permalink
Fix handling of void aliases, support FuncNoProto
Browse files Browse the repository at this point in the history
  • Loading branch information
PMunch committed Oct 15, 2021
1 parent 77e72ac commit 427a16b
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 35 deletions.
57 changes: 30 additions & 27 deletions src/futhark.nim
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import macros, strutils, os, json, tables, sets, sugar, hashes, std/compilesetti
import macroutils except Lit

const
Stringable = {nnkStrLit..nnkTripleStrLit, nnkCommentStmt, nnkIdent, nnkSym}
VERSION = "0.3.0"
builtins = ["addr", "and", "as", "asm",
"bind", "block", "break",
Expand All @@ -24,6 +25,8 @@ const
"xor",
"yield"]

template strCmp(node, value: untyped): untyped = node.kind in Stringable and node.strVal == value

type
RenameCallback = proc(name: string, kind: string, partof = ""): string
State = object
Expand Down Expand Up @@ -104,7 +107,8 @@ proc addUsings(used: var HashSet[string], node: JsonNode) =
of "struct", "union":
for field in node["fields"]:
if field["type"].kind != JNull:
if field["type"]["kind"].str in ["struct", "union"]:
case field["type"]["kind"].str:
of "struct", "union", "pointer", "proc":
used.addUsings field["type"]
let alias = field["type"].findAlias
if alias.len != 0:
Expand All @@ -118,6 +122,8 @@ proc addUsings(used: var HashSet[string], node: JsonNode) =
let alias = node["base"].findAlias
if alias.len != 0:
used.incl alias
elif node["base"]["kind"].str == "proc":
used.addUsings(node["base"])
of "alias":
used.incl node.findAlias
of "enum", "base": discard
Expand All @@ -135,28 +141,18 @@ proc toNimType(json: JsonNode, state: var State): NimNode =
result = case json["kind"].str:
of "base": json["value"].str.ident
of "pointer":
if json["base"]["kind"].str == "alias":
var node = state.typeNameMap[json["base"]["value"].str]
for i in 0..<json["depth"].num:
node = nnkPtrTy.newTree(node)
node
elif json["base"]["kind"].str == "proc":
var node = json["base"].toNimType(state)
for i in 0..<json["depth"].num - 1:
node = nnkPtrTy.newTree(node)
node
elif json["base"]["kind"].str == "base":
var node = json["base"].toNimType(state)
if node.strVal == "void":
node = "pointer".ident
for i in 0..<json["depth"].num - (if node.strVal == "pointer": 1 else: 0):
node = nnkPtrTy.newTree(node)
node
else:
var node = "pointer".ident
for i in 0..<json["depth"].num - 1:
node = nnkPtrTy.newTree(node)
node
var node =
case json["base"]["kind"].str:
of "alias", "proc", "base":
var node = json["base"].toNimType(state)
if node.strCmp "void":
node = "pointer".ident
node
else:
"pointer".ident
for i in 0..<json["depth"].num - (if node.strCmp("pointer") or json["base"]["kind"].str == "proc": 1 else: 0):
node = nnkPtrTy.newTree(node)
node
of "proc":
var procTy = nnkProcTy.newTree(
nnkFormalParams.newTree(json["return"].toNimType(state)),
Expand Down Expand Up @@ -381,8 +377,6 @@ proc createConst(origName: string, node: JsonNode, state: var State, comment: st
type
FromTo = tuple[f, t: string]

const Stringable = {nnkStrLit..nnkTripleStrLit, nnkCommentStmt, nnkIdent, nnkSym}

macro importc*(imports: varargs[untyped]): untyped =
## Generate code from C imports. String literals will be treated as files to
## `#include`. Paths can be added with `path <string literal>`, which are
Expand Down Expand Up @@ -489,6 +483,7 @@ macro importcImpl*(defs: static[string], compilerArguments, files: static[openAr
opirOutput[^1]


hint "Parsing Opir output"
# TODO: Clear out old cache files?
let
fut = try:
Expand All @@ -501,6 +496,7 @@ macro importcImpl*(defs: static[string], compilerArguments, files: static[openAr
if not fileExists(opirCache):
writeFile(opirCache, output)

hint "Generating Futhark output"
var state = State(
types: newNimNode(nnkTypeSection),
procs: newStmtList(),
Expand Down Expand Up @@ -553,8 +549,11 @@ macro importcImpl*(defs: static[string], compilerArguments, files: static[openAr
if state.entities[name]["kind"].str notin ["proc", "var", "const"]:
state.typeDefMap[name] = genSym(nskType, saneName)
state.typeNameMap[name] = genSym(nskType, saneName)
#if state.entities[name]["kind"].str == "const":
# state.typeNameMap[name] = sanitizeName(name, true).ident

if state.entities[name]["kind"].str == "typedef":
if state.entities[name]["type"]["kind"].str == "base" and state.entities[name]["type"]["value"].str == "void":
state.typeDefMap[name] = bindSym("void")
state.typeNameMap[name] = bindSym("void")
else:
state.typeNameMap[name] = state.sanitizeName(name, "anon").ident

Expand All @@ -578,6 +577,8 @@ macro importcImpl*(defs: static[string], compilerArguments, files: static[openAr
var newType = parseStmt("type dummy = dummy ## " & comment)[0][0]
newType[0] = state.typeDefMap[node["name"].str].postfix "*"
newType[^1] = node["type"].toNimType(state)
if newType[^1].kind == nnkIdent and newType[^1].strVal == "void":
continue
state.types.add newType
of "enum":
createEnum(node["name"].str, node, state, comment)
Expand Down Expand Up @@ -612,6 +613,7 @@ macro importcImpl*(defs: static[string], compilerArguments, files: static[openAr

# Generate conditionals to define inner object types if not previously defined
for name, defIdent in state.typeDefMap:
if defIdent.strVal == "void": continue
let
origIdent = state.renamed[name].ident
nameIdent = state.typeNameMap[name]
Expand All @@ -622,6 +624,7 @@ macro importcImpl*(defs: static[string], compilerArguments, files: static[openAr

# Generate conditionals to define objects if not previously defined
for name, defIdent in state.typeDefMap:
if defIdent.strVal == "void": continue
let origIdent = state.renamed[name].ident
if state.entities[name]["kind"].str != "enum":
result.add quote do:
Expand Down
13 changes: 5 additions & 8 deletions src/opir.nim
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ proc toNimType(ct: CXType): JsonNode =
if info.depth == 1 and info.baseType.kind == CXType_CharS:
%*{"kind": "base", "value": "cstring"}
else:
%*{"kind": "pointer", "depth": info.depth, "base": info.baseType.toNimType}
let baseType = info.baseType.toNimType
%*{"kind": "pointer", "depth": info.depth, "base": if baseType.kind != JNull: baseType else: %*{"kind": "base", "value": "void"}}
of CXType_BlockPointer: %*{"kind": "pointer", "depth": 0}
of CXType_Typedef:
let name = $ct.getTypedefName
Expand Down Expand Up @@ -99,8 +100,8 @@ proc toNimType(ct: CXType): JsonNode =
newJNull()
of CXType_LValueReference, CXType_RValueReference, CXType_ObjCInterface, CXType_ObjCObjectPointer: %*{"kind": "invalid", "value": "???"}
of CXType_Enum: %*{"kind": "invalid", "value": "inline enum?"}
of CXType_FunctionNoProto: %*{"kind": "invalid", "value": "func_noproto?"}
of CXType_FunctionProto:
#of CXType_FunctionNoProto: %*{"kind": "invalid", "value": "func_noproto?"}
of CXType_FunctionProto, CXType_FunctionNoProto:
# TODO: Move to use genProcDecl? Or at least share code
let retType = ct.getResultType
var args: seq[JsonNode]
Expand Down Expand Up @@ -174,12 +175,8 @@ if unit.isNil or fatal:

proc genTypedefDecl(typedef: CXCursor): JsonNode =
let
underlying = typedef.getTypeDefDeclUnderlyingType
name = $typedef.getCursorSpelling
theType = if underlying.kind == CXType_Pointer:
underlying.getPointerInfo.baseType.toNimType
else:
underlying.toNimType
theType = typedef.getTypeDefDeclUnderlyingType.toNimType
location = typedef.getLocation
if theType.kind != JNull and not (theType["kind"].str == "alias" and theType["value"].str == name):
return %*{"kind": "typedef", "file": location.filename, "position": {"column": location.column, "line": location.line}, "name": name, "type": theType}
Expand Down

0 comments on commit 427a16b

Please sign in to comment.