Example #1
0
int
CFCType_equals(CFCType *self, CFCType *other) {
    if ((CFCType_const(self)           ^ CFCType_const(other))
        || (CFCType_nullable(self)     ^ CFCType_nullable(other))
        || (CFCType_is_void(self)      ^ CFCType_is_void(other))
        || (CFCType_is_object(self)    ^ CFCType_is_object(other))
        || (CFCType_is_primitive(self) ^ CFCType_is_primitive(other))
        || (CFCType_is_integer(self)   ^ CFCType_is_integer(other))
        || (CFCType_is_floating(self)  ^ CFCType_is_floating(other))
        || (CFCType_is_va_list(self)   ^ CFCType_is_va_list(other))
        || (CFCType_is_arbitrary(self) ^ CFCType_is_arbitrary(other))
        || (CFCType_is_composite(self) ^ CFCType_is_composite(other))
        || (CFCType_incremented(self)  ^ CFCType_incremented(other))
        || (CFCType_decremented(self)  ^ CFCType_decremented(other))
        || !!self->child ^ !!other->child
        || !!self->array ^ !!other->array
       ) {
        return false;
    }
    if (self->indirection != other->indirection) { return false; }
    if (strcmp(self->specifier, other->specifier) != 0) { return false; }
    if (self->child) {
        if (!CFCType_equals(self->child, other->child)) { return false; }
    }
    if (self->array) {
        if (strcmp(self->array, other->array) != 0) { return false; }
    }
    return true;
}
Example #2
0
int
CFCType_similar(CFCType *self, CFCType *other) {
    if (!CFCType_is_object(self)) {
        CFCUtil_die("Attempt to call 'similar' on a non-object type");
    }
    if ((CFCType_const(self)           ^ CFCType_const(other))
        || (CFCType_nullable(self)     ^ CFCType_nullable(other))
        || (CFCType_incremented(self)  ^ CFCType_incremented(other))
        || (CFCType_decremented(self)  ^ CFCType_decremented(other))
        || (CFCType_is_object(self)    ^ CFCType_is_object(other))
       ) {
        return false;
    }
    return true;
}
Example #3
0
static void
S_run_integer_tests(CFCTest *test) {
    {
        CFCType *type = CFCType_new_integer(CFCTYPE_CONST, "int32_t");
        OK(test, CFCType_const(type), "const");
        STR_EQ(test, CFCType_get_specifier(type), "int32_t", "get_specifier");
        STR_EQ(test, CFCType_to_c(type), "const int32_t",
               "'const' in C representation");
        CFCBase_decref((CFCBase*)type);
    }

    {
        CFCParser *parser = CFCParser_new();
        static const char *specifiers[14] = {
            "bool",
            "char",
            "short",
            "int",
            "long",
            "size_t",
            "int8_t",
            "int16_t",
            "int32_t",
            "int64_t",
            "uint8_t",
            "uint16_t",
            "uint32_t",
            "uint64_t"
        };
        for (int i = 0; i < 14; ++i) {
            const char *specifier = specifiers[i];
            CFCType *type;

            type = CFCTest_parse_type(test, parser, specifier);
            OK(test, CFCType_is_integer(type), "%s is_integer", specifier);
            CFCBase_decref((CFCBase*)type);

            char *const_specifier = CFCUtil_sprintf("const %s", specifier);
            type = CFCTest_parse_type(test, parser, const_specifier);
            OK(test, CFCType_is_integer(type), "%s is_integer",
               const_specifier);
            OK(test, CFCType_const(type), "%s is const", const_specifier);
            FREEMEM(const_specifier);
            CFCBase_decref((CFCBase*)type);
        }
        CFCBase_decref((CFCBase*)parser);
    }
}
Example #4
0
static void
S_run_void_tests(CFCTest *test) {
    CFCParser *parser = CFCParser_new();

    {
        CFCType *type = CFCType_new_void(false);
        STR_EQ(test, CFCType_get_specifier(type), "void", "get_specifier");
        STR_EQ(test, CFCType_to_c(type), "void", "to_c");
        OK(test, CFCType_is_void(type), "is_void");
        CFCBase_decref((CFCBase*)type);
    }

    {
        CFCType *type = CFCType_new_void(true);
        STR_EQ(test, CFCType_to_c(type), "const void",
               "'const' in C representation");
        CFCBase_decref((CFCBase*)type);
    }

    {
        CFCType *type = CFCTest_parse_type(test, parser, "void");
        OK(test, CFCType_is_void(type), "void is_void");
        CFCBase_decref((CFCBase*)type);
    }

    {
        CFCType *type = CFCTest_parse_type(test, parser, "const void");
        OK(test, CFCType_is_void(type), "const void is_void");
        OK(test, CFCType_const(type), "const void is const");
        CFCBase_decref((CFCBase*)type);
    }

    CFCBase_decref((CFCBase*)parser);
}
Example #5
0
const char*
CFCType_to_c(CFCType *self) {
    char *c_string = self->c_string;

    if (c_string) { return c_string; }

    if (CFCType_is_composite(self)) {
        // NOTE: Array postfixes are NOT included.
        const char *child_c_string = CFCType_to_c(self->child);
        size_t      child_c_len    = strlen(child_c_string);
        size_t      amount         = child_c_len + self->indirection;
        c_string = (char*)MALLOCATE(amount + 1);
        strcpy(c_string, child_c_string);
        for (int i = 0; i < self->indirection; i++) {
            strncat(c_string, "*", 1);
        }
    }
    else if (CFCType_is_object(self)) {
        if (CFCType_const(self)) {
            c_string = CFCUtil_sprintf("const %s*", self->specifier);
        }
        else {
            c_string = CFCUtil_sprintf("%s*", self->specifier);
        }
    }
    else {
        if (CFCType_const(self)) {
            c_string = CFCUtil_sprintf("const %s", self->specifier);
        }
        else {
            c_string = CFCUtil_strdup(self->specifier);
        }
    }

    self->c_string = c_string;

    return c_string;
}
Example #6
0
static void
S_run_float_tests(CFCTest *test) {
    {
        CFCType *type = CFCType_new_float(CFCTYPE_CONST, "float");
        OK(test, CFCType_const(type), "const");
        STR_EQ(test, CFCType_get_specifier(type), "float", "get_specifier");
        STR_EQ(test, CFCType_to_c(type), "const float",
               "'const' in C representation");
        CFCBase_decref((CFCBase*)type);
    }

    {
        CFCParser *parser = CFCParser_new();
        static const char *specifiers[2] = {
            "float",
            "double"
        };
        for (int i = 0; i < 2; ++i) {
            const char *specifier = specifiers[i];
            CFCType *type;

            type = CFCTest_parse_type(test, parser, specifier);
            OK(test, CFCType_is_floating(type), "%s is_floating", specifier);
            CFCBase_decref((CFCBase*)type);

            char *const_specifier = CFCUtil_sprintf("const %s", specifier);
            type = CFCTest_parse_type(test, parser, const_specifier);
            OK(test, CFCType_is_floating(type), "%s is_floating",
               const_specifier);
            OK(test, CFCType_const(type), "%s is const", const_specifier);
            FREEMEM(const_specifier);
            CFCBase_decref((CFCBase*)type);
        }
        CFCBase_decref((CFCBase*)parser);
    }
}
Example #7
0
static void
S_run_tests(CFCTest *test) {
    CFCParser *parser = CFCParser_new();
    OK(test, parser != NULL, "new");

    {
        CFCParcel *fish = CFCTest_parse_parcel(test, parser, "parcel Fish;");

        CFCParcel *registered
            = CFCParcel_new("Crustacean", "Crust", NULL, false);
        CFCParcel_register(registered);
        CFCParcel *parcel
            = CFCTest_parse_parcel(test, parser, "parcel Crustacean;");
        OK(test, parcel == registered, "Fetch registered parcel");
        OK(test, CFCParser_get_parcel(parser) == parcel,
           "parcel_definition sets internal var");

        CFCBase_decref((CFCBase*)fish);
        CFCBase_decref((CFCBase*)registered);
        CFCBase_decref((CFCBase*)parcel);
    }

    {
        static const char *const specifiers[8] = {
            "foo", "_foo", "foo_yoo", "FOO", "Foo", "fOO", "f00", "foo_foo_foo"
        };
        for (int i = 0; i < 8; ++i) {
            const char *specifier = specifiers[i];
            char *src = CFCUtil_sprintf("int32_t %s;", specifier);
            CFCVariable *var = CFCTest_parse_variable(test, parser, src);
            STR_EQ(test, CFCVariable_micro_sym(var), specifier,
                   "identifier/declarator: %s", specifier);
            FREEMEM(src);
            CFCBase_decref((CFCBase*)var);
        }
    }

    {
        static const char *const specifiers[6] = {
            "void", "float", "uint32_t", "int64_t", "uint8_t", "bool"
        };
        for (int i = 0; i < 6; ++i) {
            const char *specifier = specifiers[i];
            char *src = CFCUtil_sprintf("int32_t %s;", specifier);
            CFCBase *result = CFCParser_parse(parser, src);
            OK(test, result == NULL,
               "reserved word not parsed as identifier: %s", specifier);
            FREEMEM(src);
            CFCBase_decref(result);
        }
    }

    {
        static const char *const type_strings[7] = {
            "bool", "const char *", "Obj*", "i32_t", "char[]", "long[1]",
            "i64_t[30]"
        };
        for (int i = 0; i < 7; ++i) {
            const char *type_string = type_strings[i];
            CFCType *type = CFCTest_parse_type(test, parser, type_string);
            CFCBase_decref((CFCBase*)type);
        }
    }

    {
        static const char *const class_names[7] = {
            "ByteBuf", "Obj", "ANDMatcher", "Foo", "FooJr", "FooIII", "Foo4th"
        };
        CFCClass *class_list[8];
        for (int i = 0; i < 7; ++i) {
            char *class_code = CFCUtil_sprintf("class %s {}", class_names[i]);
            CFCClass *klass = CFCTest_parse_class(test, parser, class_code);
            class_list[i] = klass;
            FREEMEM(class_code);
        }
        class_list[7] = NULL;
        for (int i = 0; i < 7; ++i) {
            const char *class_name = class_names[i];
            char *src      = CFCUtil_sprintf("%s*", class_name);
            char *expected = CFCUtil_sprintf("crust_%s", class_name);
            CFCType *type = CFCTest_parse_type(test, parser, src);
            CFCType_resolve(type, class_list);
            STR_EQ(test, CFCType_get_specifier(type), expected,
                   "object_type_specifier: %s", class_name);
            FREEMEM(src);
            FREEMEM(expected);
            CFCBase_decref((CFCBase*)type);
        }
        for (int i = 0; i < 7; ++i) {
            CFCBase_decref((CFCBase*)class_list[i]);
        }
        CFCClass_clear_registry();
    }

    {
        CFCType *type = CFCTest_parse_type(test, parser, "const char");
        OK(test, CFCType_const(type), "type_qualifier const");
        CFCBase_decref((CFCBase*)type);
    }

    {
        static const char *const exposures[2] = {
            "public", ""
        };
        static int (*const accessors[2])(CFCSymbol *sym) = {
            CFCSymbol_public, CFCSymbol_parcel
        };
        for (int i = 0; i < 2; ++i) {
            const char *exposure = exposures[i];
            char *src = CFCUtil_sprintf("%s inert int32_t foo;", exposure);
            CFCVariable *var = CFCTest_parse_variable(test, parser, src);
            OK(test, accessors[i]((CFCSymbol*)var), "exposure_specifier %s",
               exposure);
            FREEMEM(src);
            CFCBase_decref((CFCBase*)var);
        }
    }

    {
        static const char *const hex_constants[] = {
            "0x1", "0x0a", "0xFFFFFFFF", "-0xFC", NULL
        };
        S_test_initial_value(test, parser, hex_constants, "int32_t",
                             "hex_constant:");
    }

    {
        static const char *const integer_constants[] = {
            "1", "-9999", "0", "10000", NULL
        };
        S_test_initial_value(test, parser, integer_constants, "int32_t",
                             "integer_constant:");
    }

    {
        static const char *const float_constants[] = {
            "1.0", "-9999.999", "0.1", "0.0", NULL
        };
        S_test_initial_value(test, parser, float_constants, "double",
                             "float_constant:");
    }

    {
        static const char *const string_literals[] = {
            "\"blah\"", "\"blah blah\"", "\"\\\"blah\\\" \\\"blah\\\"\"", NULL
        };
        S_test_initial_value(test, parser, string_literals, "String*",
                             "string_literal:");
    }

    {
        static const char *const composites[5] = {
            "int[]", "i32_t **", "Foo **", "Foo ***", "const void *"
        };
        for (int i = 0; i < 5; ++i) {
            const char *composite = composites[i];
            CFCType *type = CFCTest_parse_type(test, parser, composite);
            OK(test, CFCType_is_composite(type), "composite_type: %s",
               composite);
            CFCBase_decref((CFCBase*)type);
        }
    }

    {
        static const char *const object_types[5] = {
            "Obj *", "incremented Foo*", "decremented String *"
        };
        for (int i = 0; i < 3; ++i) {
            const char *object_type = object_types[i];
            CFCType *type = CFCTest_parse_type(test, parser, object_type);
            OK(test, CFCType_is_object(type), "object_type: %s",
               object_type);
            CFCBase_decref((CFCBase*)type);
        }
    }

    {
        static const char *const param_list_strings[3] = {
            "()",
            "(int foo)",
            "(Obj *foo, Foo **foo_ptr)"
        };
        for (int i = 0; i < 3; ++i) {
            const char *param_list_string = param_list_strings[i];
            CFCParamList *param_list
                = CFCTest_parse_param_list(test, parser, param_list_string);
            INT_EQ(test, CFCParamList_num_vars(param_list), i,
                   "param list num_vars: %d", i);
            CFCBase_decref((CFCBase*)param_list);
        }
    }

    {
        CFCParamList *param_list
            = CFCTest_parse_param_list(test, parser, "(int foo, ...)");
        OK(test, CFCParamList_variadic(param_list), "variadic param list");
        CFCBase_decref((CFCBase*)param_list);
    }

    {
        const char *param_list_string =
            "(int foo = 0xFF, char *bar =\"blah\")";
        CFCParamList *param_list
            = CFCTest_parse_param_list(test, parser, param_list_string);
        const char **initial_values
            = CFCParamList_get_initial_values(param_list);
        STR_EQ(test, initial_values[0], "0xFF",
               "param list initial_values[0]");
        STR_EQ(test, initial_values[1], "\"blah\"",
               "param list initial_values[1]");
        OK(test, initial_values[2] == NULL, "param list initial_values[2]");
        CFCBase_decref((CFCBase*)param_list);
    }

    {
        CFCParser_set_class_name(parser, "Stuff::Obj");
        CFCParser_set_class_cnick(parser, "Obj");

        const char *method_string =
            "public Foo* Spew_Foo(Obj *self, uint32_t *how_many);";
        CFCMethod *method = CFCTest_parse_method(test, parser, method_string);
        CFCBase_decref((CFCBase*)method);

        const char *var_string =
            "public inert Hash *hash;";
        CFCVariable *var = CFCTest_parse_variable(test, parser, var_string);
        CFCBase_decref((CFCBase*)var);
    }

    {
        static const char *const class_names[4] = {
            "Foo", "Foo::FooJr", "Foo::FooJr::FooIII",
            "Foo::FooJr::FooIII::Foo4th"
        };
        for (int i = 0; i < 4; ++i) {
            const char *class_name = class_names[i];
            char *class_string = CFCUtil_sprintf("class %s { }", class_name);
            CFCClass *klass
                = CFCTest_parse_class(test, parser, class_string);
            STR_EQ(test, CFCClass_get_class_name(klass), class_name,
                   "class_name: %s", class_name);
            FREEMEM(class_string);
            CFCBase_decref((CFCBase*)klass);
        }
    }

    {
        static const char *const cnicks[2] =  { "Food", "FF" };
        for (int i = 0; i < 2; ++i) {
            const char *cnick = cnicks[i];
            char *class_string
                = CFCUtil_sprintf("class Foodie%s cnick %s { }", cnick, cnick);
            CFCClass *klass
                = CFCTest_parse_class(test, parser, class_string);
            STR_EQ(test, CFCClass_get_cnick(klass), cnick, "cnick: %s", cnick);
            FREEMEM(class_string);
            CFCBase_decref((CFCBase*)klass);
        }
    }

    CFCBase_decref((CFCBase*)parser);

    CFCClass_clear_registry();
    CFCParcel_reap_singletons();
}