mirror of
https://github.com/krgamestudios/Toy.git
synced 2026-04-15 14:54:07 +10:00
Resolved #45, Exports region removed
This commit is contained in:
@@ -129,11 +129,6 @@ void freeASTNodeCustom(ASTNode* node, bool freeSelf) {
|
|||||||
freeLiteral(node->import.identifier);
|
freeLiteral(node->import.identifier);
|
||||||
freeLiteral(node->import.alias);
|
freeLiteral(node->import.alias);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AST_NODE_EXPORT:
|
|
||||||
freeLiteral(node->export.identifier);
|
|
||||||
freeLiteral(node->export.alias);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (freeSelf) {
|
if (freeSelf) {
|
||||||
@@ -371,13 +366,3 @@ void emitASTNodeImport(ASTNode** nodeHandle, Literal identifier, Literal alias)
|
|||||||
|
|
||||||
*nodeHandle = tmp;
|
*nodeHandle = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void emitASTNodeExport(ASTNode** nodeHandle, Literal identifier, Literal alias) {
|
|
||||||
ASTNode* tmp = ALLOCATE(ASTNode, 1);
|
|
||||||
|
|
||||||
tmp->type = AST_NODE_EXPORT;
|
|
||||||
tmp->export.identifier = copyLiteral(identifier);
|
|
||||||
tmp->export.alias = copyLiteral(alias);
|
|
||||||
|
|
||||||
*nodeHandle = tmp;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -32,8 +32,7 @@ typedef enum ASTNodeType {
|
|||||||
AST_NODE_POSTFIX_INCREMENT, //increment a variable
|
AST_NODE_POSTFIX_INCREMENT, //increment a variable
|
||||||
AST_NODE_PREFIX_DECREMENT, //decrement a variable
|
AST_NODE_PREFIX_DECREMENT, //decrement a variable
|
||||||
AST_NODE_POSTFIX_DECREMENT, //decrement a variable
|
AST_NODE_POSTFIX_DECREMENT, //decrement a variable
|
||||||
AST_NODE_IMPORT, //import a variable
|
AST_NODE_IMPORT, //import a library
|
||||||
AST_NODE_EXPORT, //export a variable
|
|
||||||
} ASTNodeType;
|
} ASTNodeType;
|
||||||
|
|
||||||
//literals
|
//literals
|
||||||
@@ -219,9 +218,8 @@ typedef struct NodePostfixDecrement {
|
|||||||
Literal identifier;
|
Literal identifier;
|
||||||
} NodePostfixDecrement;
|
} NodePostfixDecrement;
|
||||||
|
|
||||||
//import/export a variable
|
//import a library
|
||||||
void emitASTNodeImport(ASTNode** nodeHandle, Literal identifier, Literal alias);
|
void emitASTNodeImport(ASTNode** nodeHandle, Literal identifier, Literal alias);
|
||||||
void emitASTNodeExport(ASTNode** nodeHandle, Literal identifier, Literal alias);
|
|
||||||
|
|
||||||
typedef struct NodeImport {
|
typedef struct NodeImport {
|
||||||
ASTNodeType type;
|
ASTNodeType type;
|
||||||
@@ -229,12 +227,6 @@ typedef struct NodeImport {
|
|||||||
Literal alias;
|
Literal alias;
|
||||||
} NodeImport;
|
} NodeImport;
|
||||||
|
|
||||||
typedef struct NodeExport {
|
|
||||||
ASTNodeType type;
|
|
||||||
Literal identifier;
|
|
||||||
Literal alias;
|
|
||||||
} NodeExport;
|
|
||||||
|
|
||||||
union _node {
|
union _node {
|
||||||
ASTNodeType type;
|
ASTNodeType type;
|
||||||
NodeLiteral atomic;
|
NodeLiteral atomic;
|
||||||
@@ -260,7 +252,6 @@ union _node {
|
|||||||
NodePostfixIncrement postfixIncrement;
|
NodePostfixIncrement postfixIncrement;
|
||||||
NodePostfixDecrement postfixDecrement;
|
NodePostfixDecrement postfixDecrement;
|
||||||
NodeImport import;
|
NodeImport import;
|
||||||
NodeExport export;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
TOY_API void freeASTNode(ASTNode* node);
|
TOY_API void freeASTNode(ASTNode* node);
|
||||||
|
|||||||
@@ -846,16 +846,6 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, ASTNode* node, void* br
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AST_NODE_EXPORT: {
|
|
||||||
//push the identifier, and the alias
|
|
||||||
writeLiteralToCompiler(compiler, node->import.identifier);
|
|
||||||
writeLiteralToCompiler(compiler, node->import.alias);
|
|
||||||
|
|
||||||
//push the import opcode
|
|
||||||
compiler->bytecode[compiler->count++] = (unsigned char)OP_EXPORT; //1 byte
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AST_NODE_INDEX: {
|
case AST_NODE_INDEX: {
|
||||||
//pass to the child nodes, then embed the opcode
|
//pass to the child nodes, then embed the opcode
|
||||||
|
|
||||||
|
|||||||
@@ -1227,8 +1227,6 @@ bool callLiteralFn(Interpreter* interpreter, Literal func, LiteralArray* argumen
|
|||||||
inner.depth = interpreter->depth + 1;
|
inner.depth = interpreter->depth + 1;
|
||||||
inner.panic = false;
|
inner.panic = false;
|
||||||
initLiteralArray(&inner.stack);
|
initLiteralArray(&inner.stack);
|
||||||
inner.exports = interpreter->exports;
|
|
||||||
inner.exportTypes = interpreter->exportTypes;
|
|
||||||
inner.hooks = interpreter->hooks;
|
inner.hooks = interpreter->hooks;
|
||||||
setInterpreterPrint(&inner, interpreter->printOutput);
|
setInterpreterPrint(&inner, interpreter->printOutput);
|
||||||
setInterpreterAssert(&inner, interpreter->assertOutput);
|
setInterpreterAssert(&inner, interpreter->assertOutput);
|
||||||
@@ -1473,96 +1471,34 @@ static bool execImport(Interpreter* interpreter) {
|
|||||||
Literal identifier = popLiteralArray(&interpreter->stack);
|
Literal identifier = popLiteralArray(&interpreter->stack);
|
||||||
|
|
||||||
//access the hooks
|
//access the hooks
|
||||||
if (existsLiteralDictionary(interpreter->hooks, identifier)) {
|
if (!existsLiteralDictionary(interpreter->hooks, identifier)) {
|
||||||
Literal func = getLiteralDictionary(interpreter->hooks, identifier);
|
interpreter->errorOutput("Unknown library name in import statement: ");
|
||||||
|
printLiteralCustom(identifier, interpreter->errorOutput);
|
||||||
|
interpreter->errorOutput("\"\n");
|
||||||
|
|
||||||
if (!IS_FUNCTION_NATIVE(func)) {
|
freeLiteral(alias);
|
||||||
interpreter->errorOutput("Expected native function for a hook: ");
|
freeLiteral(identifier);
|
||||||
printLiteralCustom(identifier, interpreter->errorOutput);
|
return false;
|
||||||
interpreter->errorOutput("\"\n");
|
}
|
||||||
|
|
||||||
freeLiteral(func);
|
Literal func = getLiteralDictionary(interpreter->hooks, identifier);
|
||||||
freeLiteral(alias);
|
|
||||||
freeLiteral(identifier);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
HookFn fn = (HookFn)AS_FUNCTION(func).bytecode;
|
if (!IS_FUNCTION_NATIVE(func)) {
|
||||||
|
interpreter->errorOutput("Expected native function for a hook: ");
|
||||||
fn(interpreter, identifier, alias);
|
printLiteralCustom(identifier, interpreter->errorOutput);
|
||||||
|
interpreter->errorOutput("\"\n");
|
||||||
|
|
||||||
freeLiteral(func);
|
freeLiteral(func);
|
||||||
freeLiteral(alias);
|
freeLiteral(alias);
|
||||||
freeLiteral(identifier);
|
freeLiteral(identifier);
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Literal lit = getLiteralDictionary(interpreter->exports, identifier);
|
HookFn fn = (HookFn)AS_FUNCTION(func).bytecode;
|
||||||
Literal type = getLiteralDictionary(interpreter->exportTypes, identifier);
|
|
||||||
|
|
||||||
//use the alias
|
fn(interpreter, identifier, alias);
|
||||||
if (!IS_NULL(alias)) {
|
|
||||||
if (!declareScopeVariable(interpreter->scope, alias, type)) {
|
|
||||||
interpreter->errorOutput("Can't redefine the variable \"");
|
|
||||||
printLiteralCustom(alias, interpreter->errorOutput);
|
|
||||||
interpreter->errorOutput("\"\n");
|
|
||||||
|
|
||||||
freeLiteral(lit);
|
freeLiteral(func);
|
||||||
freeLiteral(type);
|
|
||||||
freeLiteral(alias);
|
|
||||||
freeLiteral(identifier);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
setScopeVariable(interpreter->scope, alias, lit, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
//use the original identifier
|
|
||||||
else {
|
|
||||||
if (!declareScopeVariable(interpreter->scope, identifier, type)) {
|
|
||||||
interpreter->errorOutput("Can't redefine the variable \"");
|
|
||||||
printLiteralCustom(identifier, interpreter->errorOutput);
|
|
||||||
interpreter->errorOutput("\"\n");
|
|
||||||
|
|
||||||
freeLiteral(lit);
|
|
||||||
freeLiteral(type);
|
|
||||||
freeLiteral(alias);
|
|
||||||
freeLiteral(identifier);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
setScopeVariable(interpreter->scope, identifier, lit, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
//cleanup
|
|
||||||
freeLiteral(lit);
|
|
||||||
freeLiteral(type);
|
|
||||||
freeLiteral(alias);
|
|
||||||
freeLiteral(identifier);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool execExport(Interpreter* interpreter) {
|
|
||||||
Literal alias = popLiteralArray(&interpreter->stack);
|
|
||||||
Literal identifier = popLiteralArray(&interpreter->stack);
|
|
||||||
|
|
||||||
Literal lit = TO_NULL_LITERAL;
|
|
||||||
|
|
||||||
getScopeVariable(interpreter->scope, identifier, &lit);
|
|
||||||
Literal type = getScopeType(interpreter->scope, identifier);
|
|
||||||
|
|
||||||
if (!IS_NULL(alias)) {
|
|
||||||
setLiteralDictionary(interpreter->exports, alias, lit);
|
|
||||||
setLiteralDictionary(interpreter->exportTypes, alias, type);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
setLiteralDictionary(interpreter->exports, identifier, lit);
|
|
||||||
setLiteralDictionary(interpreter->exportTypes, identifier, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
//cleanup
|
|
||||||
freeLiteral(lit);
|
|
||||||
freeLiteral(type);
|
|
||||||
freeLiteral(alias);
|
freeLiteral(alias);
|
||||||
freeLiteral(identifier);
|
freeLiteral(identifier);
|
||||||
return true;
|
return true;
|
||||||
@@ -2087,12 +2023,6 @@ static void execInterpreter(Interpreter* interpreter) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OP_EXPORT:
|
|
||||||
if (!execExport(interpreter)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case OP_INDEX:
|
case OP_INDEX:
|
||||||
if (!execIndex(interpreter, false)) {
|
if (!execIndex(interpreter, false)) {
|
||||||
return;
|
return;
|
||||||
@@ -2401,11 +2331,6 @@ static void readInterpreterSections(Interpreter* interpreter) {
|
|||||||
|
|
||||||
//exposed functions
|
//exposed functions
|
||||||
void initInterpreter(Interpreter* interpreter) {
|
void initInterpreter(Interpreter* interpreter) {
|
||||||
//NOTE: separate initialization for exports
|
|
||||||
interpreter->exports = ALLOCATE(LiteralDictionary, 1);
|
|
||||||
initLiteralDictionary(interpreter->exports);
|
|
||||||
interpreter->exportTypes = ALLOCATE(LiteralDictionary, 1);
|
|
||||||
initLiteralDictionary(interpreter->exportTypes);
|
|
||||||
interpreter->hooks = ALLOCATE(LiteralDictionary, 1);
|
interpreter->hooks = ALLOCATE(LiteralDictionary, 1);
|
||||||
initLiteralDictionary(interpreter->hooks);
|
initLiteralDictionary(interpreter->hooks);
|
||||||
|
|
||||||
@@ -2520,26 +2445,6 @@ void freeInterpreter(Interpreter* interpreter) {
|
|||||||
interpreter->scope = popScope(interpreter->scope);
|
interpreter->scope = popScope(interpreter->scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
//BUGFIX: handle scopes/types in the exports
|
|
||||||
for (int i = 0; i < interpreter->exports->capacity; i++) {
|
|
||||||
if (IS_FUNCTION(interpreter->exports->entries[i].key)) {
|
|
||||||
popScope(AS_FUNCTION(interpreter->exports->entries[i].key).scope);
|
|
||||||
AS_FUNCTION(interpreter->exports->entries[i].key).scope = NULL;
|
|
||||||
}
|
|
||||||
if (IS_FUNCTION(interpreter->exports->entries[i].value)) {
|
|
||||||
popScope(AS_FUNCTION(interpreter->exports->entries[i].value).scope);
|
|
||||||
AS_FUNCTION(interpreter->exports->entries[i].value).scope = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
freeLiteralDictionary(interpreter->exports);
|
|
||||||
FREE(LiteralDictionary, interpreter->exports);
|
|
||||||
interpreter->exports = NULL;
|
|
||||||
|
|
||||||
freeLiteralDictionary(interpreter->exportTypes);
|
|
||||||
FREE(LiteralDictionary, interpreter->exportTypes);
|
|
||||||
interpreter->exportTypes = NULL;
|
|
||||||
|
|
||||||
freeLiteralDictionary(interpreter->hooks);
|
freeLiteralDictionary(interpreter->hooks);
|
||||||
FREE(LiteralDictionary, interpreter->hooks);
|
FREE(LiteralDictionary, interpreter->hooks);
|
||||||
interpreter->hooks = NULL;
|
interpreter->hooks = NULL;
|
||||||
|
|||||||
@@ -21,8 +21,7 @@ typedef struct Interpreter {
|
|||||||
Scope* scope;
|
Scope* scope;
|
||||||
LiteralArray stack;
|
LiteralArray stack;
|
||||||
|
|
||||||
LiteralDictionary* exports; //read-write - interface with Toy from C - this is a pointer, since it works at a script-level
|
//Library APIs
|
||||||
LiteralDictionary* exportTypes;
|
|
||||||
LiteralDictionary* hooks;
|
LiteralDictionary* hooks;
|
||||||
|
|
||||||
//debug outputs
|
//debug outputs
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ typedef enum Opcode {
|
|||||||
OP_TYPE_OF, //get the type of a variable
|
OP_TYPE_OF, //get the type of a variable
|
||||||
|
|
||||||
OP_IMPORT,
|
OP_IMPORT,
|
||||||
OP_EXPORT,
|
OP_EXPORT_removed,
|
||||||
|
|
||||||
//for indexing
|
//for indexing
|
||||||
OP_INDEX,
|
OP_INDEX,
|
||||||
|
|||||||
@@ -1321,37 +1321,6 @@ static void importStmt(Parser* parser, ASTNode** nodeHandle) {
|
|||||||
freeLiteral(alias);
|
freeLiteral(alias);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void exportStmt(Parser* parser, ASTNode** nodeHandle) {
|
|
||||||
//read the identifier
|
|
||||||
ASTNode* node = NULL;
|
|
||||||
advance(parser);
|
|
||||||
identifier(parser, &node);
|
|
||||||
|
|
||||||
if (node == NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Literal idn = copyLiteral(node->atomic.literal);
|
|
||||||
freeASTNode(node);
|
|
||||||
|
|
||||||
Literal alias = TO_NULL_LITERAL;
|
|
||||||
|
|
||||||
if (match(parser, TOKEN_AS)) {
|
|
||||||
ASTNode* node;
|
|
||||||
advance(parser);
|
|
||||||
identifier(parser, &node);
|
|
||||||
alias = copyLiteral(node->atomic.literal);
|
|
||||||
freeASTNode(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
emitASTNodeExport(nodeHandle, idn, alias);
|
|
||||||
|
|
||||||
consume(parser, TOKEN_SEMICOLON, "Expected ';' at end of export statement");
|
|
||||||
|
|
||||||
freeLiteral(idn);
|
|
||||||
freeLiteral(alias);
|
|
||||||
}
|
|
||||||
|
|
||||||
//precedence functions
|
//precedence functions
|
||||||
static void expressionStmt(Parser* parser, ASTNode** nodeHandle) {
|
static void expressionStmt(Parser* parser, ASTNode** nodeHandle) {
|
||||||
//BUGFIX: check for empty statements
|
//BUGFIX: check for empty statements
|
||||||
@@ -1431,12 +1400,6 @@ static void statement(Parser* parser, ASTNode** nodeHandle) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//export
|
|
||||||
if (match(parser, TOKEN_EXPORT)) {
|
|
||||||
exportStmt(parser, nodeHandle);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//default
|
//default
|
||||||
expressionStmt(parser, nodeHandle);
|
expressionStmt(parser, nodeHandle);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,8 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#define TOY_VERSION_MAJOR 0
|
#define TOY_VERSION_MAJOR 0
|
||||||
#define TOY_VERSION_MINOR 6
|
#define TOY_VERSION_MINOR 7
|
||||||
#define TOY_VERSION_PATCH 5
|
#define TOY_VERSION_PATCH 0
|
||||||
#define TOY_VERSION_BUILD __DATE__ " " __TIME__
|
#define TOY_VERSION_BUILD __DATE__ " " __TIME__
|
||||||
|
|
||||||
//platform-specific specifications
|
//platform-specific specifications
|
||||||
|
|||||||
@@ -1,52 +0,0 @@
|
|||||||
//test basic import/export
|
|
||||||
{
|
|
||||||
var variable: int = 42;
|
|
||||||
export variable as field;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
import field as value;
|
|
||||||
assert value == 42, "import/export failed";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//test functions using import/export
|
|
||||||
{
|
|
||||||
fn f() {
|
|
||||||
import field;
|
|
||||||
|
|
||||||
assert field == 42, "import in function failed";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//test importing/exporting of functions
|
|
||||||
{
|
|
||||||
fn func() {
|
|
||||||
return 69;
|
|
||||||
}
|
|
||||||
|
|
||||||
export func;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
import func;
|
|
||||||
assert func() == 69, "import/export of functions failed";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//test that variables retain their types with the typeof keyword
|
|
||||||
{
|
|
||||||
var t: type = int;
|
|
||||||
|
|
||||||
export t;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
import t;
|
|
||||||
|
|
||||||
assert typeof t == type, "type retention failed";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
print "All good";
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
//test exports
|
|
||||||
var field: int = 42;
|
|
||||||
|
|
||||||
fn function() {
|
|
||||||
return 69;
|
|
||||||
}
|
|
||||||
|
|
||||||
export field;
|
|
||||||
export function;
|
|
||||||
|
|
||||||
print "All good";
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
//test imports
|
|
||||||
import field;
|
|
||||||
//import function;
|
|
||||||
|
|
||||||
//assert field == 42, "import field failed";
|
|
||||||
|
|
||||||
//assert function() == 69, "import function failed";
|
|
||||||
|
|
||||||
print "All good";
|
|
||||||
|
|
||||||
@@ -186,7 +186,6 @@ int main() {
|
|||||||
"dot-chaining.toy",
|
"dot-chaining.toy",
|
||||||
"dottify-bugfix.toy",
|
"dottify-bugfix.toy",
|
||||||
"functions.toy",
|
"functions.toy",
|
||||||
"imports-and-exports.toy",
|
|
||||||
"index-arrays.toy",
|
"index-arrays.toy",
|
||||||
"index-dictionaries.toy",
|
"index-dictionaries.toy",
|
||||||
"index-strings.toy",
|
"index-strings.toy",
|
||||||
@@ -212,38 +211,6 @@ int main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
|
||||||
//read source
|
|
||||||
size_t dummy;
|
|
||||||
size_t exportSize, importSize;
|
|
||||||
char* exportSource = readFile("scripts/separate-exports.toy", &dummy);
|
|
||||||
char* importSource = readFile("scripts/separate-imports.toy", &dummy);
|
|
||||||
|
|
||||||
//compile
|
|
||||||
unsigned char* exportBinary = compileString(exportSource, &exportSize);
|
|
||||||
unsigned char* importBinary = compileString(importSource, &importSize);
|
|
||||||
|
|
||||||
//run the interpreter over both binaries
|
|
||||||
Interpreter interpreter;
|
|
||||||
initInterpreter(&interpreter);
|
|
||||||
|
|
||||||
//NOTE: supress print output for testing
|
|
||||||
setInterpreterPrint(&interpreter, noPrintFn);
|
|
||||||
setInterpreterAssert(&interpreter, noAssertFn);
|
|
||||||
|
|
||||||
runInterpreter(&interpreter, exportBinary, exportSize); //automatically frees the binary data
|
|
||||||
|
|
||||||
resetInterpreter(&interpreter);
|
|
||||||
|
|
||||||
runInterpreter(&interpreter, importBinary, importSize); //automatically frees the binary data
|
|
||||||
|
|
||||||
freeInterpreter(&interpreter);
|
|
||||||
|
|
||||||
//cleanup
|
|
||||||
free((void*)exportSource);
|
|
||||||
free((void*)importSource);
|
|
||||||
}
|
|
||||||
|
|
||||||
//1, to allow for the assertion test
|
//1, to allow for the assertion test
|
||||||
if (ignoredAssertions > 1) {
|
if (ignoredAssertions > 1) {
|
||||||
fprintf(stderr, ERROR "Assertions hidden: %d\n", ignoredAssertions);
|
fprintf(stderr, ERROR "Assertions hidden: %d\n", ignoredAssertions);
|
||||||
|
|||||||
Reference in New Issue
Block a user