You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucy.apache.org by ma...@apache.org on 2014/11/17 18:33:33 UTC

[1/8] lucy git commit: Prep charmonizer for Go bindings.

Repository: lucy
Updated Branches:
  refs/heads/go_bindings_1 [created] b24c5c963


Prep charmonizer for Go bindings.

*   Add a `static` target.
*   Add `--enable-go` switch.
*   Use the C host src dir for now.


Project: http://git-wip-us.apache.org/repos/asf/lucy/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy/commit/1b065744
Tree: http://git-wip-us.apache.org/repos/asf/lucy/tree/1b065744
Diff: http://git-wip-us.apache.org/repos/asf/lucy/diff/1b065744

Branch: refs/heads/go_bindings_1
Commit: 1b065744eb50879bd18ee3cb6823767f5200d9b9
Parents: 2fdf429
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Sun Nov 16 16:36:14 2014 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Sun Nov 16 16:36:14 2014 -0800

----------------------------------------------------------------------
 common/charmonizer.main | 7 +++++++
 1 file changed, 7 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy/blob/1b065744/common/charmonizer.main
----------------------------------------------------------------------
diff --git a/common/charmonizer.main b/common/charmonizer.main
index 7a6e66a..1e4b434 100644
--- a/common/charmonizer.main
+++ b/common/charmonizer.main
@@ -112,6 +112,8 @@ int main(int argc, const char **argv) {
     chaz_CLI_register(cli, "clownfish-prefix",
                       "prefix of Clownfish installation",
                       CHAZ_CLI_ARG_OPTIONAL);
+    chaz_CLI_register(cli, "enable-go", "enable Go bindings",
+                      CHAZ_CLI_NO_ARG);
     chaz_CLI_set_usage(cli, "Usage: charmonizer [OPTIONS] [-- [CFLAGS]]");
     if (!chaz_Probe_parse_cli_args(argc, argv, cli)) {
         chaz_Probe_die_usage();
@@ -240,6 +242,9 @@ lucy_MakeFile_new(chaz_CLI *cli) {
     if (chaz_CLI_defined(cli, "enable-perl")) {
         self->host_src_dir = "xs";
     }
+	else if (chaz_CLI_defined(cli, "enable-go")) {
+        self->host_src_dir = "../c/src";
+	}
     else {
         self->host_src_dir = "src";
     }
@@ -424,6 +429,8 @@ lucy_MakeFile_write(lucy_MakeFile *self) {
     chaz_MakeFile_add_rule(self->makefile, "all", scratch);
     free(scratch);
 
+    chaz_MakeFile_add_rule(self->makefile, "static", self->static_lib_filename);
+
     chaz_MakeFile_add_lemon_exe(self->makefile, self->lemon_dir);
     chaz_MakeFile_add_lemon_grammar(self->makefile, self->json_parser);
 


[5/8] lucy git commit: Add basic Go Indexer bindings.

Posted by ma...@apache.org.
Add basic Go Indexer bindings.


Project: http://git-wip-us.apache.org/repos/asf/lucy/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy/commit/d36da9ef
Tree: http://git-wip-us.apache.org/repos/asf/lucy/tree/d36da9ef
Diff: http://git-wip-us.apache.org/repos/asf/lucy/diff/d36da9ef

Branch: refs/heads/go_bindings_1
Commit: d36da9ef385dc0b0f699aad44f27b31cf7a9e405
Parents: 308b879
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Sun Nov 16 22:06:58 2014 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Mon Nov 17 09:28:25 2014 -0800

----------------------------------------------------------------------
 go/lucy/index.go     | 166 ++++++++++++++++++++++++++++++++++++++++++++++
 go/lucy/lucy_test.go |  11 ++-
 2 files changed, 176 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy/blob/d36da9ef/go/lucy/index.go
----------------------------------------------------------------------
diff --git a/go/lucy/index.go b/go/lucy/index.go
new file mode 100644
index 0000000..fa91085
--- /dev/null
+++ b/go/lucy/index.go
@@ -0,0 +1,166 @@
+/* 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.
+ */
+
+package lucy
+
+/*
+#include "Lucy/Index/Indexer.h"
+#include "Lucy/Index/IndexManager.h"
+#include "Lucy/Document/Doc.h"
+#include "Lucy/Plan/Schema.h"
+#include "Clownfish/Hash.h"
+#include "Clownfish/String.h"
+#include "Clownfish/VArray.h"
+#include "Clownfish/Err.h"
+*/
+import "C"
+import "fmt"
+import "reflect"
+import "runtime"
+import "strings"
+import "unsafe"
+import "git-wip-us.apache.org/repos/asf/lucy-clownfish.git/runtime/go/clownfish"
+
+type Indexer struct {
+	ref        *C.lucy_Indexer
+	fieldNames map[string]*clownfish.String
+}
+
+type IndexManager struct {
+	ref *C.lucy_IndexManager
+}
+
+type OpenIndexerArgs struct {
+	Schema   *Schema
+	Index    interface{}
+	Manager  *IndexManager
+	Create   bool
+	Truncate bool
+}
+
+func OpenIndexer(args *OpenIndexerArgs) (obj *Indexer, err error) {
+	var schemaC *C.lucy_Schema = nil
+	if args.Schema != nil {
+		schemaC = args.Schema.ref
+	}
+	switch args.Index.(type) {
+	case string:
+	default:
+		panic("TODO: support Folder")
+	}
+	ixLoc := clownfish.NewString(args.Index.(string))
+	var managerC *C.lucy_IndexManager = nil
+	if args.Manager != nil {
+		managerC = args.Manager.ref
+	}
+	var flags int32
+	if args.Create {
+		flags = flags | int32(C.lucy_Indexer_CREATE)
+	}
+	if args.Truncate {
+		flags = flags | int32(C.lucy_Indexer_TRUNCATE)
+	}
+	err = clownfish.TrapErr(func() {
+		obj = &Indexer{
+			C.lucy_Indexer_new(schemaC, (*C.cfish_Obj)(ixLoc.ToPtr()),
+				managerC, C.int32_t(flags)),
+			nil,
+		}
+		runtime.SetFinalizer(obj, (*Indexer).finalize)
+	})
+	return obj, err
+}
+
+func (obj *Indexer) finalize() {
+	obj.Close()
+}
+
+func (obj *Indexer) Close() error {
+	// TODO: implement Close in core Lucy rather than bindings.
+	if obj.ref != nil {
+		C.LUCY_Indexer_Dec_RefCount(obj.ref)
+		obj.ref = nil
+	}
+	return nil // TODO catch errors
+}
+
+func (obj *Indexer) AddDoc(doc interface{}) error {
+	stockDoc := C.LUCY_Indexer_Get_Stock_Doc(obj.ref)
+	docFields := (*C.cfish_Hash)(C.LUCY_Doc_Get_Fields(stockDoc))
+	C.CFISH_Hash_Clear(docFields)
+
+	// TODO: Support map as doc in addition to struct as doc.
+
+	// Get reflection value and type for the supplied struct.
+	var docValue reflect.Value
+	if reflect.ValueOf(doc).Kind() == reflect.Ptr {
+		temp := reflect.ValueOf(doc).Elem()
+		if temp.Kind() == reflect.Struct {
+			docValue = temp
+		}
+	}
+	if docValue == (reflect.Value{}) {
+		mess := fmt.Sprintf("Doc not struct pointer: %v",
+			reflect.TypeOf(doc))
+		return clownfish.NewError(mess)
+	}
+	docType := docValue.Type()
+
+	for i := 0; i < docValue.NumField(); i++ {
+		field := docType.Field(i).Name
+		value := docValue.Field(i).String()
+		fieldC := obj.findFieldC(field)
+		valueC := clownfish.NewString(value)
+		C.CFISH_Hash_Store(docFields, (*C.cfish_Obj)(fieldC.ToPtr()),
+			C.CFISH_Str_Inc_RefCount((*C.cfish_String)(valueC.ToPtr())))
+	}
+
+	// TODO create an additional method AddDocWithBoost which allows the
+	// client to supply `boost`.
+	boost := 1.0
+	err := clownfish.TrapErr(func() {
+		C.LUCY_Indexer_Add_Doc(obj.ref, stockDoc, C.float(boost))
+	})
+
+	return err
+}
+
+func (obj *Indexer) findFieldC(name string) *clownfish.String {
+	if obj.fieldNames == nil {
+		obj.fieldNames = make(map[string]*clownfish.String)
+	}
+	fieldC, ok := obj.fieldNames[name]
+	if !ok {
+		schema := C.LUCY_Indexer_Get_Schema(obj.ref)
+		fieldList := C.LUCY_Schema_All_Fields(schema)
+		defer C.CFISH_VA_Dec_RefCount(fieldList)
+		for i := 0; i < int(C.CFISH_VA_Get_Size(fieldList)); i++ {
+			cfString := unsafe.Pointer(C.CFISH_VA_Fetch(fieldList, C.uint32_t(i)))
+			field := clownfish.CFStringToGo(cfString)
+			if strings.EqualFold(name, field) {
+				obj.fieldNames[name] = clownfish.NewString(field)
+				fieldC = obj.fieldNames[name]
+			}
+		}
+	}
+	return fieldC
+}
+
+func (obj *Indexer) Commit() error {
+	return clownfish.TrapErr(func() {
+		C.LUCY_Indexer_Commit(obj.ref)
+	})
+}

http://git-wip-us.apache.org/repos/asf/lucy/blob/d36da9ef/go/lucy/lucy_test.go
----------------------------------------------------------------------
diff --git a/go/lucy/lucy_test.go b/go/lucy/lucy_test.go
index 6a4c6d8..19b13bf 100644
--- a/go/lucy/lucy_test.go
+++ b/go/lucy/lucy_test.go
@@ -16,8 +16,17 @@
 
 package lucy_test
 
-import _ "git-wip-us.apache.org/repos/asf/lucy.git/go/lucy"
+import "git-wip-us.apache.org/repos/asf/lucy.git/go/lucy"
+import "git-wip-us.apache.org/repos/asf/lucy-clownfish.git/runtime/go/clownfish"
 import "testing"
 
 func TestStuff(t *testing.T) {
+	lucy.NewSchema()
+}
+
+func TestOpenIndexer(t *testing.T) {
+	_, err := lucy.OpenIndexer(&lucy.OpenIndexerArgs{Index: "notalucyindex"})
+	if _, ok := err.(*clownfish.Err); !ok {
+		t.Error("Didn't catch exception opening indexer")
+	}
 }


[8/8] lucy git commit: Add Go port of sample app.

Posted by ma...@apache.org.
Add Go port of sample app.


Project: http://git-wip-us.apache.org/repos/asf/lucy/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy/commit/b24c5c96
Tree: http://git-wip-us.apache.org/repos/asf/lucy/tree/b24c5c96
Diff: http://git-wip-us.apache.org/repos/asf/lucy/diff/b24c5c96

Branch: refs/heads/go_bindings_1
Commit: b24c5c963472b08ee2c448909657c5e1ac49c24f
Parents: e956964
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Mon Nov 17 09:30:49 2014 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Mon Nov 17 09:30:49 2014 -0800

----------------------------------------------------------------------
 go/sample/getting_started.go | 127 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 127 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy/blob/b24c5c96/go/sample/getting_started.go
----------------------------------------------------------------------
diff --git a/go/sample/getting_started.go b/go/sample/getting_started.go
new file mode 100644
index 0000000..fb69b74
--- /dev/null
+++ b/go/sample/getting_started.go
@@ -0,0 +1,127 @@
+/* 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.
+ */
+
+/*
+ * Sample program to get started with the Go bindings for the Apache Lucy C
+ * library.
+ *
+ * Creates an index with a few documents and conducts a few searches.
+ */
+
+package main
+
+import "git-wip-us.apache.org/repos/asf/lucy.git/go/lucy"
+import "fmt"
+import "log"
+
+func main() {
+	schema := createSchema()
+	index := "lucydemo"
+	indexDocuments(schema, index)
+	searcher, err := lucy.OpenIndexSearcher(index)
+	if err != nil {
+		log.Fatal(err)
+	}
+	defer searcher.Close()
+	performSearch(searcher, "ullamco")
+	performSearch(searcher, "ut OR laborum")
+	performSearch(searcher, `"fugiat nulla"`)
+}
+
+func createSchema() *lucy.Schema {
+	// Create a new schema.
+	schema := lucy.NewSchema()
+
+	// Create an analyzer.
+	analyzer := lucy.NewEasyAnalyzer("en")
+
+	// Specify fields.
+	fieldType := lucy.NewFullTextType(analyzer)
+	schema.SpecField("title", fieldType)
+	schema.SpecField("content", fieldType)
+
+	return schema
+}
+
+type MyDoc struct {
+	Title   string
+	Content string
+}
+
+var docs []MyDoc = []MyDoc{
+	MyDoc{
+		Title: `lorem ipsum`,
+		Content: `Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do
+                  eiusmod tempor incididunt ut labore et dolore magna aliqua.`,
+	},
+	MyDoc{
+		Title: `Ut enim`,
+		Content: `Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris
+                  nisi ut aliquip ex ea commodo consequat.`,
+	},
+	MyDoc{
+		Title: `Duis aute`,
+		Content: `Duis aute irure dolor in reprehenderit in voluptate velit essei
+                  cillum dolore eu fugiat nulla pariatur.`,
+	},
+	MyDoc{
+		Title: `Excepteur sint`,
+		Content: `Excepteur sint occaecat cupidatat non proident, sunt in culpa qui
+                  officia deserunt mollit anim id est laborum.`,
+	},
+}
+
+func indexDocuments(schema *lucy.Schema, index string) {
+	indexerArgs := &lucy.OpenIndexerArgs{
+		Schema:   schema,
+		Index:    index,
+		Create:   true,
+		Truncate: true,
+	}
+	indexer, err := lucy.OpenIndexer(indexerArgs)
+	if err != nil {
+		log.Fatal(err)
+	}
+	defer indexer.Close()
+
+	for _, doc := range docs {
+		err := indexer.AddDoc(&doc)
+		if err != nil {
+			log.Fatal(err)
+		}
+	}
+	err = indexer.Commit()
+	if err != nil {
+		log.Fatal(err)
+	}
+}
+
+func performSearch(searcher lucy.Searcher, query string) {
+	fmt.Println("Searching for:", query)
+
+	hits, err := searcher.Hits(query, 0, 10, nil)
+	if err != nil {
+		log.Fatal(err)
+	}
+	var hit MyDoc
+	for hits.Next(&hit) {
+		fmt.Printf("  Result: %s\n", hit.Title)
+	}
+	if err := hits.Error(); err != nil {
+		log.Fatal(err)
+	}
+	fmt.Println()
+}


[7/8] lucy git commit: Go stubs for Schema, FieldType, FullTextType.

Posted by ma...@apache.org.
Go stubs for Schema, FieldType, FullTextType.


Project: http://git-wip-us.apache.org/repos/asf/lucy/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy/commit/308b8791
Tree: http://git-wip-us.apache.org/repos/asf/lucy/tree/308b8791
Diff: http://git-wip-us.apache.org/repos/asf/lucy/diff/308b8791

Branch: refs/heads/go_bindings_1
Commit: 308b87913743b8cf3c2d8fe2805c138900291142
Parents: 3d2b0fd
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Sun Nov 16 21:40:34 2014 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Mon Nov 17 09:28:25 2014 -0800

----------------------------------------------------------------------
 go/lucy/plan.go | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 80 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy/blob/308b8791/go/lucy/plan.go
----------------------------------------------------------------------
diff --git a/go/lucy/plan.go b/go/lucy/plan.go
new file mode 100644
index 0000000..d7d10f2
--- /dev/null
+++ b/go/lucy/plan.go
@@ -0,0 +1,80 @@
+/* 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.
+ */
+
+package lucy
+
+/*
+#include "Lucy/Plan/Schema.h"
+#include "Lucy/Plan/FullTextType.h"
+*/
+import "C"
+import "runtime"
+import "unsafe"
+
+import "git-wip-us.apache.org/repos/asf/lucy-clownfish.git/runtime/go/clownfish"
+
+type Schema struct {
+	ref *C.lucy_Schema
+}
+
+type FieldType interface {
+	clownfish.Obj
+	ToFieldTypePtr() unsafe.Pointer
+}
+
+type FullTextType struct {
+	ref *C.lucy_FullTextType
+}
+
+func NewSchema() *Schema {
+	obj := &Schema{
+		C.lucy_Schema_new(),
+	}
+	runtime.SetFinalizer(obj, (*Schema).finalize)
+	return obj
+}
+
+func (obj *Schema) finalize() {
+	C.LUCY_Schema_Dec_RefCount(obj.ref)
+	obj.ref = nil
+}
+
+func (obj *Schema) SpecField(field string, fieldType FieldType) {
+	fieldCF := clownfish.NewString(field)
+	C.LUCY_Schema_Spec_Field(obj.ref, (*C.cfish_String)(fieldCF.ToPtr()),
+		(*C.lucy_FieldType)(fieldType.ToFieldTypePtr()))
+}
+
+func NewFullTextType(analyzer Analyzer) *FullTextType {
+	obj := &FullTextType{
+		C.lucy_FullTextType_new((*C.lucy_Analyzer)(analyzer.ToAnalyzerPtr())),
+	}
+	runtime.SetFinalizer(obj, (*FullTextType).finalize)
+	return obj
+}
+
+func (obj *FullTextType) finalize() {
+	C.LUCY_FullTextType_Dec_RefCount(obj.ref)
+	obj.ref = nil
+}
+
+func (obj *FullTextType) ToPtr() unsafe.Pointer {
+	return unsafe.Pointer(obj.ref)
+}
+
+func (obj *FullTextType) ToFieldTypePtr() unsafe.Pointer {
+	return obj.ToPtr()
+}


[3/8] lucy git commit: Add Go stubs for IndexSearcher, Hits.

Posted by ma...@apache.org.
Add Go stubs for IndexSearcher, Hits.


Project: http://git-wip-us.apache.org/repos/asf/lucy/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy/commit/e956964f
Tree: http://git-wip-us.apache.org/repos/asf/lucy/tree/e956964f
Diff: http://git-wip-us.apache.org/repos/asf/lucy/diff/e956964f

Branch: refs/heads/go_bindings_1
Commit: e956964f3768382361a9d4d41ea10ee7e163c805
Parents: d36da9e
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Mon Nov 17 09:23:09 2014 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Mon Nov 17 09:28:25 2014 -0800

----------------------------------------------------------------------
 go/lucy/search.go | 179 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 179 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy/blob/e956964f/go/lucy/search.go
----------------------------------------------------------------------
diff --git a/go/lucy/search.go b/go/lucy/search.go
new file mode 100644
index 0000000..63dc98e
--- /dev/null
+++ b/go/lucy/search.go
@@ -0,0 +1,179 @@
+/* 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.
+ */
+
+package lucy
+
+/*
+#include "Lucy/Search/Collector.h"
+#include "Lucy/Search/Hits.h"
+#include "Lucy/Search/IndexSearcher.h"
+#include "Lucy/Search/Query.h"
+#include "Lucy/Search/Searcher.h"
+#include "Lucy/Document/HitDoc.h"
+#include "Clownfish/Hash.h"
+#include "Clownfish/HashIterator.h"
+*/
+import "C"
+import "fmt"
+import "reflect"
+import "runtime"
+import "strings"
+import "unsafe"
+
+import "git-wip-us.apache.org/repos/asf/lucy-clownfish.git/runtime/go/clownfish"
+
+type Query interface {
+	clownfish.Obj
+	ToQueryPtr() unsafe.Pointer
+}
+
+type Searcher interface {
+	clownfish.Obj
+	ToSearcherPtr() unsafe.Pointer
+	Hits(query interface{}, offset uint32, numWanted uint32, sortSpec *SortSpec) (*Hits, error)
+}
+
+type Hits struct {
+	ref *C.lucy_Hits
+	err error
+}
+
+type SortSpec struct {
+	ref *C.lucy_SortSpec
+}
+
+type IndexSearcher struct {
+	ref *C.lucy_IndexSearcher
+}
+
+func OpenIndexSearcher(index interface{}) (obj *IndexSearcher, err error) {
+	var indexC *C.cfish_Obj
+	switch index.(type) {
+	case string:
+		ixLoc := clownfish.NewString(index.(string))
+		indexC = (*C.cfish_Obj)(ixLoc.ToPtr())
+	default:
+		panic("TODO: support Folder")
+	}
+	err = clownfish.TrapErr(func() {
+		obj = &IndexSearcher{C.lucy_IxSearcher_new(indexC)}
+	})
+	runtime.SetFinalizer(obj, (*IndexSearcher).finalize)
+	return obj, err
+}
+
+func (obj *IndexSearcher) finalize() {
+	C.LUCY_IxSearcher_Dec_RefCount(obj.ref)
+	obj.ref = nil
+}
+
+func (obj *IndexSearcher) Close() error {
+	return clownfish.TrapErr(func() {
+		C.LUCY_IxSearcher_Close(obj.ref)
+	})
+}
+
+func (obj *IndexSearcher) ToPtr() unsafe.Pointer {
+	return unsafe.Pointer(obj.ref)
+}
+
+func (obj *IndexSearcher) ToSearcherPtr() unsafe.Pointer {
+	return obj.ToPtr()
+}
+
+func (obj *IndexSearcher) Hits(query interface{}, offset uint32, numWanted uint32,
+	sortSpec *SortSpec) (hits *Hits, err error) {
+	var hitsC *C.lucy_Hits
+	var sortSpecC *C.lucy_SortSpec
+	if sortSpec != nil {
+		sortSpecC = sortSpec.ref
+	}
+	switch query.(type) {
+	case string:
+		queryStringC := clownfish.NewString(query.(string))
+		err = clownfish.TrapErr(func() {
+			hitsC = C.LUCY_IxSearcher_Hits(obj.ref,
+				(*C.cfish_Obj)(queryStringC.ToPtr()),
+				C.uint32_t(offset), C.uint32_t(numWanted), sortSpecC)
+		})
+	default:
+		panic("TODO: support Query objects")
+	}
+	hits = &Hits{hitsC, nil}
+	runtime.SetFinalizer(hits, (*Hits).finalize)
+	return hits, err
+}
+
+func (obj *Hits) Next(hit interface{}) bool {
+	// TODO: accept a HitDoc object and populate score.
+
+	// Get reflection value and type for the supplied struct.
+	var hitValue reflect.Value
+	if reflect.ValueOf(hit).Kind() == reflect.Ptr {
+		temp := reflect.ValueOf(hit).Elem()
+		if temp.Kind() == reflect.Struct {
+			if temp.CanSet() {
+				hitValue = temp
+			}
+		}
+	}
+	if hitValue == (reflect.Value{}) {
+		mess := fmt.Sprintf("Arg not writeable struct pointer: %v",
+			reflect.TypeOf(hit))
+		obj.err = clownfish.NewError(mess)
+		return false
+	}
+
+	var docC *C.lucy_HitDoc
+	errCallingNext := clownfish.TrapErr(func() {
+		docC = C.LUCY_Hits_Next(obj.ref)
+	})
+	if errCallingNext != nil {
+		obj.err = errCallingNext
+		return false
+	}
+	if docC == nil {
+		return false
+	}
+	defer C.LUCY_HitDoc_Dec_RefCount(docC)
+
+	fields := (*C.cfish_Hash)(unsafe.Pointer(C.LUCY_HitDoc_Get_Fields(docC)))
+	iterator := C.cfish_HashIter_new(fields)
+	defer C.CFISH_HashIter_Dec_RefCount(iterator)
+	for C.CFISH_HashIter_Next(iterator) {
+		keyC := C.CFISH_HashIter_Get_Key(iterator)
+		valC := C.CFISH_HashIter_Get_Value(iterator)
+		key := clownfish.CFStringToGo(unsafe.Pointer(keyC))
+		val := clownfish.CFStringToGo(unsafe.Pointer(valC))
+		match := func(name string) bool {
+			return strings.EqualFold(key, name)
+		}
+		structField := hitValue.FieldByNameFunc(match)
+		if structField != (reflect.Value{}) {
+			structField.SetString(val)
+		}
+	}
+	return true
+}
+
+func (obj *Hits) finalize() {
+	C.LUCY_Hits_Dec_RefCount(obj.ref)
+	obj.ref = nil
+}
+
+func (obj *Hits) Error() error {
+	return obj.err
+}


[4/8] lucy git commit: Add stub Go bindings and build.go "script".

Posted by ma...@apache.org.
Add stub Go bindings and build.go "script".


Project: http://git-wip-us.apache.org/repos/asf/lucy/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy/commit/3866bbb2
Tree: http://git-wip-us.apache.org/repos/asf/lucy/tree/3866bbb2
Diff: http://git-wip-us.apache.org/repos/asf/lucy/diff/3866bbb2

Branch: refs/heads/go_bindings_1
Commit: 3866bbb2a732921a09648f6d8e65e0bbdccfb000
Parents: b4ce496
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Sun Nov 16 20:39:07 2014 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Mon Nov 17 09:28:25 2014 -0800

----------------------------------------------------------------------
 go/build.go          | 220 ++++++++++++++++++++++++++++++++++++++++++++++
 go/lucy/lucy.go      |  27 ++++++
 go/lucy/lucy_test.go |  23 +++++
 3 files changed, 270 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy/blob/3866bbb2/go/build.go
----------------------------------------------------------------------
diff --git a/go/build.go b/go/build.go
new file mode 100644
index 0000000..5a09253
--- /dev/null
+++ b/go/build.go
@@ -0,0 +1,220 @@
+/* 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.
+ */
+
+package main
+
+import "flag"
+import "fmt"
+import "io"
+import "io/ioutil"
+import "log"
+import "os"
+import "os/exec"
+import "path"
+import "runtime"
+
+import "git-wip-us.apache.org/repos/asf/lucy-clownfish.git/compiler/go/cfc"
+
+var packageName string = "git-wip-us.apache.org/repos/asf/lucy.git/go/lucy"
+var cfPackageName string = "git-wip-us.apache.org/repos/asf/lucy-clownfish.git/runtime/go/clownfish"
+var charmonizerC string = "../common/charmonizer.c"
+var charmonizerEXE string = "charmonizer"
+var charmonyH string = "charmony.h"
+var buildDir string
+var hostSrcDir string
+var buildGO string
+var configGO string
+var installedLibPath string
+
+func init() {
+	_, buildGO, _, _ = runtime.Caller(1)
+	buildDir = path.Dir(buildGO)
+	hostSrcDir = path.Join(buildDir, "../c/src")
+	configGO = path.Join(buildDir, "lucy", "config.go")
+	var err error
+	installedLibPath, err = cfc.InstalledLibPath(packageName)
+	if err != nil {
+		log.Fatal(err)
+	}
+}
+
+func main() {
+	os.Chdir(buildDir)
+	flag.Parse()
+	action := "build"
+	args := flag.Args()
+	if len(args) > 0 {
+		action = args[0]
+	}
+	switch action {
+	case "build":
+		build()
+	case "clean":
+		clean()
+	case "test":
+		test()
+	case "install":
+		install()
+	default:
+		log.Fatalf("Unrecognized action specified: %s", action)
+	}
+}
+
+func current(orig, dest string) bool {
+
+	destInfo, err := os.Stat(dest)
+	if err != nil {
+		if os.IsNotExist(err) {
+			// If dest doesn't exist, we're not current.
+			return false
+		} else {
+			log.Fatalf("Unexpected stat err: %s", err)
+		}
+	}
+
+	// If source is newer than dest, we're not current.
+	origInfo, err := os.Stat(orig)
+	if err != nil {
+		log.Fatalf("Unexpected: %s", err)
+	}
+	return origInfo.ModTime().Before(destInfo.ModTime())
+}
+
+func runCommand(name string, args ...string) {
+	command := exec.Command(name, args...)
+	command.Stdout = os.Stdout
+	command.Stderr = os.Stderr
+	err := command.Run()
+	if err != nil {
+		log.Fatal(err)
+	}
+}
+
+func configure() {
+	if !current(charmonizerC, charmonizerEXE) {
+		runCommand("cc", "-o", charmonizerEXE, charmonizerC)
+	}
+	if !current(charmonizerEXE, charmonyH) {
+		runCommand("./charmonizer", "--cc=cc", "--enable-c", "--enable-go",
+			"--enable-makefile", "--", "-std=gnu99", "-O2")
+	}
+}
+
+func runCFC() {
+	hierarchy := cfc.NewHierarchy("autogen")
+	hierarchy.AddSourceDir("../core")
+	hierarchy.Build()
+	autogenHeader := "/* Auto-generated by build.go. */\n"
+	coreBinding := cfc.NewBindCore(hierarchy, autogenHeader, "")
+	modified := coreBinding.WriteAllModified(false)
+	if modified {
+		cBinding := cfc.NewBindC(hierarchy, autogenHeader, "")
+		cBinding.WriteCallbacks()
+		cBinding.WriteHostDefs()
+		hierarchy.WriteLog()
+	}
+}
+
+func build() {
+	configure()
+	runCFC()
+	runCommand("make", "-j", "static")
+	writeConfigGO()
+	runCommand("go", "build", packageName)
+}
+
+func test() {
+	build()
+	runCommand("go", "test", packageName)
+}
+
+func copyFile(source, dest string) {
+	sourceFH, err := os.Open(source)
+	if err != nil {
+		log.Fatal(err)
+	}
+	defer sourceFH.Close()
+	destFH, err := os.Create(dest)
+	if err != nil {
+		log.Fatal(err)
+	}
+	defer destFH.Close()
+	_, err = io.Copy(destFH, sourceFH)
+	if err != nil {
+		log.Fatalf("io.Copy from %s to %s failed: %s", source, dest, err)
+	}
+}
+
+func installStaticLib() {
+	tempLibPath := path.Join(buildDir, "liblucy.a")
+	destDir := path.Dir(installedLibPath)
+	if _, err := os.Stat(destDir); os.IsNotExist(err) {
+		err = os.MkdirAll(destDir, 0755)
+		if err != nil {
+			log.Fatalf("Can't create dir '%s': %s", destDir, err)
+		}
+	}
+	os.Remove(installedLibPath)
+	copyFile(tempLibPath, installedLibPath)
+}
+
+func install() {
+	build()
+	runCommand("go", "install", packageName)
+	installStaticLib()
+}
+
+func writeConfigGO() {
+	if current(buildGO, configGO) {
+		return
+	}
+	installedLibDir := path.Dir(installedLibPath)
+	cfLibPath, err := cfc.InstalledLibPath(cfPackageName)
+	if err != nil {
+		log.Fatal(err)
+	}
+	cfLibDir := path.Dir(cfLibPath)
+	content := fmt.Sprintf(
+		"// Auto-generated by build.go, specifying absolute path to static lib.\n"+
+			"package lucy\n"+
+			"// #cgo CFLAGS: -I%s/../core\n"+
+			"// #cgo CFLAGS: -I%s\n"+
+			"// #cgo CFLAGS: -I%s/autogen/include\n"+
+			"// #cgo LDFLAGS: -L%s\n"+
+			"// #cgo LDFLAGS: -L%s\n"+
+			"// #cgo LDFLAGS: -L%s\n"+
+			"// #cgo LDFLAGS: -llucy\n"+
+			"// #cgo LDFLAGS: -lclownfish\n"+
+			"import \"C\"\n",
+		buildDir, buildDir, buildDir, buildDir, installedLibDir, cfLibDir)
+	ioutil.WriteFile(configGO, []byte(content), 0666)
+}
+
+func clean() {
+	fmt.Println("Cleaning")
+	if _, err := os.Stat("Makefile"); !os.IsNotExist(err) {
+		runCommand("make", "clean")
+	}
+	files := []string{charmonizerEXE, "charmony.h", "Makefile", configGO}
+	for _, file := range files {
+		err := os.Remove(file)
+		if err == nil {
+			fmt.Println("Removing", file)
+		} else if !os.IsNotExist(err) {
+			log.Fatal(err)
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/lucy/blob/3866bbb2/go/lucy/lucy.go
----------------------------------------------------------------------
diff --git a/go/lucy/lucy.go b/go/lucy/lucy.go
new file mode 100644
index 0000000..908599a
--- /dev/null
+++ b/go/lucy/lucy.go
@@ -0,0 +1,27 @@
+/* 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.
+ */
+
+package lucy
+
+/*
+#include "lucy_parcel.h"
+*/
+import "C"
+import _ "git-wip-us.apache.org/repos/asf/lucy-clownfish.git/runtime/go/clownfish"
+
+func init() {
+	C.lucy_bootstrap_parcel()
+}

http://git-wip-us.apache.org/repos/asf/lucy/blob/3866bbb2/go/lucy/lucy_test.go
----------------------------------------------------------------------
diff --git a/go/lucy/lucy_test.go b/go/lucy/lucy_test.go
new file mode 100644
index 0000000..6a4c6d8
--- /dev/null
+++ b/go/lucy/lucy_test.go
@@ -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.
+ */
+
+package lucy_test
+
+import _ "git-wip-us.apache.org/repos/asf/lucy.git/go/lucy"
+import "testing"
+
+func TestStuff(t *testing.T) {
+}


[6/8] lucy git commit: Go stubs for Analyzer and EasyAnalyzer.

Posted by ma...@apache.org.
Go stubs for Analyzer and EasyAnalyzer.


Project: http://git-wip-us.apache.org/repos/asf/lucy/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy/commit/3d2b0fd1
Tree: http://git-wip-us.apache.org/repos/asf/lucy/tree/3d2b0fd1
Diff: http://git-wip-us.apache.org/repos/asf/lucy/diff/3d2b0fd1

Branch: refs/heads/go_bindings_1
Commit: 3d2b0fd16302c0c8f7c9e88a24e8d84bc7ffa0d3
Parents: 3866bbb
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Sun Nov 16 21:25:08 2014 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Mon Nov 17 09:28:25 2014 -0800

----------------------------------------------------------------------
 go/lucy/analysis.go | 58 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 58 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy/blob/3d2b0fd1/go/lucy/analysis.go
----------------------------------------------------------------------
diff --git a/go/lucy/analysis.go b/go/lucy/analysis.go
new file mode 100644
index 0000000..4ee58d1
--- /dev/null
+++ b/go/lucy/analysis.go
@@ -0,0 +1,58 @@
+/* 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.
+ */
+
+package lucy
+
+/*
+#include "Lucy/Analysis/Analyzer.h"
+#include "Lucy/Analysis/EasyAnalyzer.h"
+*/
+import "C"
+import "runtime"
+import "unsafe"
+
+import "git-wip-us.apache.org/repos/asf/lucy-clownfish.git/runtime/go/clownfish"
+
+type Analyzer interface {
+	clownfish.Obj
+	ToAnalyzerPtr() unsafe.Pointer
+}
+
+type EasyAnalyzer struct {
+	ref *C.lucy_EasyAnalyzer
+}
+
+func NewEasyAnalyzer(language string) *EasyAnalyzer {
+	lang := clownfish.NewString(language)
+	obj := &EasyAnalyzer{
+		C.lucy_EasyAnalyzer_new((*C.cfish_String)(lang.ToPtr())),
+	}
+	runtime.SetFinalizer(obj, (*EasyAnalyzer).finalize)
+	return obj
+}
+
+func (obj *EasyAnalyzer) finalize() {
+	C.LUCY_EasyAnalyzer_Dec_RefCount(obj.ref)
+	obj.ref = nil
+}
+
+func (obj *EasyAnalyzer) ToPtr() unsafe.Pointer {
+	return unsafe.Pointer(obj.ref)
+}
+
+func (obj *EasyAnalyzer) ToAnalyzerPtr() unsafe.Pointer {
+	return obj.ToPtr()
+}


[2/8] lucy git commit: Regen charmonizer in prep for Go bindings.

Posted by ma...@apache.org.
Regen charmonizer in prep for Go bindings.


Project: http://git-wip-us.apache.org/repos/asf/lucy/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy/commit/b4ce4965
Tree: http://git-wip-us.apache.org/repos/asf/lucy/tree/b4ce4965
Diff: http://git-wip-us.apache.org/repos/asf/lucy/diff/b4ce4965

Branch: refs/heads/go_bindings_1
Commit: b4ce4965bb19ad3649aee062c52314d25a444de8
Parents: 1b06574
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Sun Nov 16 16:37:32 2014 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Sun Nov 16 16:37:32 2014 -0800

----------------------------------------------------------------------
 common/charmonizer.c | 7 +++++++
 1 file changed, 7 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy/blob/b4ce4965/common/charmonizer.c
----------------------------------------------------------------------
diff --git a/common/charmonizer.c b/common/charmonizer.c
index 465938b..12dade5 100644
--- a/common/charmonizer.c
+++ b/common/charmonizer.c
@@ -7792,6 +7792,8 @@ int main(int argc, const char **argv) {
     chaz_CLI_register(cli, "clownfish-prefix",
                       "prefix of Clownfish installation",
                       CHAZ_CLI_ARG_OPTIONAL);
+    chaz_CLI_register(cli, "enable-go", "enable Go bindings",
+                      CHAZ_CLI_NO_ARG);
     chaz_CLI_set_usage(cli, "Usage: charmonizer [OPTIONS] [-- [CFLAGS]]");
     if (!chaz_Probe_parse_cli_args(argc, argv, cli)) {
         chaz_Probe_die_usage();
@@ -7920,6 +7922,9 @@ lucy_MakeFile_new(chaz_CLI *cli) {
     if (chaz_CLI_defined(cli, "enable-perl")) {
         self->host_src_dir = "xs";
     }
+	else if (chaz_CLI_defined(cli, "enable-go")) {
+        self->host_src_dir = "../c/src";
+	}
     else {
         self->host_src_dir = "src";
     }
@@ -8104,6 +8109,8 @@ lucy_MakeFile_write(lucy_MakeFile *self) {
     chaz_MakeFile_add_rule(self->makefile, "all", scratch);
     free(scratch);
 
+    chaz_MakeFile_add_rule(self->makefile, "static", self->static_lib_filename);
+
     chaz_MakeFile_add_lemon_exe(self->makefile, self->lemon_dir);
     chaz_MakeFile_add_lemon_grammar(self->makefile, self->json_parser);