You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucy.apache.org by nw...@apache.org on 2013/01/29 02:27:29 UTC
[lucy-commits] git commit: refs/heads/cfc-tests - Port more CFC tests to C
Updated Branches:
refs/heads/cfc-tests 3a9cef14e -> 64602a2a9
Port more CFC tests to C
Project: http://git-wip-us.apache.org/repos/asf/lucy/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy/commit/64602a2a
Tree: http://git-wip-us.apache.org/repos/asf/lucy/tree/64602a2a
Diff: http://git-wip-us.apache.org/repos/asf/lucy/diff/64602a2a
Branch: refs/heads/cfc-tests
Commit: 64602a2a992b205600ec40d6ea39822635cee52e
Parents: 3a9cef1
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Mon Jan 28 23:02:59 2013 +0100
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Tue Jan 29 02:21:31 2013 +0100
----------------------------------------------------------------------
clownfish/compiler/perl/lib/Clownfish/CFC.xs | 14 +-
clownfish/compiler/perl/t/core/300-variable.t | 23 ++
clownfish/compiler/perl/t/core/301-param_list.t | 23 ++
clownfish/compiler/perl/t/core/400-file_spec.t | 23 ++
clownfish/compiler/perl/t/core/401-class.t | 23 ++
clownfish/compiler/src/CFCTest.c | 43 ++-
clownfish/compiler/src/CFCTest.h | 22 ++
clownfish/compiler/src/CFCTestClass.c | 352 ++++++++++++++++++
clownfish/compiler/src/CFCTestFileSpec.c | 54 +++
clownfish/compiler/src/CFCTestParamList.c | 78 ++++
clownfish/compiler/src/CFCTestVariable.c | 101 +++++
11 files changed, 740 insertions(+), 16 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucy/blob/64602a2a/clownfish/compiler/perl/lib/Clownfish/CFC.xs
----------------------------------------------------------------------
diff --git a/clownfish/compiler/perl/lib/Clownfish/CFC.xs b/clownfish/compiler/perl/lib/Clownfish/CFC.xs
index c461922..fc306f2 100644
--- a/clownfish/compiler/perl/lib/Clownfish/CFC.xs
+++ b/clownfish/compiler/perl/lib/Clownfish/CFC.xs
@@ -2406,21 +2406,33 @@ run_batch(self, klass)
CFCTest *self;
const char *klass;
PPCODE:
- if (strcmp(klass, "Clownfish::CFC::Model::DocuComment") == 0) {
+ if (strcmp(klass, "Clownfish::CFC::Model::Class") == 0) {
+ CFCTestClass_run(self);
+ }
+ else if (strcmp(klass, "Clownfish::CFC::Model::DocuComment") == 0) {
CFCTestDocuComment_run(self);
}
+ else if (strcmp(klass, "Clownfish::CFC::Model::FileSpec") == 0) {
+ CFCTestFileSpec_run(self);
+ }
else if (strcmp(klass, "Clownfish::CFC::Model::Function") == 0) {
CFCTestFunction_run(self);
}
else if (strcmp(klass, "Clownfish::CFC::Model::Method") == 0) {
CFCTestMethod_run(self);
}
+ else if (strcmp(klass, "Clownfish::CFC::Model::ParamList") == 0) {
+ CFCTestParamList_run(self);
+ }
else if (strcmp(klass, "Clownfish::CFC::Model::Symbol") == 0) {
CFCTestSymbol_run(self);
}
else if (strcmp(klass, "Clownfish::CFC::Model::Type") == 0) {
CFCTestType_run(self);
}
+ else if (strcmp(klass, "Clownfish::CFC::Model::Variable") == 0) {
+ CFCTestVariable_run(self);
+ }
else if (strcmp(klass, "Clownfish::CFC::Model::Version") == 0) {
CFCTestVersion_run(self);
}
http://git-wip-us.apache.org/repos/asf/lucy/blob/64602a2a/clownfish/compiler/perl/t/core/300-variable.t
----------------------------------------------------------------------
diff --git a/clownfish/compiler/perl/t/core/300-variable.t b/clownfish/compiler/perl/t/core/300-variable.t
new file mode 100644
index 0000000..9e0e1ed
--- /dev/null
+++ b/clownfish/compiler/perl/t/core/300-variable.t
@@ -0,0 +1,23 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+use strict;
+use warnings;
+
+use Clownfish::CFC::Test;
+
+my $test = Clownfish::CFC::Test->new;
+$test->run_batch('Clownfish::CFC::Model::Variable');
+
http://git-wip-us.apache.org/repos/asf/lucy/blob/64602a2a/clownfish/compiler/perl/t/core/301-param_list.t
----------------------------------------------------------------------
diff --git a/clownfish/compiler/perl/t/core/301-param_list.t b/clownfish/compiler/perl/t/core/301-param_list.t
new file mode 100644
index 0000000..66abb5e
--- /dev/null
+++ b/clownfish/compiler/perl/t/core/301-param_list.t
@@ -0,0 +1,23 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+use strict;
+use warnings;
+
+use Clownfish::CFC::Test;
+
+my $test = Clownfish::CFC::Test->new;
+$test->run_batch('Clownfish::CFC::Model::ParamList');
+
http://git-wip-us.apache.org/repos/asf/lucy/blob/64602a2a/clownfish/compiler/perl/t/core/400-file_spec.t
----------------------------------------------------------------------
diff --git a/clownfish/compiler/perl/t/core/400-file_spec.t b/clownfish/compiler/perl/t/core/400-file_spec.t
new file mode 100644
index 0000000..46e34c4
--- /dev/null
+++ b/clownfish/compiler/perl/t/core/400-file_spec.t
@@ -0,0 +1,23 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+use strict;
+use warnings;
+
+use Clownfish::CFC::Test;
+
+my $test = Clownfish::CFC::Test->new;
+$test->run_batch('Clownfish::CFC::Model::FileSpec');
+
http://git-wip-us.apache.org/repos/asf/lucy/blob/64602a2a/clownfish/compiler/perl/t/core/401-class.t
----------------------------------------------------------------------
diff --git a/clownfish/compiler/perl/t/core/401-class.t b/clownfish/compiler/perl/t/core/401-class.t
new file mode 100644
index 0000000..f78e107
--- /dev/null
+++ b/clownfish/compiler/perl/t/core/401-class.t
@@ -0,0 +1,23 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+use strict;
+use warnings;
+
+use Clownfish::CFC::Test;
+
+my $test = Clownfish::CFC::Test->new;
+$test->run_batch('Clownfish::CFC::Model::Class');
+
http://git-wip-us.apache.org/repos/asf/lucy/blob/64602a2a/clownfish/compiler/src/CFCTest.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCTest.c b/clownfish/compiler/src/CFCTest.c
index 0085aa9..352cdd1 100644
--- a/clownfish/compiler/src/CFCTest.c
+++ b/clownfish/compiler/src/CFCTest.c
@@ -22,12 +22,7 @@
#define CFC_USE_TEST_MACROS
#include "CFCTest.h"
#include "CFCBase.h"
-#include "CFCFunction.h"
-#include "CFCMethod.h"
-#include "CFCParamList.h"
-#include "CFCParcel.h"
#include "CFCParser.h"
-#include "CFCType.h"
#include "CFCUtil.h"
struct CFCTestFormatter {
@@ -352,48 +347,66 @@ static void
S_format_tap_summary(CFCTest *test) {
}
-CFCParcel*
+struct CFCParcel*
CFCTest_parse_parcel(CFCTest *test, CFCParser *parser, const char *src) {
CFCBase *result = CFCParser_parse(parser, src);
OK(test, result != NULL, "parse '%s'", src);
STR_EQ(test, CFCBase_get_cfc_class(result),
"Clownfish::CFC::Model::Parcel", "result class of '%s'", src);
- return (CFCParcel*)result;
+ return (struct CFCParcel*)result;
}
-CFCType*
+struct CFCType*
CFCTest_parse_type(CFCTest *test, CFCParser *parser, const char *src) {
CFCBase *result = CFCParser_parse(parser, src);
OK(test, result != NULL, "parse '%s'", src);
STR_EQ(test, CFCBase_get_cfc_class(result),
"Clownfish::CFC::Model::Type", "result class of '%s'", src);
- return (CFCType*)result;
+ return (struct CFCType*)result;
}
-CFCParamList*
+struct CFCVariable*
+CFCTest_parse_variable(CFCTest *test, CFCParser *parser, const char *src) {
+ CFCBase *result = CFCParser_parse(parser, src);
+ OK(test, result != NULL, "parse '%s'", src);
+ STR_EQ(test, CFCBase_get_cfc_class(result),
+ "Clownfish::CFC::Model::Variable", "result class of '%s'", src);
+ return (struct CFCVariable*)result;
+}
+
+struct CFCParamList*
CFCTest_parse_param_list(CFCTest *test, CFCParser *parser, const char *src) {
CFCBase *result = CFCParser_parse(parser, src);
OK(test, result != NULL, "parse '%s'", src);
STR_EQ(test, CFCBase_get_cfc_class(result),
"Clownfish::CFC::Model::ParamList", "result class of '%s'", src);
- return (CFCParamList*)result;
+ return (struct CFCParamList*)result;
}
-CFCFunction*
+struct CFCFunction*
CFCTest_parse_function(CFCTest *test, CFCParser *parser, const char *src) {
CFCBase *result = CFCParser_parse(parser, src);
OK(test, result != NULL, "parse '%s'", src);
STR_EQ(test, CFCBase_get_cfc_class(result),
"Clownfish::CFC::Model::Function", "result class of '%s'", src);
- return (CFCFunction*)result;
+ return (struct CFCFunction*)result;
}
-CFCMethod*
+struct CFCMethod*
CFCTest_parse_method(CFCTest *test, CFCParser *parser, const char *src) {
CFCBase *result = CFCParser_parse(parser, src);
OK(test, result != NULL, "parse '%s'", src);
STR_EQ(test, CFCBase_get_cfc_class(result),
"Clownfish::CFC::Model::Method", "result class of '%s'", src);
- return (CFCMethod*)result;
+ return (struct CFCMethod*)result;
+}
+
+struct CFCClass*
+CFCTest_parse_class(CFCTest *test, CFCParser *parser, const char *src) {
+ CFCBase *result = CFCParser_parse(parser, src);
+ OK(test, result != NULL, "parse class");
+ STR_EQ(test, CFCBase_get_cfc_class(result),
+ "Clownfish::CFC::Model::Class", "result class");
+ return (struct CFCClass*)result;
}
http://git-wip-us.apache.org/repos/asf/lucy/blob/64602a2a/clownfish/compiler/src/CFCTest.h
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCTest.h b/clownfish/compiler/src/CFCTest.h
index cf8f3ac..ecada06 100644
--- a/clownfish/compiler/src/CFCTest.h
+++ b/clownfish/compiler/src/CFCTest.h
@@ -24,11 +24,14 @@
#endif
typedef struct CFCTest CFCTest;
+struct CFCClass;
struct CFCFunction;
+struct CFCMethod;
struct CFCParamList;
struct CFCParcel;
struct CFCParser;
struct CFCType;
+struct CFCVariable;
CFCTest*
CFCTest_new(const char *formatter_name);
@@ -65,6 +68,10 @@ CFCTest_parse_parcel(CFCTest *test, struct CFCParser *parser, const char *src);
struct CFCType*
CFCTest_parse_type(CFCTest *test, struct CFCParser *parser, const char *src);
+struct CFCVariable*
+CFCTest_parse_variable(CFCTest *test, struct CFCParser *parser,
+ const char *src);
+
struct CFCParamList*
CFCTest_parse_param_list(CFCTest *test, struct CFCParser *parser,
const char *src);
@@ -76,16 +83,28 @@ CFCTest_parse_function(CFCTest *test, struct CFCParser *parser,
struct CFCMethod*
CFCTest_parse_method(CFCTest *test, struct CFCParser *parser, const char *src);
+struct CFCClass*
+CFCTest_parse_class(CFCTest *test, struct CFCParser *parser, const char *src);
+
+void
+CFCTestClass_run(CFCTest *test);
+
void
CFCTestDocuComment_run(CFCTest *test);
void
+CFCTestFileSpec_run(CFCTest *test);
+
+void
CFCTestFunction_run(CFCTest *test);
void
CFCTestMethod_run(CFCTest *test);
void
+CFCTestParamList_run(CFCTest *test);
+
+void
CFCTestSymbol_run(CFCTest *test);
void
@@ -95,6 +114,9 @@ void
CFCTestUtil_run(CFCTest *test);
void
+CFCTestVariable_run(CFCTest *test);
+
+void
CFCTestVersion_run(CFCTest *test);
#endif /* H_TEST_CFC */
http://git-wip-us.apache.org/repos/asf/lucy/blob/64602a2a/clownfish/compiler/src/CFCTestClass.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCTestClass.c b/clownfish/compiler/src/CFCTestClass.c
new file mode 100644
index 0000000..50b4024
--- /dev/null
+++ b/clownfish/compiler/src/CFCTestClass.c
@@ -0,0 +1,352 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <string.h>
+
+#define CFC_USE_TEST_MACROS
+#include "CFCBase.h"
+#include "CFCClass.h"
+#include "CFCFileSpec.h"
+#include "CFCFunction.h"
+#include "CFCMethod.h"
+#include "CFCParamList.h"
+#include "CFCParcel.h"
+#include "CFCParser.h"
+#include "CFCSymbol.h"
+#include "CFCTest.h"
+#include "CFCType.h"
+#include "CFCUtil.h"
+#include "CFCVariable.h"
+
+static void
+S_run_basic_tests(CFCTest *test);
+
+static int
+S_has_symbol(CFCSymbol **symbols, const char *micro_sym);
+
+void
+CFCTestClass_run(CFCTest *test) {
+ CFCTest_start_batch(test, "class", 83);
+
+ S_run_basic_tests(test);
+}
+
+static void
+S_run_basic_tests(CFCTest *test) {
+ CFCParser *parser = CFCParser_new();
+
+ CFCParcel *neato = CFCParcel_new("Neato", NULL, NULL);
+ CFCFileSpec *file_spec = CFCFileSpec_new(".", "Foo/FooJr", 0);
+
+ CFCVariable *thing;
+ CFCVariable *widget;
+ CFCFunction *tread_water;
+
+ {
+ CFCType *thing_type = CFCTest_parse_type(test, parser, "Thing*");
+ thing = CFCVariable_new(neato, NULL, "Foo", NULL, "thing",
+ thing_type, 0);
+
+ CFCType *widget_type = CFCTest_parse_type(test, parser, "Widget*");
+ widget = CFCVariable_new(NULL, NULL, "Widget", NULL, "widget",
+ widget_type, 0);
+
+ CFCType *return_type = CFCTest_parse_type(test, parser, "void");
+ CFCParamList *param_list
+ = CFCTest_parse_param_list(test, parser, "()");
+ tread_water
+ = CFCFunction_new(neato, NULL, "Foo", NULL, "tread_water",
+ return_type, param_list, NULL, 0);
+
+ CFCBase_decref((CFCBase*)thing_type);
+ CFCBase_decref((CFCBase*)widget_type);
+ CFCBase_decref((CFCBase*)return_type);
+ CFCBase_decref((CFCBase*)param_list);
+ }
+
+ CFCClass *foo
+ = CFCClass_create(neato, NULL, "Foo", NULL, NULL, NULL, NULL, NULL,
+ 0, 0);
+ CFCClass_add_function(foo, tread_water);
+ CFCClass_add_member_var(foo, thing);
+ CFCClass_add_inert_var(foo, widget);
+
+ {
+ CFCClass *should_be_foo = CFCClass_fetch_singleton(neato, "Foo");
+ OK(test, should_be_foo == foo, "fetch_singleton");
+ CFCBase_decref((CFCBase*)should_be_foo);
+ }
+
+ CFCClass *foo_jr
+ = CFCClass_create(neato, NULL, "Foo::FooJr", NULL, NULL, NULL, NULL,
+ "Foo", 0, 0);
+ CFCClass_add_attribute(foo_jr, "dumpable", "1");
+ OK(test, CFCClass_has_attribute(foo_jr, "dumpable"), "has_attribute");
+ STR_EQ(test, CFCClass_get_struct_sym(foo_jr), "FooJr",
+ "get_struct_sym");
+ STR_EQ(test, CFCClass_full_struct_sym(foo_jr), "neato_FooJr",
+ "full_struct_sym");
+
+ CFCClass *final_foo
+ = CFCClass_create(neato, NULL, "Foo::FooJr::FinalFoo", NULL, NULL, NULL,
+ file_spec, "Foo::FooJr", 1, 0);
+ CFCClass_add_attribute(final_foo, "dumpable", "1");
+ OK(test, CFCClass_final(final_foo), "final");
+ STR_EQ(test, CFCClass_include_h(final_foo), "Foo/FooJr.h",
+ "include_h uses path_part");
+ STR_EQ(test, CFCClass_get_parent_class_name(final_foo), "Foo::FooJr",
+ "get_parent_class_name");
+
+ {
+ CFCParcel *parsed_neato
+ = CFCTest_parse_parcel(test, parser, "parcel Neato;");
+ CFCBase_decref((CFCBase*)parsed_neato);
+ }
+
+ CFCParser_set_class_name(parser, "Foo");
+ CFCMethod *do_stuff
+ = CFCTest_parse_method(test, parser, "void Do_Stuff(Foo *self);");
+ CFCClass_add_method(foo, do_stuff);
+
+ CFCClass_add_child(foo, foo_jr);
+ CFCClass_add_child(foo_jr, final_foo);
+ CFCClass_grow_tree(foo);
+
+ OK(test, CFCClass_get_parent(foo_jr) == foo, "grow_tree, one level" );
+ OK(test, CFCClass_get_parent(final_foo) == foo_jr,
+ "grow_tree, two levels");
+ OK(test, CFCClass_fresh_method(foo, "Do_Stuff") == do_stuff,
+ "fresh_method");
+ OK(test, CFCClass_method(foo_jr, "Do_Stuff") == do_stuff,
+ "inherited method");
+ OK(test, CFCClass_fresh_method(foo_jr, "Do_Stuff") == NULL,
+ "inherited method not 'fresh'");
+ OK(test, CFCMethod_final(CFCClass_method(final_foo, "Do_Stuff")),
+ "Finalize inherited method");
+ OK(test, !CFCMethod_final(CFCClass_method(foo_jr, "Do_Stuff")),
+ "Don't finalize method in parent");
+
+ {
+ CFCVariable **inert_vars = CFCClass_inert_vars(foo);
+ OK(test, inert_vars[0] == widget, "inert_vars[0]");
+ OK(test, inert_vars[1] == NULL, "inert_vars[1]");
+
+ CFCFunction **functions = CFCClass_functions(foo);
+ OK(test, functions[0] == tread_water, "functions[0]");
+ OK(test, functions[1] == NULL, "functions[1]");
+
+ CFCMethod **methods = CFCClass_methods(foo);
+ OK(test, methods[0] == do_stuff, "methods[0]");
+ OK(test, methods[1] == NULL, "methods[1]");
+
+ CFCMethod **fresh_methods = CFCClass_fresh_methods(foo);
+ OK(test, fresh_methods[0] == do_stuff, "fresh_methods[0]");
+ OK(test, fresh_methods[1] == NULL, "fresh_methods[1]");
+
+ CFCVariable **fresh_member_vars = CFCClass_fresh_member_vars(foo);
+ OK(test, fresh_member_vars[0] == thing, "fresh_member_vars[0]");
+ OK(test, fresh_member_vars[1] == NULL, "fresh_member_vars[1]");
+ }
+
+ {
+ CFCVariable **member_vars = CFCClass_member_vars(foo_jr);
+ OK(test, member_vars[0] == thing, "member_vars[0]");
+ OK(test, member_vars[1] == NULL, "member_vars[1]");
+
+ CFCFunction **functions = CFCClass_functions(foo_jr);
+ OK(test, functions[0] == NULL, "functions[0]");
+
+ CFCVariable **fresh_member_vars = CFCClass_fresh_member_vars(foo_jr);
+ OK(test, fresh_member_vars[0] == NULL, "fresh_member_vars[0]");
+
+ CFCVariable **inert_vars = CFCClass_inert_vars(foo_jr);
+ OK(test, inert_vars[0] == NULL, "inert_vars[0]");
+ }
+
+ {
+ CFCMethod **fresh_methods = CFCClass_fresh_methods(final_foo);
+ OK(test, fresh_methods[0] == NULL, "fresh_methods[0]");
+ }
+
+ {
+ const char *autocode = CFCClass_get_autocode(foo_jr);
+ OK(test, strstr(autocode, "load") != NULL, "autogenerate Dump/Load");
+ }
+
+ {
+ CFCClass **ladder = CFCClass_tree_to_ladder(foo);
+ OK(test, ladder[0] == foo, "ladder[0]");
+ OK(test, ladder[1] == foo_jr, "ladder[1]");
+ OK(test, ladder[2] == final_foo, "ladder[2]");
+ OK(test, ladder[3] == NULL, "ladder[3]");
+ }
+
+ {
+ CFCClass *final_class
+ = CFCTest_parse_class(test, parser, "final class Iamfinal { }");
+ OK(test, CFCClass_final(final_class), "class modifer: final");
+ CFCClass *inert_class
+ = CFCTest_parse_class(test, parser, "inert class Iaminert { }");
+ OK(test, CFCClass_inert(inert_class), "class modifer: inert");
+
+ CFCBase_decref((CFCBase*)final_class);
+ CFCBase_decref((CFCBase*)inert_class);
+ }
+
+ {
+ static const char *names[2] = { "Fooble", "Foo::FooJr::FooIII" };
+ for (int i = 0; i < 2; ++i) {
+ const char *name = names[i];
+ char *class_src
+ = CFCUtil_sprintf("class Fu::%s inherits %s { }", name, name);
+ CFCClass *klass = CFCTest_parse_class(test, parser, class_src);
+ STR_EQ(test, CFCClass_get_parent_class_name(klass), name,
+ "class_inheritance: %s", name);
+ FREEMEM(class_src);
+ CFCBase_decref((CFCBase*)klass);
+ }
+ }
+
+ {
+ const char *class_src =
+ "public class Foo::Foodie cnick Foodie inherits Foo {\n"
+ " private int num;\n"
+ "}\n";
+ CFCClass *klass = CFCTest_parse_class(test, parser, class_src);
+ CFCSymbol **member_vars = (CFCSymbol**)CFCClass_member_vars(klass);
+ OK(test, S_has_symbol(member_vars, "num"),
+ "parsed private member var");
+
+ CFCBase_decref((CFCBase*)klass);
+ }
+
+ {
+ const char *class_src =
+ "/**\n"
+ " * Bow wow.\n"
+ " *\n"
+ " * Wow wow wow.\n"
+ " */\n"
+ "public class Animal::Dog inherits Animal : lovable : drooly {\n"
+ " public inert Dog* init(Dog *self, CharBuf *name,\n"
+ " CharBuf *fave_food);\n"
+ " inert uint32_t count();\n"
+ " inert uint64_t num_dogs;\n"
+ "\n"
+ " private CharBuf *name;\n"
+ " private bool likes_to_go_fetch;\n"
+ " private void Chase_Tail(Dog *self);\n"
+ "\n"
+ " ChewToy *squishy;\n"
+ "\n"
+ " void Destroy(Dog *self);\n"
+ " public CharBuf* Bark(Dog *self);\n"
+ " public void Eat(Dog *self);\n"
+ " public void Bite(Dog *self, Enemy *enemy);\n"
+ " public Thing *Fetch(Dog *self, Thing *thing);\n"
+ " public final void Bury(Dog *self, Bone *bone);\n"
+ " public Owner *mom;\n"
+ " public abstract incremented nullable Thing*\n"
+ " Scratch(Dog *self);\n"
+ "\n"
+ " int32_t[1] flexible_array_at_end_of_struct;\n"
+ "}\n";
+ CFCClass *klass = CFCTest_parse_class(test, parser, class_src);
+
+ CFCSymbol **inert_vars = (CFCSymbol**)CFCClass_inert_vars(klass);
+ CFCSymbol **member_vars = (CFCSymbol**)CFCClass_member_vars(klass);
+ CFCSymbol **functions = (CFCSymbol**)CFCClass_functions(klass);
+ CFCSymbol **methods = (CFCSymbol**)CFCClass_methods(klass);
+ OK(test, S_has_symbol(inert_vars, "num_dogs"), "parsed inert var");
+ OK(test, S_has_symbol(member_vars, "mom"), "parsed public member var");
+ OK(test, S_has_symbol(member_vars, "squishy"),
+ "parsed parcel member var");
+ OK(test, S_has_symbol(functions, "init"), "parsed function");
+ OK(test, S_has_symbol(methods, "chase_tail"), "parsed private method");
+ OK(test, S_has_symbol(methods, "destroy"), "parsed parcel method");
+ OK(test, S_has_symbol(methods, "bury"), "parsed public method");
+ OK(test, S_has_symbol(methods, "scratch"),
+ "parsed public abstract nullable method");
+
+ CFCMethod *scratch = CFCClass_method(klass, "scratch");
+ OK(test, scratch != NULL, "find method 'scratch'");
+ OK(test, CFCType_nullable(CFCMethod_get_return_type(scratch)),
+ "public abstract incremented nullable flagged as nullable");
+
+ int num_public_methods = 0;
+ for (int i = 0; methods[i]; ++i) {
+ if (CFCSymbol_public(methods[i])) { ++num_public_methods; }
+ }
+ INT_EQ(test, num_public_methods, 6, "pass acl to Method constructor");
+
+ OK(test, CFCClass_has_attribute(klass, "lovable"),
+ "parsed class attribute");
+ OK(test, CFCClass_has_attribute(klass, "drooly"),
+ "parsed second class attribute");
+
+ CFCBase_decref((CFCBase*)klass);
+ }
+
+ {
+ const char *class_src =
+ "parcel inert class Rigor::Mortis cnick Mort {\n"
+ " parcel inert void lie_still();\n"
+ "}\n";
+ CFCClass *klass = CFCTest_parse_class(test, parser, class_src);
+ OK(test, CFCClass_inert(klass),
+ "inert modifier parsed and passed to constructor");
+
+ CFCBase_decref((CFCBase*)klass);
+ }
+
+ {
+ const char *class_src =
+ "final class Ultimo {\n"
+ " /** Throws an error.\n"
+ " */\n"
+ " void Say_Never(Ultimo *self);\n"
+ "}\n";
+ CFCClass *klass = CFCTest_parse_class(test, parser, class_src);
+ OK(test, CFCClass_final(klass), "final class_declaration");
+ CFCBase_decref((CFCBase*)klass);
+ }
+
+ CFCBase_decref((CFCBase*)parser);
+ CFCBase_decref((CFCBase*)neato);
+ CFCBase_decref((CFCBase*)file_spec);
+ CFCBase_decref((CFCBase*)thing);
+ CFCBase_decref((CFCBase*)widget);
+ CFCBase_decref((CFCBase*)tread_water);
+ CFCBase_decref((CFCBase*)foo);
+ CFCBase_decref((CFCBase*)foo_jr);
+ CFCBase_decref((CFCBase*)final_foo);
+ CFCBase_decref((CFCBase*)do_stuff);
+
+ CFCClass_clear_registry();
+ CFCParcel_reap_singletons();
+}
+
+static int
+S_has_symbol(CFCSymbol **symbols, const char *micro_sym) {
+ for (int i = 0; symbols[i]; ++i) {
+ if (strcmp(CFCSymbol_micro_sym(symbols[i]), micro_sym) == 0) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
http://git-wip-us.apache.org/repos/asf/lucy/blob/64602a2a/clownfish/compiler/src/CFCTestFileSpec.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCTestFileSpec.c b/clownfish/compiler/src/CFCTestFileSpec.c
new file mode 100644
index 0000000..2cddfa8
--- /dev/null
+++ b/clownfish/compiler/src/CFCTestFileSpec.c
@@ -0,0 +1,54 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define CFC_USE_TEST_MACROS
+#include "CFCBase.h"
+#include "CFCFileSpec.h"
+#include "CFCTest.h"
+
+static void
+S_run_basic_tests(CFCTest *test);
+
+void
+CFCTestFileSpec_run(CFCTest *test) {
+ CFCTest_start_batch(test, "file_spec", 4);
+
+ S_run_basic_tests(test);
+}
+
+static void
+S_run_basic_tests(CFCTest *test) {
+ {
+ CFCFileSpec *file_spec
+ = CFCFileSpec_new("Clownfish/_include", "Stuff/Thing", 0);
+ STR_EQ(test, CFCFileSpec_get_source_dir(file_spec),
+ "Clownfish/_include", "get_source_dir");
+ STR_EQ(test, CFCFileSpec_get_path_part(file_spec),
+ "Stuff/Thing", "get_path_part");
+ OK(test, !CFCFileSpec_included(file_spec), "not included");
+
+ CFCBase_decref((CFCBase*)file_spec);
+ }
+
+ {
+ CFCFileSpec *file_spec
+ = CFCFileSpec_new("Clownfish/_include", "Stuff/Thing", 1);
+ OK(test, CFCFileSpec_included(file_spec), "included");
+
+ CFCBase_decref((CFCBase*)file_spec);
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/lucy/blob/64602a2a/clownfish/compiler/src/CFCTestParamList.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCTestParamList.c b/clownfish/compiler/src/CFCTestParamList.c
new file mode 100644
index 0000000..16f0a1e
--- /dev/null
+++ b/clownfish/compiler/src/CFCTestParamList.c
@@ -0,0 +1,78 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define CFC_USE_TEST_MACROS
+#include "CFCBase.h"
+#include "CFCParamList.h"
+#include "CFCParcel.h"
+#include "CFCParser.h"
+#include "CFCTest.h"
+#include "CFCVariable.h"
+
+static void
+S_run_basic_tests(CFCTest *test);
+
+void
+CFCTestParamList_run(CFCTest *test) {
+ CFCTest_start_batch(test, "param_list", 16);
+
+ S_run_basic_tests(test);
+}
+
+static void
+S_run_basic_tests(CFCTest *test) {
+ CFCParser *parser = CFCParser_new();
+ CFCParcel *neato_parcel
+ = CFCTest_parse_parcel(test, parser, "parcel Neato;");
+
+ {
+ CFCParamList *param_list
+ = CFCTest_parse_param_list(test, parser, "(Obj *self, int num)");
+ OK(test, !CFCParamList_variadic(param_list), "not variadic");
+ STR_EQ(test, CFCParamList_to_c(param_list), "neato_Obj* self, int num",
+ "to_c");
+ STR_EQ(test, CFCParamList_name_list(param_list), "self, num",
+ "name_list");
+
+ CFCBase_decref((CFCBase*)param_list);
+ }
+
+ {
+ CFCParamList *param_list
+ = CFCTest_parse_param_list(test, parser,
+ "(Obj *self=NULL, int num, ...)");
+ OK(test, CFCParamList_variadic(param_list), "variadic");
+ STR_EQ(test, CFCParamList_to_c(param_list),
+ "neato_Obj* self, int num, ...", "to_c");
+ INT_EQ(test, CFCParamList_num_vars(param_list), 2, "num_vars");
+ const char **initial_values
+ = CFCParamList_get_initial_values(param_list);
+ STR_EQ(test, initial_values[0], "NULL", "initial_values[0]");
+ OK(test, initial_values[1] == NULL, "initial_values[1]");
+ CFCVariable **variables = CFCParamList_get_variables(param_list);
+ OK(test, variables[0] != NULL, "get_variables");
+ STR_EQ(test, CFCBase_get_cfc_class((CFCBase*)variables[0]),
+ "Clownfish::CFC::Model::Variable", "get_variables return type");
+
+ CFCBase_decref((CFCBase*)param_list);
+ }
+
+ CFCBase_decref((CFCBase*)parser);
+ CFCBase_decref((CFCBase*)neato_parcel);
+
+ CFCParcel_reap_singletons();
+}
+
http://git-wip-us.apache.org/repos/asf/lucy/blob/64602a2a/clownfish/compiler/src/CFCTestVariable.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCTestVariable.c b/clownfish/compiler/src/CFCTestVariable.c
new file mode 100644
index 0000000..f6673e0
--- /dev/null
+++ b/clownfish/compiler/src/CFCTestVariable.c
@@ -0,0 +1,101 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define CFC_USE_TEST_MACROS
+#include "CFCBase.h"
+#include "CFCParcel.h"
+#include "CFCParser.h"
+#include "CFCSymbol.h"
+#include "CFCTest.h"
+#include "CFCType.h"
+#include "CFCVariable.h"
+
+static void
+S_run_basic_tests(CFCTest *test);
+
+void
+CFCTestVariable_run(CFCTest *test) {
+ CFCTest_start_batch(test, "variable", 27);
+
+ S_run_basic_tests(test);
+}
+
+static void
+S_run_basic_tests(CFCTest *test) {
+ CFCParser *parser = CFCParser_new();
+ CFCParcel *neato_parcel
+ = CFCTest_parse_parcel(test, parser, "parcel Neato;");
+
+ {
+ CFCType *type = CFCTest_parse_type(test, parser, "float*");
+ CFCVariable *var
+ = CFCVariable_new(NULL, NULL, NULL, NULL, "foo", type, 0);
+ STR_EQ(test, CFCVariable_local_c(var), "float* foo", "local_c");
+ STR_EQ(test, CFCVariable_local_declaration(var), "float* foo;",
+ "local_declaration");
+ OK(test, CFCSymbol_local((CFCSymbol*)var), "default to local access");
+
+ CFCBase_decref((CFCBase*)type);
+ CFCBase_decref((CFCBase*)var);
+ }
+
+ {
+ CFCType *type = CFCTest_parse_type(test, parser, "float[1]");
+ CFCVariable *var
+ = CFCVariable_new(NULL, NULL, NULL, NULL, "foo", type, 0);
+ STR_EQ(test, CFCVariable_local_c(var), "float foo[1]",
+ "to_c appends array to var name rather than type specifier");
+
+ CFCBase_decref((CFCBase*)type);
+ CFCBase_decref((CFCBase*)var);
+ }
+
+ {
+ CFCType *type = CFCTest_parse_type(test, parser, "Foo*");
+ CFCVariable *var
+ = CFCVariable_new(neato_parcel, NULL,
+ "Crustacean::Lobster::LobsterClaw", "LobClaw",
+ "foo", type, 0);
+ STR_EQ(test, CFCVariable_global_c(var), "neato_Foo* neato_LobClaw_foo",
+ "global_c");
+
+ CFCBase_decref((CFCBase*)type);
+ CFCBase_decref((CFCBase*)var);
+ }
+
+ {
+ static const char *variable_strings[7] = {
+ "parcel int foo;",
+ "private Obj *obj;",
+ "public inert int32_t **foo;",
+ "Dog *fido;",
+ "uint32_t baz",
+ "CharBuf *stuff",
+ "float **ptr"
+ };
+ for (int i = 0; i < 7; ++i) {
+ CFCVariable *var
+ = CFCTest_parse_variable(test, parser, variable_strings[i]);
+ CFCBase_decref((CFCBase*)var);
+ }
+ }
+
+ CFCBase_decref((CFCBase*)parser);
+ CFCBase_decref((CFCBase*)neato_parcel);
+
+ CFCParcel_reap_singletons();
+}
+