Fix GC issue for D backend with AST enabled - close #36
This commit is contained in:
parent
839174a635
commit
92da10e483
@ -8,6 +8,7 @@
|
||||
module <%= @grammar.modulename %>;
|
||||
<% end %>
|
||||
|
||||
import core.memory;
|
||||
import core.stdc.stdlib : malloc;
|
||||
|
||||
/**************************************************************************
|
||||
@ -1079,7 +1080,9 @@ public size_t <%= @grammar.prefix %>parse(<%= @grammar.prefix %>context_t * cont
|
||||
else if (parser_reduce_table[reduce_index].n_states > 0)
|
||||
{
|
||||
size_t n_fields = parser_reduce_table[reduce_index].rule_set_node_field_array_size;
|
||||
ASTNode * node = cast(ASTNode *)malloc(ASTNode.sizeof + n_fields * (void *).sizeof);
|
||||
size_t node_size = ASTNode.sizeof + n_fields * (void *).sizeof;
|
||||
ASTNode * node = cast(ASTNode *)malloc(node_size);
|
||||
GC.addRange(node, node_size);
|
||||
node.position = <%= @grammar.prefix %>position_t.INVALID;
|
||||
node.end_position = <%= @grammar.prefix %>position_t.INVALID;
|
||||
foreach (i; 0..n_fields)
|
||||
|
||||
151
spec/ast_node_memory_remains.c.propane
Normal file
151
spec/ast_node_memory_remains.c.propane
Normal file
@ -0,0 +1,151 @@
|
||||
ast;
|
||||
ast_prefix P;
|
||||
|
||||
<<header
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef union
|
||||
{
|
||||
uint64_t i64;
|
||||
const uint8_t * s;
|
||||
double dou;
|
||||
} TokenVal;
|
||||
>>
|
||||
|
||||
ptype TokenVal;
|
||||
|
||||
# Keywords.
|
||||
token byte;
|
||||
token def;
|
||||
token int;
|
||||
token long;
|
||||
token module;
|
||||
token return;
|
||||
token short;
|
||||
token size_t;
|
||||
token ssize_t;
|
||||
token ubyte;
|
||||
token uint;
|
||||
token ulong;
|
||||
token ushort;
|
||||
|
||||
# Symbols.
|
||||
token arrow /->/;
|
||||
token comma /,/;
|
||||
token lbrace /\{/;
|
||||
token lparen /\(/;
|
||||
token rbrace /\}/;
|
||||
token rparen /\)/;
|
||||
token semicolon /;/;
|
||||
|
||||
# Integer literals.
|
||||
token hex_int_l /0[xX][0-9a-fA-F][0-9a-fA-F_]*/ <<
|
||||
$$.i64 = 64u;
|
||||
>>
|
||||
|
||||
# Identifier.
|
||||
token ident /\$?[a-zA-Z_][a-zA-Z_0-9]*\??/ <<
|
||||
$$.s = match;
|
||||
$mode(default);
|
||||
return $token(ident);
|
||||
>>
|
||||
|
||||
# Comments.
|
||||
drop /#.*/;
|
||||
|
||||
# Whitespace.
|
||||
drop /[ \r\n]*/;
|
||||
|
||||
start Module;
|
||||
|
||||
# Assignment operators - right associative
|
||||
Expression -> Expression_Or:exp0;
|
||||
|
||||
# Logical OR operator - left associative
|
||||
Expression_Or -> Expression_And:exp0;
|
||||
|
||||
# Logical AND operator - left associative
|
||||
Expression_And -> Expression_Comp:exp0;
|
||||
|
||||
# Equality operators - left associative
|
||||
Expression_Comp -> Expression_Relational:exp0;
|
||||
|
||||
# Relational operators - left associative
|
||||
Expression_Relational -> Expression_REMatch:exp0;
|
||||
|
||||
# Regular expression - left associative
|
||||
Expression_REMatch -> Expression_BinOr:exp0;
|
||||
|
||||
# Binary OR operator - left associative
|
||||
Expression_BinOr -> Expression_Xor:exp0;
|
||||
|
||||
# Binary XOR operator - left associative
|
||||
Expression_Xor -> Expression_BinAnd:exp0;
|
||||
|
||||
# Binary AND operator - left associative
|
||||
Expression_BinAnd -> Expression_BitShift:exp0;
|
||||
|
||||
# Bit shift operators - left associative
|
||||
Expression_BitShift -> Expression_Plus:exp0;
|
||||
|
||||
# Add/subtract operators - left associative
|
||||
Expression_Plus -> Expression_Mul:exp0;
|
||||
|
||||
# Multiplication/divide/modulus operators - left associative
|
||||
Expression_Mul -> Expression_Range:exp0;
|
||||
|
||||
# Range construction operators - left associative
|
||||
Expression_Range -> Expression_UnaryPrefix:exp0;
|
||||
|
||||
# Unary prefix operators
|
||||
Expression_UnaryPrefix -> Expression_Dot:exp0;
|
||||
|
||||
# Postfix operators
|
||||
Expression_Dot -> Expression_Ident:exp0;
|
||||
Expression_Dot -> Expression_Dot:exp1 lparen rparen;
|
||||
|
||||
# Literals, identifiers, and parenthesized expressions
|
||||
Expression_Ident -> Literal;
|
||||
Expression_Ident -> ident;
|
||||
|
||||
FunctionDefinition -> def ident:name lparen FunctionParameterList?:parameters rparen FunctionReturnType?:returntype lbrace Statements rbrace;
|
||||
|
||||
FunctionParameterList -> ident:name Type:type FunctionParameterListMore?:more;
|
||||
FunctionParameterListMore -> comma ident:name Type:type FunctionParameterListMore?:more;
|
||||
|
||||
FunctionReturnType -> arrow Type;
|
||||
|
||||
Literal -> LiteralInteger;
|
||||
LiteralInteger -> hex_int_l;
|
||||
|
||||
Module -> ModuleStatement? ModuleItems;
|
||||
|
||||
ModuleItem -> FunctionDefinition;
|
||||
|
||||
ModuleItems -> ;
|
||||
ModuleItems -> ModuleItems ModuleItem;
|
||||
|
||||
ModulePath -> ident;
|
||||
|
||||
ModuleStatement -> module ModulePath semicolon;
|
||||
|
||||
ReturnStatement -> return Expression?:exp0 semicolon;
|
||||
|
||||
Statements -> ;
|
||||
Statements -> Statements Statement;
|
||||
Statement -> Expression semicolon;
|
||||
Statement -> ReturnStatement;
|
||||
|
||||
Type -> TypeBase;
|
||||
|
||||
TypeBase -> byte;
|
||||
TypeBase -> ubyte;
|
||||
TypeBase -> short;
|
||||
TypeBase -> ushort;
|
||||
TypeBase -> int;
|
||||
TypeBase -> uint;
|
||||
TypeBase -> long;
|
||||
TypeBase -> ulong;
|
||||
TypeBase -> size_t;
|
||||
TypeBase -> ssize_t;
|
||||
177
spec/ast_node_memory_remains.d.propane
Normal file
177
spec/ast_node_memory_remains.d.propane
Normal file
@ -0,0 +1,177 @@
|
||||
ast;
|
||||
ast_prefix P;
|
||||
|
||||
<<
|
||||
import std.bigint;
|
||||
|
||||
private string stringvalue;
|
||||
|
||||
union TokenVal
|
||||
{
|
||||
BigInt bi;
|
||||
string s;
|
||||
double dou;
|
||||
}
|
||||
>>
|
||||
|
||||
ptype TokenVal;
|
||||
|
||||
# Keywords.
|
||||
token byte;
|
||||
token def;
|
||||
token int;
|
||||
token long;
|
||||
token module;
|
||||
token return;
|
||||
token short;
|
||||
token size_t;
|
||||
token ssize_t;
|
||||
token ubyte;
|
||||
token uint;
|
||||
token ulong;
|
||||
token ushort;
|
||||
|
||||
# Symbols.
|
||||
token arrow /->/;
|
||||
token comma /,/;
|
||||
token lbrace /\{/;
|
||||
token lparen /\(/;
|
||||
token rbrace /\}/;
|
||||
token rparen /\)/;
|
||||
token semicolon /;/;
|
||||
|
||||
# Integer literals.
|
||||
token hex_int_l /0[xX][0-9a-fA-F][0-9a-fA-F_]*/ <<
|
||||
$$.bi = BigInt(match[0..3]);
|
||||
foreach (c; match[3..$])
|
||||
{
|
||||
if (('0' <= c) && (c <= '9'))
|
||||
{
|
||||
$$.bi *= 0x10;
|
||||
$$.bi += (c - '0');
|
||||
}
|
||||
if (('a' <= c) && (c <= 'f'))
|
||||
{
|
||||
$$.bi *= 0x10;
|
||||
$$.bi += (c - 'a' + 10);
|
||||
}
|
||||
if (('A' <= c) && (c <= 'F'))
|
||||
{
|
||||
$$.bi *= 0x10;
|
||||
$$.bi += (c - 'A' + 10);
|
||||
}
|
||||
}
|
||||
>>
|
||||
|
||||
# Identifier.
|
||||
token ident /\$?[a-zA-Z_][a-zA-Z_0-9]*\??/ <<
|
||||
if (match[0] == '$')
|
||||
{
|
||||
$$.s = match[1..$];
|
||||
}
|
||||
else
|
||||
{
|
||||
$$.s = match;
|
||||
}
|
||||
$mode(default);
|
||||
return $token(ident);
|
||||
>>
|
||||
|
||||
# Comments.
|
||||
drop /#.*/;
|
||||
|
||||
# Whitespace.
|
||||
drop /[ \r\n]*/;
|
||||
|
||||
start Module;
|
||||
|
||||
# Assignment operators - right associative
|
||||
Expression -> Expression_Or:exp0;
|
||||
|
||||
# Logical OR operator - left associative
|
||||
Expression_Or -> Expression_And:exp0;
|
||||
|
||||
# Logical AND operator - left associative
|
||||
Expression_And -> Expression_Comp:exp0;
|
||||
|
||||
# Equality operators - left associative
|
||||
Expression_Comp -> Expression_Relational:exp0;
|
||||
|
||||
# Relational operators - left associative
|
||||
Expression_Relational -> Expression_REMatch:exp0;
|
||||
|
||||
# Regular expression - left associative
|
||||
Expression_REMatch -> Expression_BinOr:exp0;
|
||||
|
||||
# Binary OR operator - left associative
|
||||
Expression_BinOr -> Expression_Xor:exp0;
|
||||
|
||||
# Binary XOR operator - left associative
|
||||
Expression_Xor -> Expression_BinAnd:exp0;
|
||||
|
||||
# Binary AND operator - left associative
|
||||
Expression_BinAnd -> Expression_BitShift:exp0;
|
||||
|
||||
# Bit shift operators - left associative
|
||||
Expression_BitShift -> Expression_Plus:exp0;
|
||||
|
||||
# Add/subtract operators - left associative
|
||||
Expression_Plus -> Expression_Mul:exp0;
|
||||
|
||||
# Multiplication/divide/modulus operators - left associative
|
||||
Expression_Mul -> Expression_Range:exp0;
|
||||
|
||||
# Range construction operators - left associative
|
||||
Expression_Range -> Expression_UnaryPrefix:exp0;
|
||||
|
||||
# Unary prefix operators
|
||||
Expression_UnaryPrefix -> Expression_Dot:exp0;
|
||||
|
||||
# Postfix operators
|
||||
Expression_Dot -> Expression_Ident:exp0;
|
||||
Expression_Dot -> Expression_Dot:exp1 lparen rparen;
|
||||
|
||||
# Literals, identifiers, and parenthesized expressions
|
||||
Expression_Ident -> Literal;
|
||||
Expression_Ident -> ident;
|
||||
|
||||
FunctionDefinition -> def ident:name lparen FunctionParameterList?:parameters rparen FunctionReturnType?:returntype lbrace Statements rbrace;
|
||||
|
||||
FunctionParameterList -> ident:name Type:type FunctionParameterListMore?:more;
|
||||
FunctionParameterListMore -> comma ident:name Type:type FunctionParameterListMore?:more;
|
||||
|
||||
FunctionReturnType -> arrow Type;
|
||||
|
||||
Literal -> LiteralInteger;
|
||||
LiteralInteger -> hex_int_l;
|
||||
|
||||
Module -> ModuleStatement? ModuleItems;
|
||||
|
||||
ModuleItem -> FunctionDefinition;
|
||||
|
||||
ModuleItems -> ;
|
||||
ModuleItems -> ModuleItems ModuleItem;
|
||||
|
||||
ModulePath -> ident;
|
||||
|
||||
ModuleStatement -> module ModulePath semicolon;
|
||||
|
||||
ReturnStatement -> return Expression?:exp0 semicolon;
|
||||
|
||||
Statements -> ;
|
||||
Statements -> Statements Statement;
|
||||
Statement -> Expression semicolon;
|
||||
Statement -> ReturnStatement;
|
||||
|
||||
Type -> TypeBase;
|
||||
|
||||
TypeBase -> byte;
|
||||
TypeBase -> ubyte;
|
||||
TypeBase -> short;
|
||||
TypeBase -> ushort;
|
||||
TypeBase -> int;
|
||||
TypeBase -> uint;
|
||||
TypeBase -> long;
|
||||
TypeBase -> ulong;
|
||||
TypeBase -> size_t;
|
||||
TypeBase -> ssize_t;
|
||||
@ -74,7 +74,7 @@ EOF
|
||||
when "c"
|
||||
result = system(*%w[gcc -Wall -o spec/run/testparser -Ispec -Ispec/run], *parsers, *test_files, "spec/testutils.c", "-lm")
|
||||
when "d"
|
||||
result = system(*%w[ldc2 --unittest -of spec/run/testparser -Ispec], *parsers, *test_files, "spec/testutils.d")
|
||||
result = system(*%w[ldc2 -g --unittest -of spec/run/testparser -Ispec], *parsers, *test_files, "spec/testutils.d")
|
||||
end
|
||||
expect(result).to be_truthy
|
||||
end
|
||||
@ -1391,6 +1391,15 @@ EOF
|
||||
expect(results.status).to eq 0
|
||||
expect(results.stdout).to match /first is foo1.*second is bar2/m
|
||||
end
|
||||
|
||||
it "does not free memory allocated for AST nodes" do
|
||||
write_grammar(File.read("spec/ast_node_memory_remains.#{language}.propane"))
|
||||
run_propane(language: language)
|
||||
compile("spec/test_ast_node_memory_remains.#{language}", language: language)
|
||||
results = run_test
|
||||
expect(results.stderr).to eq ""
|
||||
expect(results.status).to eq 0
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
415
spec/test_ast_node_memory_remains.c
Normal file
415
spec/test_ast_node_memory_remains.c
Normal file
@ -0,0 +1,415 @@
|
||||
#include "testparser.h"
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "testutils.h"
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
const char * input =
|
||||
"# 0\n"
|
||||
"def byte_val() -> byte\n"
|
||||
"{\n"
|
||||
" return 0x42;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"# 1\n"
|
||||
"def short_val() -> short\n"
|
||||
"{\n"
|
||||
" return 0x4242;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"# 2\n"
|
||||
"def int_val() -> int\n"
|
||||
"{\n"
|
||||
" return 0x42424242;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"# 3\n"
|
||||
"def long_val() -> long\n"
|
||||
"{\n"
|
||||
" return 0x4242_4242_4242_4242;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"# 4\n"
|
||||
"def ssize_t_val() -> ssize_t\n"
|
||||
"{\n"
|
||||
" return 0x42424242;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"# 5\n"
|
||||
"def byte_to_short() -> short\n"
|
||||
"{\n"
|
||||
" return byte_val();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"# 6\n"
|
||||
"def byte_to_int() -> int\n"
|
||||
"{\n"
|
||||
" return byte_val();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"# 7\n"
|
||||
"def byte_to_long() -> long\n"
|
||||
"{\n"
|
||||
" return byte_val();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"# 8\n"
|
||||
"def byte_to_ssize_t() -> ssize_t\n"
|
||||
"{\n"
|
||||
" return byte_val();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"# 9\n"
|
||||
"def short_to_byte() -> byte\n"
|
||||
"{\n"
|
||||
" return short_val();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"# 10\n"
|
||||
"def short_to_int() -> int\n"
|
||||
"{\n"
|
||||
" return short_val();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"# 11\n"
|
||||
"def short_to_long() -> long\n"
|
||||
"{\n"
|
||||
" return short_val();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"# 12\n"
|
||||
"def short_to_ssize_t() -> ssize_t\n"
|
||||
"{\n"
|
||||
" return short_val();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"# 13\n"
|
||||
"def int_to_byte() -> byte\n"
|
||||
"{\n"
|
||||
" return int_val();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"# 14\n"
|
||||
"def int_to_short() -> short\n"
|
||||
"{\n"
|
||||
" return int_val();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"# 15\n"
|
||||
"def int_to_long() -> long\n"
|
||||
"{\n"
|
||||
" return int_val();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"# 16\n"
|
||||
"def int_to_ssize_t() -> ssize_t\n"
|
||||
"{\n"
|
||||
" return int_val();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"# 17\n"
|
||||
"def long_to_byte() -> byte\n"
|
||||
"{\n"
|
||||
" return long_val();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"# 18\n"
|
||||
"def long_to_short() -> short\n"
|
||||
"{\n"
|
||||
" return long_val();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"# 19\n"
|
||||
"def long_to_int() -> int\n"
|
||||
"{\n"
|
||||
" return long_val();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"# 20\n"
|
||||
"def long_to_ssize_t() -> ssize_t\n"
|
||||
"{\n"
|
||||
" return long_val();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"# 21\n"
|
||||
"def ssize_t_to_byte() -> byte\n"
|
||||
"{\n"
|
||||
" return ssize_t_val();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"# 22\n"
|
||||
"def ssize_t_to_short() -> short\n"
|
||||
"{\n"
|
||||
" return ssize_t_val();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"# 23\n"
|
||||
"def ssize_t_to_int() -> int\n"
|
||||
"{\n"
|
||||
" return ssize_t_val();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"# 24\n"
|
||||
"def ssize_t_to_long() -> long\n"
|
||||
"{\n"
|
||||
" return ssize_t_val();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"# 25\n"
|
||||
"def ubyte_val() -> ubyte\n"
|
||||
"{\n"
|
||||
" return 0x42;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"# 26\n"
|
||||
"def ushort_val() -> ushort\n"
|
||||
"{\n"
|
||||
" return 0x4242;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"# 27\n"
|
||||
"def uint_val() -> uint\n"
|
||||
"{\n"
|
||||
" return 0x42424242;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"# 28\n"
|
||||
"def ulong_val() -> ulong\n"
|
||||
"{\n"
|
||||
" return 0x4242_4242_4242_4242;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"# 29\n"
|
||||
"def size_t_val() -> size_t\n"
|
||||
"{\n"
|
||||
" return 0x42424242;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"# 30\n"
|
||||
"def ubyte_to_ushort() -> ushort\n"
|
||||
"{\n"
|
||||
" return ubyte_val();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"# 31\n"
|
||||
"def ubyte_to_uint() -> uint\n"
|
||||
"{\n"
|
||||
" return ubyte_val();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"# 32\n"
|
||||
"def ubyte_to_ulong() -> ulong\n"
|
||||
"{\n"
|
||||
" return ubyte_val();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"# 33\n"
|
||||
"def ubyte_to_size_t() -> size_t\n"
|
||||
"{\n"
|
||||
" return ubyte_val();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"# 34\n"
|
||||
"def ushort_to_ubyte() -> ubyte\n"
|
||||
"{\n"
|
||||
" return ushort_val();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"# 35\n"
|
||||
"def ushort_to_uint() -> uint\n"
|
||||
"{\n"
|
||||
" return ushort_val();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"# 36\n"
|
||||
"def ushort_to_ulong() -> ulong\n"
|
||||
"{\n"
|
||||
" return ushort_val();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"# 37\n"
|
||||
"def ushort_to_size_t() -> size_t\n"
|
||||
"{\n"
|
||||
" return ushort_val();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"# 38\n"
|
||||
"def uint_to_ubyte() -> ubyte\n"
|
||||
"{\n"
|
||||
" return uint_val();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"# 39\n"
|
||||
"def uint_to_ushort() -> ushort\n"
|
||||
"{\n"
|
||||
" return uint_val();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"# 40\n"
|
||||
"def uint_to_ulong() -> ulong\n"
|
||||
"{\n"
|
||||
" return uint_val();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"# 41\n"
|
||||
"def uint_to_size_t() -> size_t\n"
|
||||
"{\n"
|
||||
" return uint_val();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"# 42\n"
|
||||
"def ulong_to_ubyte() -> ubyte\n"
|
||||
"{\n"
|
||||
" return ulong_val();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"# 43\n"
|
||||
"def ulong_to_ushort() -> ushort\n"
|
||||
"{\n"
|
||||
" return ulong_val();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"# 44\n"
|
||||
"def ulong_to_uint() -> uint\n"
|
||||
"{\n"
|
||||
" return ulong_val();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"# 45\n"
|
||||
"def ulong_to_size_t() -> size_t\n"
|
||||
"{\n"
|
||||
" return ulong_val();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"# 46\n"
|
||||
"def size_t_to_ubyte() -> ubyte\n"
|
||||
"{\n"
|
||||
" return size_t_val();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"# 47\n"
|
||||
"def size_t_to_ushort() -> ushort\n"
|
||||
"{\n"
|
||||
" return size_t_val();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"# 48\n"
|
||||
"def size_t_to_int() -> int\n"
|
||||
"{\n"
|
||||
" return size_t_val();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"# 49\n"
|
||||
"def size_t_to_ulong() -> ulong\n"
|
||||
"{\n"
|
||||
" return size_t_val();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"# 50\n"
|
||||
"def main() -> int\n"
|
||||
"{\n"
|
||||
" return int_val();\n"
|
||||
"}\n";
|
||||
struct
|
||||
{
|
||||
const char * name;
|
||||
p_token_t token;
|
||||
} expected[] = {
|
||||
{"byte_val", TOKEN_byte},
|
||||
{"short_val", TOKEN_short},
|
||||
{"int_val", TOKEN_int},
|
||||
{"long_val", TOKEN_long},
|
||||
{"ssize_t_val", TOKEN_ssize_t},
|
||||
{"byte_to_short", TOKEN_short},
|
||||
{"byte_to_int", TOKEN_int},
|
||||
{"byte_to_long", TOKEN_long},
|
||||
{"byte_to_ssize_t", TOKEN_ssize_t},
|
||||
{"short_to_byte", TOKEN_byte},
|
||||
{"short_to_int", TOKEN_int},
|
||||
{"short_to_long", TOKEN_long},
|
||||
{"short_to_ssize_t", TOKEN_ssize_t},
|
||||
{"int_to_byte", TOKEN_byte},
|
||||
{"int_to_short", TOKEN_short},
|
||||
{"int_to_long", TOKEN_long},
|
||||
{"int_to_ssize_t", TOKEN_ssize_t},
|
||||
{"long_to_byte", TOKEN_byte},
|
||||
{"long_to_short", TOKEN_short},
|
||||
{"long_to_int", TOKEN_int},
|
||||
{"long_to_ssize_t", TOKEN_ssize_t},
|
||||
{"ssize_t_to_byte", TOKEN_byte},
|
||||
{"ssize_t_to_short", TOKEN_short},
|
||||
{"ssize_t_to_int", TOKEN_int},
|
||||
{"ssize_t_to_long", TOKEN_long},
|
||||
{"ubyte_val", TOKEN_ubyte},
|
||||
{"ushort_val", TOKEN_ushort},
|
||||
{"uint_val", TOKEN_uint},
|
||||
{"ulong_val", TOKEN_ulong},
|
||||
{"size_t_val", TOKEN_size_t},
|
||||
{"ubyte_to_ushort", TOKEN_ushort},
|
||||
{"ubyte_to_uint", TOKEN_uint},
|
||||
{"ubyte_to_ulong", TOKEN_ulong},
|
||||
{"ubyte_to_size_t", TOKEN_size_t},
|
||||
{"ushort_to_ubyte", TOKEN_ubyte},
|
||||
{"ushort_to_uint", TOKEN_uint},
|
||||
{"ushort_to_ulong", TOKEN_ulong},
|
||||
{"ushort_to_size_t", TOKEN_size_t},
|
||||
{"uint_to_ubyte", TOKEN_ubyte},
|
||||
{"uint_to_ushort", TOKEN_ushort},
|
||||
{"uint_to_ulong", TOKEN_ulong},
|
||||
{"uint_to_size_t", TOKEN_size_t},
|
||||
{"ulong_to_ubyte", TOKEN_ubyte},
|
||||
{"ulong_to_ushort", TOKEN_ushort},
|
||||
{"ulong_to_uint", TOKEN_uint},
|
||||
{"ulong_to_size_t", TOKEN_size_t},
|
||||
{"size_t_to_ubyte", TOKEN_ubyte},
|
||||
{"size_t_to_ushort", TOKEN_ushort},
|
||||
{"size_t_to_int", TOKEN_int},
|
||||
{"size_t_to_ulong", TOKEN_ulong},
|
||||
{"main", TOKEN_int},
|
||||
};
|
||||
p_context_t context;
|
||||
p_context_init(&context, (const uint8_t *)input, strlen(input));
|
||||
size_t result = p_parse(&context);
|
||||
assert_eq(P_SUCCESS, result);
|
||||
PModule * pmod = p_result(&context);
|
||||
PModuleItems * pmis = pmod->pModuleItems;
|
||||
PFunctionDefinition ** pfds;
|
||||
size_t n_pfds = 0u;
|
||||
while (pmis != NULL)
|
||||
{
|
||||
PModuleItem * pmi = pmis->pModuleItem;
|
||||
if (pmi->pFunctionDefinition != NULL)
|
||||
{
|
||||
n_pfds++;
|
||||
}
|
||||
pmis = pmis->pModuleItems;
|
||||
}
|
||||
pfds = malloc(n_pfds * sizeof(PModuleItems *));
|
||||
pmis = pmod->pModuleItems;
|
||||
size_t pfd_i = n_pfds;
|
||||
while (pmis != NULL)
|
||||
{
|
||||
PModuleItem * pmi = pmis->pModuleItem;
|
||||
PFunctionDefinition * pfd = pmi->pFunctionDefinition;
|
||||
if (pfd != NULL)
|
||||
{
|
||||
pfd_i--;
|
||||
assert(pfd_i < n_pfds);
|
||||
pfds[pfd_i] = pfd;
|
||||
}
|
||||
pmis = pmis->pModuleItems;
|
||||
}
|
||||
assert_eq(51, n_pfds);
|
||||
for (size_t i = 0; i < n_pfds; i++)
|
||||
{
|
||||
if (strncmp(expected[i].name, (const char *)pfds[i]->name->pvalue.s, strlen(expected[i].name)) != 0 ||
|
||||
(expected[i].token != pfds[i]->returntype->pType->pTypeBase->pToken1->token))
|
||||
{
|
||||
fprintf(stderr, "Index %lu: expected %s/%u, got %u\n", i, expected[i].name, expected[i].token, pfds[i]->returntype->pType->pTypeBase->pToken1->token);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
408
spec/test_ast_node_memory_remains.d
Normal file
408
spec/test_ast_node_memory_remains.d
Normal file
@ -0,0 +1,408 @@
|
||||
import testparser;
|
||||
import std.stdio;
|
||||
import testutils;
|
||||
|
||||
int main()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
string input = "
|
||||
# 0
|
||||
def byte_val() -> byte
|
||||
{
|
||||
return 0x42;
|
||||
}
|
||||
|
||||
# 1
|
||||
def short_val() -> short
|
||||
{
|
||||
return 0x4242;
|
||||
}
|
||||
|
||||
# 2
|
||||
def int_val() -> int
|
||||
{
|
||||
return 0x42424242;
|
||||
}
|
||||
|
||||
# 3
|
||||
def long_val() -> long
|
||||
{
|
||||
return 0x4242_4242_4242_4242;
|
||||
}
|
||||
|
||||
# 4
|
||||
def ssize_t_val() -> ssize_t
|
||||
{
|
||||
return 0x42424242;
|
||||
}
|
||||
|
||||
# 5
|
||||
def byte_to_short() -> short
|
||||
{
|
||||
return byte_val();
|
||||
}
|
||||
|
||||
# 6
|
||||
def byte_to_int() -> int
|
||||
{
|
||||
return byte_val();
|
||||
}
|
||||
|
||||
# 7
|
||||
def byte_to_long() -> long
|
||||
{
|
||||
return byte_val();
|
||||
}
|
||||
|
||||
# 8
|
||||
def byte_to_ssize_t() -> ssize_t
|
||||
{
|
||||
return byte_val();
|
||||
}
|
||||
|
||||
# 9
|
||||
def short_to_byte() -> byte
|
||||
{
|
||||
return short_val();
|
||||
}
|
||||
|
||||
# 10
|
||||
def short_to_int() -> int
|
||||
{
|
||||
return short_val();
|
||||
}
|
||||
|
||||
# 11
|
||||
def short_to_long() -> long
|
||||
{
|
||||
return short_val();
|
||||
}
|
||||
|
||||
# 12
|
||||
def short_to_ssize_t() -> ssize_t
|
||||
{
|
||||
return short_val();
|
||||
}
|
||||
|
||||
# 13
|
||||
def int_to_byte() -> byte
|
||||
{
|
||||
return int_val();
|
||||
}
|
||||
|
||||
# 14
|
||||
def int_to_short() -> short
|
||||
{
|
||||
return int_val();
|
||||
}
|
||||
|
||||
# 15
|
||||
def int_to_long() -> long
|
||||
{
|
||||
return int_val();
|
||||
}
|
||||
|
||||
# 16
|
||||
def int_to_ssize_t() -> ssize_t
|
||||
{
|
||||
return int_val();
|
||||
}
|
||||
|
||||
# 17
|
||||
def long_to_byte() -> byte
|
||||
{
|
||||
return long_val();
|
||||
}
|
||||
|
||||
# 18
|
||||
def long_to_short() -> short
|
||||
{
|
||||
return long_val();
|
||||
}
|
||||
|
||||
# 19
|
||||
def long_to_int() -> int
|
||||
{
|
||||
return long_val();
|
||||
}
|
||||
|
||||
# 20
|
||||
def long_to_ssize_t() -> ssize_t
|
||||
{
|
||||
return long_val();
|
||||
}
|
||||
|
||||
# 21
|
||||
def ssize_t_to_byte() -> byte
|
||||
{
|
||||
return ssize_t_val();
|
||||
}
|
||||
|
||||
# 22
|
||||
def ssize_t_to_short() -> short
|
||||
{
|
||||
return ssize_t_val();
|
||||
}
|
||||
|
||||
# 23
|
||||
def ssize_t_to_int() -> int
|
||||
{
|
||||
return ssize_t_val();
|
||||
}
|
||||
|
||||
# 24
|
||||
def ssize_t_to_long() -> long
|
||||
{
|
||||
return ssize_t_val();
|
||||
}
|
||||
|
||||
# 25
|
||||
def ubyte_val() -> ubyte
|
||||
{
|
||||
return 0x42;
|
||||
}
|
||||
|
||||
# 26
|
||||
def ushort_val() -> ushort
|
||||
{
|
||||
return 0x4242;
|
||||
}
|
||||
|
||||
# 27
|
||||
def uint_val() -> uint
|
||||
{
|
||||
return 0x42424242;
|
||||
}
|
||||
|
||||
# 28
|
||||
def ulong_val() -> ulong
|
||||
{
|
||||
return 0x4242_4242_4242_4242;
|
||||
}
|
||||
|
||||
# 29
|
||||
def size_t_val() -> size_t
|
||||
{
|
||||
return 0x42424242;
|
||||
}
|
||||
|
||||
# 30
|
||||
def ubyte_to_ushort() -> ushort
|
||||
{
|
||||
return ubyte_val();
|
||||
}
|
||||
|
||||
# 31
|
||||
def ubyte_to_uint() -> uint
|
||||
{
|
||||
return ubyte_val();
|
||||
}
|
||||
|
||||
# 32
|
||||
def ubyte_to_ulong() -> ulong
|
||||
{
|
||||
return ubyte_val();
|
||||
}
|
||||
|
||||
# 33
|
||||
def ubyte_to_size_t() -> size_t
|
||||
{
|
||||
return ubyte_val();
|
||||
}
|
||||
|
||||
# 34
|
||||
def ushort_to_ubyte() -> ubyte
|
||||
{
|
||||
return ushort_val();
|
||||
}
|
||||
|
||||
# 35
|
||||
def ushort_to_uint() -> uint
|
||||
{
|
||||
return ushort_val();
|
||||
}
|
||||
|
||||
# 36
|
||||
def ushort_to_ulong() -> ulong
|
||||
{
|
||||
return ushort_val();
|
||||
}
|
||||
|
||||
# 37
|
||||
def ushort_to_size_t() -> size_t
|
||||
{
|
||||
return ushort_val();
|
||||
}
|
||||
|
||||
# 38
|
||||
def uint_to_ubyte() -> ubyte
|
||||
{
|
||||
return uint_val();
|
||||
}
|
||||
|
||||
# 39
|
||||
def uint_to_ushort() -> ushort
|
||||
{
|
||||
return uint_val();
|
||||
}
|
||||
|
||||
# 40
|
||||
def uint_to_ulong() -> ulong
|
||||
{
|
||||
return uint_val();
|
||||
}
|
||||
|
||||
# 41
|
||||
def uint_to_size_t() -> size_t
|
||||
{
|
||||
return uint_val();
|
||||
}
|
||||
|
||||
# 42
|
||||
def ulong_to_ubyte() -> ubyte
|
||||
{
|
||||
return ulong_val();
|
||||
}
|
||||
|
||||
# 43
|
||||
def ulong_to_ushort() -> ushort
|
||||
{
|
||||
return ulong_val();
|
||||
}
|
||||
|
||||
# 44
|
||||
def ulong_to_uint() -> uint
|
||||
{
|
||||
return ulong_val();
|
||||
}
|
||||
|
||||
# 45
|
||||
def ulong_to_size_t() -> size_t
|
||||
{
|
||||
return ulong_val();
|
||||
}
|
||||
|
||||
# 46
|
||||
def size_t_to_ubyte() -> ubyte
|
||||
{
|
||||
return size_t_val();
|
||||
}
|
||||
|
||||
# 47
|
||||
def size_t_to_ushort() -> ushort
|
||||
{
|
||||
return size_t_val();
|
||||
}
|
||||
|
||||
# 48
|
||||
def size_t_to_int() -> int
|
||||
{
|
||||
return size_t_val();
|
||||
}
|
||||
|
||||
# 49
|
||||
def size_t_to_ulong() -> ulong
|
||||
{
|
||||
return size_t_val();
|
||||
}
|
||||
|
||||
# 50
|
||||
def main() -> int
|
||||
{
|
||||
return int_val();
|
||||
}
|
||||
";
|
||||
struct Expected
|
||||
{
|
||||
string name;
|
||||
p_token_t token;
|
||||
}
|
||||
Expected[] expected = [
|
||||
Expected("byte_val", TOKEN_byte),
|
||||
Expected("short_val", TOKEN_short),
|
||||
Expected("int_val", TOKEN_int),
|
||||
Expected("long_val", TOKEN_long),
|
||||
Expected("ssize_t_val", TOKEN_ssize_t),
|
||||
Expected("byte_to_short", TOKEN_short),
|
||||
Expected("byte_to_int", TOKEN_int),
|
||||
Expected("byte_to_long", TOKEN_long),
|
||||
Expected("byte_to_ssize_t", TOKEN_ssize_t),
|
||||
Expected("short_to_byte", TOKEN_byte),
|
||||
Expected("short_to_int", TOKEN_int),
|
||||
Expected("short_to_long", TOKEN_long),
|
||||
Expected("short_to_ssize_t", TOKEN_ssize_t),
|
||||
Expected("int_to_byte", TOKEN_byte),
|
||||
Expected("int_to_short", TOKEN_short),
|
||||
Expected("int_to_long", TOKEN_long),
|
||||
Expected("int_to_ssize_t", TOKEN_ssize_t),
|
||||
Expected("long_to_byte", TOKEN_byte),
|
||||
Expected("long_to_short", TOKEN_short),
|
||||
Expected("long_to_int", TOKEN_int),
|
||||
Expected("long_to_ssize_t", TOKEN_ssize_t),
|
||||
Expected("ssize_t_to_byte", TOKEN_byte),
|
||||
Expected("ssize_t_to_short", TOKEN_short),
|
||||
Expected("ssize_t_to_int", TOKEN_int),
|
||||
Expected("ssize_t_to_long", TOKEN_long),
|
||||
Expected("ubyte_val", TOKEN_ubyte),
|
||||
Expected("ushort_val", TOKEN_ushort),
|
||||
Expected("uint_val", TOKEN_uint),
|
||||
Expected("ulong_val", TOKEN_ulong),
|
||||
Expected("size_t_val", TOKEN_size_t),
|
||||
Expected("ubyte_to_ushort", TOKEN_ushort),
|
||||
Expected("ubyte_to_uint", TOKEN_uint),
|
||||
Expected("ubyte_to_ulong", TOKEN_ulong),
|
||||
Expected("ubyte_to_size_t", TOKEN_size_t),
|
||||
Expected("ushort_to_ubyte", TOKEN_ubyte),
|
||||
Expected("ushort_to_uint", TOKEN_uint),
|
||||
Expected("ushort_to_ulong", TOKEN_ulong),
|
||||
Expected("ushort_to_size_t", TOKEN_size_t),
|
||||
Expected("uint_to_ubyte", TOKEN_ubyte),
|
||||
Expected("uint_to_ushort", TOKEN_ushort),
|
||||
Expected("uint_to_ulong", TOKEN_ulong),
|
||||
Expected("uint_to_size_t", TOKEN_size_t),
|
||||
Expected("ulong_to_ubyte", TOKEN_ubyte),
|
||||
Expected("ulong_to_ushort", TOKEN_ushort),
|
||||
Expected("ulong_to_uint", TOKEN_uint),
|
||||
Expected("ulong_to_size_t", TOKEN_size_t),
|
||||
Expected("size_t_to_ubyte", TOKEN_ubyte),
|
||||
Expected("size_t_to_ushort", TOKEN_ushort),
|
||||
Expected("size_t_to_int", TOKEN_int),
|
||||
Expected("size_t_to_ulong", TOKEN_ulong),
|
||||
Expected("main", TOKEN_int),
|
||||
];
|
||||
p_context_t context;
|
||||
p_context_init(&context, input);
|
||||
size_t result = p_parse(&context);
|
||||
assert_eq(P_SUCCESS, result);
|
||||
PModule * pmod = p_result(&context);
|
||||
PModuleItems * pmis = pmod.pModuleItems;
|
||||
PFunctionDefinition *[] pfds;
|
||||
while (pmis !is null)
|
||||
{
|
||||
PModuleItem * pmi = pmis.pModuleItem;
|
||||
if (pmi is null)
|
||||
{
|
||||
stderr.writeln("pmi is null!!!?");
|
||||
assert(0);
|
||||
}
|
||||
PFunctionDefinition * pfd = pmi.pFunctionDefinition;
|
||||
if (pfd !is null)
|
||||
{
|
||||
pfds = [pfd] ~ pfds;
|
||||
}
|
||||
pmis = pmis.pModuleItems;
|
||||
}
|
||||
assert_eq(51, pfds.length);
|
||||
for (size_t i = 0; i < pfds.length; i++)
|
||||
{
|
||||
if ((expected[i].name != pfds[i].name.pvalue.s) ||
|
||||
(expected[i].token != pfds[i].returntype.pType.pTypeBase.pToken1.token))
|
||||
{
|
||||
stderr.writeln("Index ", i, ": expected ", expected[i].name, "/", expected[i].token, ", got ", pfds[i].name.pvalue.s, "/", pfds[i].returntype.pType.pTypeBase.pToken1.token);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user