Skip to content

Commit

Permalink
Fix 128 bit integers and some type macros
Browse files Browse the repository at this point in the history
  • Loading branch information
dkorpel committed Nov 14, 2023
1 parent 5a156c2 commit 4691c3b
Show file tree
Hide file tree
Showing 8 changed files with 196 additions and 140 deletions.
18 changes: 9 additions & 9 deletions source/ctod/cdeclaration.d
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ Decl[] ctodTryDeclaration(ref CtodCtx ctx, ref Node node) {
if (apiMacro.length > 0) {
result ~= apiMacro ~ " ";
}
foreach(s; inlinetypes) {
foreach (s; inlinetypes) {
result ~= s.toString();
}
CType previousType = CType.none;
foreach(d; decls) {
foreach (d; decls) {
if (cInit && d.initializer.length == 0) {
if (ctx.inFunction && !d.quals.staticFunc) {
// void initialize function local variables
Expand Down Expand Up @@ -50,7 +50,7 @@ Decl[] ctodTryDeclaration(ref CtodCtx ctx, ref Node node) {
return decls;
}

switch(node.typeEnum) {
switch (node.typeEnum) {
case Sym.function_definition:
if (auto bodyNode = node.childField(Field.body_)) {
auto declNode = node.childField(Field.declarator);
Expand Down Expand Up @@ -100,15 +100,15 @@ bool ctodTryTypedef(ref CtodCtx ctx, ref Node node) {
}
}

foreach(s; inlinetypes) {
foreach (s; inlinetypes) {
result ~= s.toString();
if (s.node) {
// Put enum members into the global scope with aliases
node.append(enumMemberAliases(s.name, *s.node));
}
}
bool first = true;
foreach(d; decls) {
foreach (d; decls) {
if (d.type == CType.named(d.identifier)) {
// result ~= "/*alias " ~ d.toString() ~ ";*/";
} else {
Expand All @@ -127,16 +127,16 @@ bool ctodTryTypedef(ref CtodCtx ctx, ref Node node) {
/// Try translating variable initializers
/// Returns: true if translation is done, no need to translate children
bool ctodTryInitializer(ref CtodCtx ctx, ref Node node) {
switch(node.typeEnum) {
switch (node.typeEnum) {
case Sym.compound_literal_expression:
// (Rectangle){x, y, width, height} => Rectangle(x, y, width, height)
foreach(ref c; node.children) {
foreach (ref c; node.children) {
if (c.typeEnum == Sym.anon_LPAREN) {
c.replace("");
} else if (c.typeEnum == Sym.anon_RPAREN) {
c.replace("");
} else if (c.typeEnum == Sym.initializer_list) {
foreach(ref c2; c.children) {
foreach (ref c2; c.children) {
if (c2.typeEnum == Sym.anon_LBRACE) {
c2.replace("(");
} else if (c2.typeEnum == Sym.anon_RBRACE) {
Expand All @@ -156,7 +156,7 @@ bool ctodTryInitializer(ref CtodCtx ctx, ref Node node) {
// The current type check is rather primitive, it doesn't look up type aliases and
// doesn't consider nested types (e.g. struct of array of struct of ...)
// So also inspect the literal itself to gain clues
foreach(ref c; node.children) {
foreach (ref c; node.children) {
// Array literal can have `[0] = 3`, struct can have `.field = 3`
if (c.typeEnum == Sym.initializer_pair) {
if (auto c1 = c.childField(Field.designator)) {
Expand Down
10 changes: 5 additions & 5 deletions source/ctod/cexpr.d
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Node* getParenContent(return scope Node* node) {
if (node.typeEnum != Sym.parenthesized_expression && node.typeEnum != Sym.parenthesized_declarator) {
return node;
}
foreach(i; 1 .. node.children.length + -1) {
foreach (i; 1 .. node.children.length + -1) {
if (node.children[i].typeEnum != Sym.comment) {
return &node.children[i];
}
Expand All @@ -30,7 +30,7 @@ Node* getParenContent(return scope Node* node) {
/// - pointer arithmetic on static arrays can only be done after adding `.ptr`
bool ctodExpression(ref CtodCtx ctx, ref Node node) {
void depthFirst() {
foreach(ref c; node.children) {
foreach (ref c; node.children) {
translateNode(ctx, c);
}
}
Expand Down Expand Up @@ -143,7 +143,7 @@ bool ctodExpression(ref CtodCtx ctx, ref Node node) {
case Sym.concatenated_string:
// "a" "b" "c" => "a"~"b"~"c"
bool first = true;
foreach(ref c; node.children) {
foreach (ref c; node.children) {
if (c.typeEnum == Sym.string_literal) {
if (first) {
first = false;
Expand Down Expand Up @@ -228,7 +228,7 @@ bool ctodExpression(ref CtodCtx ctx, ref Node node) {
if (argsNode.typeEnum != Sym.argument_list) {
break;
}
foreach(ref c; argsNode.children) {
foreach (ref c; argsNode.children) {
if (c.typeEnum == Sym.anon_COMMA || c.typeEnum == Sym.comment ||
c.typeEnum == Sym.anon_LPAREN || c.typeEnum == Sym.anon_RPAREN) {
continue;
Expand Down Expand Up @@ -339,7 +339,7 @@ bool translateSpecialFunction(ref Node node, ref Node funcNode) {
}
string[2] argNames;
size_t i = 0;
foreach(ref c; args.children) {
foreach (ref c; args.children) {
if (c.typeEnum == Sym.identifier) {
if (i >= 2) {
i = 0; // too many arguments
Expand Down
122 changes: 94 additions & 28 deletions source/ctod/cpreproc.d
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@ nothrow @safe:

import ctod.translate;
import ctod.tree_sitter;
import ctod.util;

package
/// If `node` is a recognized preprocessor node, translate it to D
///
/// Returns: `true` on success
bool ctodTryPreprocessor(ref CtodCtx ctx, ref Node node) {
switch(node.typeEnum) {
switch (node.typeEnum) {
case Sym.aux_preproc_else_token1: // "#else"
return node.replace("} else {");
case Sym.aux_preproc_if_token2: // "#endif"
Expand Down Expand Up @@ -46,33 +47,55 @@ bool ctodTryPreprocessor(ref CtodCtx ctx, ref Node node) {
case Sym.preproc_def:
if (auto valueNode = node.childField(Field.value)) {
// aux_sym_preproc_def_token1 = "#define"
if (auto c = node.firstChildType(Sym.aux_preproc_def_token1)) {
c.replace("enum");
}
if (auto c = node.childField(Field.name)) {
translateNode(ctx, *c);
ctx.macroTable[c.output()] = MacroType.manifestConstant;
}
if (auto c = node.firstChildType(Sym.preproc_arg)) {
// tree sitter doesn't parse line comments inside preproc arg,
// so we need to manually split it so that:
// #define X Y // comment
// Becomes:
// enum X = Y; // comment
// Instead of:
// enum X = Y // comment;
size_t p = 0;
while (p+1 < c.source.length) {
if (c.source[p] == '/' && c.source[p+1] == '/') {
while (p > 0 && c.source[p-1] == ' ') {
p--;
}
return c.replace(" =" ~ c.source[0..p] ~ ";" ~ c.source[p..$]);
auto argNode = node.firstChildType(Sym.preproc_arg);
assert(argNode);
const argText = argNode.source;
size_t p = 0;
while (p < argText.length && argText[p].isWhite) {
p++;
}
string whitespace = argText[0..p];
string value = argText[p..$];
string comment = "";

// tree sitter doesn't parse line comments inside preproc arg,
// so we need to manually split it so that:
// #define X Y // comment
// Becomes:
// enum X = Y; // comment
// Instead of:
// enum X = Y // comment;
p = 0;
while (p+1 < value.length) {
if (value[p] == '/' && value[p+1] == '/') {
while (p > 0 && value[p-1].isWhite) {
p--;
}
p++;
comment = value[p..$];
value = value[0..p];
break;
}
p++;
}

if (auto c = node.firstChildType(Sym.aux_preproc_def_token1)) {
import ctod.ctype : ctodPrimitiveType;
const newValue = ctodPrimitiveType(value);
if (newValue != value) {
c.replace("alias");
value = newValue;
} else if (value == "int") { // TODO: generalize to all D types
c.replace("alias");
} else {
c.replace("enum");
}
c.replace(" =" ~ c.source ~ ";");
}
argNode.replace(" =" ~ whitespace ~ value ~ ";" ~ comment);

} else {
if (auto c = node.firstChildType(Sym.aux_preproc_def_token1)) {
c.replace("version =");
Expand Down Expand Up @@ -106,7 +129,7 @@ bool ctodTryPreprocessor(ref CtodCtx ctx, ref Node node) {
ctx.macroTable[nameNode.output()] = MacroType.inlineFunc;

string[] params;
foreach(ref param; parametersNode.children) {
foreach (ref param; parametersNode.children) {
if (param.typeEnum == Sym.identifier) {
ctx.macroFuncParams[param.source] = true;
params ~= param.source;
Expand All @@ -116,7 +139,7 @@ bool ctodTryPreprocessor(ref CtodCtx ctx, ref Node node) {

valueNode.prepend(" = `");
valueNode.replace(ctodMacroFunc(ctx, valueNode.source));
(() @trusted => ctx.macroFuncParams.clear())();
ctx.macroFuncParams = ctx.macroFuncParams.init; //.clear();
valueNode.append("`;");
break;
case Sym.preproc_ifdef:
Expand Down Expand Up @@ -238,7 +261,7 @@ bool ctodTryPreprocessor(ref CtodCtx ctx, ref Node node) {

/// Find params in macroText, and surround them with ~""~
string ctodMacroFunc(ref CtodCtx ctx, string macroText) {
while (macroText.length > 0 && macroText[0] == ' ') {
while (macroText.length > 0 && macroText[0].isWhite) {
macroText = macroText[1 .. $];
}
// Assume the macro expand to an expression, statement, or variable declaration
Expand Down Expand Up @@ -284,8 +307,8 @@ private bool ctodHeaderGuard(ref CtodCtx ctx, ref Node ifdefNode) {
// second node is always field `name` with a `Sym.identifier`
string id = ifdefNode.children[1].source;

foreach(i; 0..ifdefNode.children.length) {
switch(ifdefNode.children[i].typeEnum) {
foreach (i; 0..ifdefNode.children.length) {
switch (ifdefNode.children[i].typeEnum) {
case Sym.comment:
commentCount++;
continue;
Expand All @@ -305,7 +328,7 @@ private bool ctodHeaderGuard(ref CtodCtx ctx, ref Node ifdefNode) {
return false;
}
// put remaining children under translation unit instead of the ifdef
foreach(j; 0..ifdefNode.children.length) {
foreach (j; 0..ifdefNode.children.length) {
if (j <= i || j + 1 == ifdefNode.children.length) {
ifdefNode.children[j].replace(""); // header guard nodes
} else {
Expand Down Expand Up @@ -372,7 +395,7 @@ string ctodIncludePath(string s) pure {

/// Replace all occurences of `from` with `to` in `s`
void replaceChar(char[] s, char from, char to) pure {
foreach(i; 0 .. s.length) {
foreach (i; 0 .. s.length) {
if (s[i] == from) {
s[i] = to;
}
Expand Down Expand Up @@ -470,3 +493,46 @@ string ctodSysLib(string s) {

return s ~ ";";
}

// Remove `#ifdef __cplusplus \n extern "C" { \n #endif` blocks since tree-sitter can't parse the unmatched braces inside them
string filterCppBlocks(string source) {
size_t[3] s = 0; // loop over line triples by keeping 3 indices of the start of a line
for (size_t i = 0; i < source.length; i++) {
if (source[i] == '\n') {
const s3 = i + 1;
if (source[s[0] .. s[1]].startsWith("#ifdef __cplusplus") && source[s[2] .. s3].startsWith("#endif")) {
source = source[0 .. s[0]] ~ source[s3 .. $];
i = s[0];
s[] = 0;
continue;
} else {
s[0] = s[1];
s[1] = s[2];
s[2] = s3;
}
}
}
return source;
}

unittest {
string source = "
#ifdef __cplusplus
extern \"C\" {
#endif
int main() {
return 0;
}
#ifdef __cplusplus
}
#endif
";

string expected = "
int main() {
return 0;
}
";
import ctod.util: assertEq;
assertEq(filterCppBlocks(source), expected);
}
Loading

0 comments on commit 4691c3b

Please sign in to comment.