From af8fdff41e260b1b21be0e127afb536980f43804 Mon Sep 17 00:00:00 2001 From: Joel Martin Date: Mon, 6 Oct 2014 20:36:23 -0500 Subject: go: add step4_if_fn_do --- go/src/core/core.go | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 go/src/core/core.go (limited to 'go/src/core') diff --git a/go/src/core/core.go b/go/src/core/core.go new file mode 100644 index 0000000..9df71a6 --- /dev/null +++ b/go/src/core/core.go @@ -0,0 +1,90 @@ +package core + +import ( + "errors" + "fmt" +) + +import ( + . "types" + "printer" +) + + +// String functions + +func pr_str(a []MalType) (MalType, error) { + return printer.Pr_list(a, true, "", "", " "), nil +} + +func str(a []MalType) (MalType, error) { + return printer.Pr_list(a, false, "", "", ""), nil +} + +func prn(a []MalType) (MalType, error) { + fmt.Println(printer.Pr_list(a, true, "", "", " ")) + return nil, nil +} + +func println(a []MalType) (MalType, error) { + fmt.Println(printer.Pr_list(a, false, "", "", " ")) + return nil, nil +} + + +// Sequence functions + +func empty_Q(a []MalType) (MalType, error) { + switch obj := a[0].(type) { + case List: return len(obj.Val) == 0, nil + case Vector: return len(obj.Val) == 0, nil + case nil: return true, nil + default: return nil, errors.New("Count called on non-sequence") + } +} + +func count(a []MalType) (MalType, error) { + switch obj := a[0].(type) { + case List: return len(obj.Val), nil + case Vector: return len(obj.Val), nil + case nil: return 0, nil + default: return nil, errors.New("Count called on non-sequence") + } +} + + +// core namespace +var NS = map[string]MalType{ + "=": func(a []MalType) (MalType, error) { + return Equal_Q(a[0], a[1]), nil }, + + "pr-str": func(a []MalType) (MalType, error) { return pr_str(a) }, + "str": func(a []MalType) (MalType, error) { return str(a) }, + "prn": func(a []MalType) (MalType, error) { return prn(a) }, + "println": func(a []MalType) (MalType, error) { return println(a) }, + + "<": func(a []MalType) (MalType, error) { + return a[0].(int) < a[1].(int), nil }, + "<=": func(a []MalType) (MalType, error) { + return a[0].(int) <= a[1].(int), nil }, + ">": func(a []MalType) (MalType, error) { + return a[0].(int) > a[1].(int), nil }, + ">=": func(a []MalType) (MalType, error) { + return a[0].(int) >= a[1].(int), nil }, + "+": func(a []MalType) (MalType, error) { + return a[0].(int) + a[1].(int), nil }, + "-": func(a []MalType) (MalType, error) { + return a[0].(int) - a[1].(int), nil }, + "*": func(a []MalType) (MalType, error) { + return a[0].(int) * a[1].(int), nil }, + "/": func(a []MalType) (MalType, error) { + return a[0].(int) / a[1].(int), nil }, + + "list": func(a []MalType) (MalType, error) { + return List{a}, nil }, + "list?": func(a []MalType) (MalType, error) { + return List_Q(a[0]), nil }, + + "empty?": empty_Q, + "count": count, + } -- cgit v1.2.3 From ad95503cea8ca85e9188effa87681275283157bf Mon Sep 17 00:00:00 2001 From: Joel Martin Date: Mon, 6 Oct 2014 22:27:28 -0500 Subject: go: add step6_file --- go/src/core/core.go | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'go/src/core') diff --git a/go/src/core/core.go b/go/src/core/core.go index 9df71a6..94e2452 100644 --- a/go/src/core/core.go +++ b/go/src/core/core.go @@ -2,11 +2,13 @@ package core import ( "errors" + "io/ioutil" "fmt" ) import ( . "types" + "reader" "printer" ) @@ -31,6 +33,12 @@ func println(a []MalType) (MalType, error) { return nil, nil } +func slurp(a []MalType) (MalType, error) { + b, e := ioutil.ReadFile(a[0].(string)) + if e != nil { return nil, e } + return string(b), nil +} + // Sequence functions @@ -62,6 +70,9 @@ var NS = map[string]MalType{ "str": func(a []MalType) (MalType, error) { return str(a) }, "prn": func(a []MalType) (MalType, error) { return prn(a) }, "println": func(a []MalType) (MalType, error) { return println(a) }, + "read-string": func(a []MalType) (MalType, error) { + return reader.Read_str(a[0].(string)) }, + "slurp": slurp, "<": func(a []MalType) (MalType, error) { return a[0].(int) < a[1].(int), nil }, -- cgit v1.2.3 From aeabd2145ff133cc6991166d8f1023ed33e223c8 Mon Sep 17 00:00:00 2001 From: Joel Martin Date: Mon, 6 Oct 2014 23:31:11 -0500 Subject: go: add step7_quote --- go/src/core/core.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'go/src/core') diff --git a/go/src/core/core.go b/go/src/core/core.go index 94e2452..65475bb 100644 --- a/go/src/core/core.go +++ b/go/src/core/core.go @@ -42,6 +42,20 @@ func slurp(a []MalType) (MalType, error) { // Sequence functions +func cons(a []MalType) (MalType, error) { + val := a[0] + lst, e := GetSlice(a[1]); if e != nil { return nil, e } + + return List{append([]MalType{val}, lst...)}, nil +} + +func concat(a []MalType) (MalType, error) { + lst1, e := GetSlice(a[0]); if e != nil { return nil, e } + lst2, e := GetSlice(a[1]); if e != nil { return nil, e } + + return List{append(lst1, lst2...)}, nil +} + func empty_Q(a []MalType) (MalType, error) { switch obj := a[0].(type) { case List: return len(obj.Val) == 0, nil @@ -96,6 +110,8 @@ var NS = map[string]MalType{ "list?": func(a []MalType) (MalType, error) { return List_Q(a[0]), nil }, + "cons": cons, + "concat": concat, "empty?": empty_Q, "count": count, } -- cgit v1.2.3 From 82efc357ba67da1eaf35ca92b6f249a344aae8d5 Mon Sep 17 00:00:00 2001 From: Joel Martin Date: Mon, 6 Oct 2014 23:53:51 -0500 Subject: go: add step8_macros --- go/src/core/core.go | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) (limited to 'go/src/core') diff --git a/go/src/core/core.go b/go/src/core/core.go index 65475bb..3c6693e 100644 --- a/go/src/core/core.go +++ b/go/src/core/core.go @@ -50,12 +50,35 @@ func cons(a []MalType) (MalType, error) { } func concat(a []MalType) (MalType, error) { - lst1, e := GetSlice(a[0]); if e != nil { return nil, e } - lst2, e := GetSlice(a[1]); if e != nil { return nil, e } + if len(a) == 0 { return List{}, nil } + slc1, e := GetSlice(a[0]); if e != nil { return nil, e } + for i := 1; i < len(a); i+=1 { + slc2, e := GetSlice(a[i]); if e != nil { return nil, e } + slc1 = append(slc1, slc2...) + } + return List{slc1}, nil +} + +func nth(a []MalType) (MalType, error) { + slc, e := GetSlice(a[0]); if e != nil { return nil, e } + idx := a[1].(int) + return slc[idx], nil +} - return List{append(lst1, lst2...)}, nil +func first(a []MalType) (MalType, error) { + if len(a) == 0 { return nil, nil } + slc, e := GetSlice(a[0]); if e != nil { return nil, e } + if len(slc) == 0 { return nil, nil } + return slc[0], nil } +func rest(a []MalType) (MalType, error) { + slc, e := GetSlice(a[0]); if e != nil { return nil, e } + if len(slc) == 0 { return List{}, nil } + return List{slc[1:]}, nil +} + + func empty_Q(a []MalType) (MalType, error) { switch obj := a[0].(type) { case List: return len(obj.Val) == 0, nil @@ -112,6 +135,9 @@ var NS = map[string]MalType{ "cons": cons, "concat": concat, + "nth": nth, + "first": first, + "rest": rest, "empty?": empty_Q, "count": count, } -- cgit v1.2.3 From d667a1bb2e7294f8722bb31f1e6e8207b971c913 Mon Sep 17 00:00:00 2001 From: Joel Martin Date: Thu, 9 Oct 2014 18:05:30 -0500 Subject: go: add stepA_more. try* and more core functions. --- go/src/core/core.go | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) (limited to 'go/src/core') diff --git a/go/src/core/core.go b/go/src/core/core.go index 3c6693e..b3961e1 100644 --- a/go/src/core/core.go +++ b/go/src/core/core.go @@ -12,6 +12,11 @@ import ( "printer" ) +// Errors/Exceptions +func throw(a []MalType) (MalType, error) { + return nil, MalError{a[0]} +} + // String functions @@ -97,11 +102,46 @@ func count(a []MalType) (MalType, error) { } } +func apply(a []MalType) (MalType, error) { + if len(a) < 2 { return nil, errors.New("apply requires at least 2 args") } + f := a[0] + args := []MalType{} + for _, b := range a[1:len(a)-1] { + args = append(args, b) + } + last, e := GetSlice(a[len(a)-1]); if e != nil { return nil, e } + args = append(args, last...) + return Apply(f, args) +} + +func do_map(a []MalType) (MalType, error) { + if len(a) != 2 { return nil, errors.New("map requires 2 args") } + f := a[0] + results := []MalType{} + args, e := GetSlice(a[1]); if e != nil { return nil, e } + for _, arg := range args { + res, e := Apply(f, []MalType{arg}) + results = append(results, res) + if e != nil { return nil, e } + } + return List{results}, nil +} + + // core namespace var NS = map[string]MalType{ "=": func(a []MalType) (MalType, error) { return Equal_Q(a[0], a[1]), nil }, + "throw": throw, + "nil?": func(a []MalType) (MalType, error) { + return Nil_Q(a[0]), nil }, + "true?": func(a []MalType) (MalType, error) { + return True_Q(a[0]), nil }, + "false?": func(a []MalType) (MalType, error) { + return False_Q(a[0]), nil }, + "symbol?": func(a []MalType) (MalType, error) { + return Symbol_Q(a[0]), nil }, "pr-str": func(a []MalType) (MalType, error) { return pr_str(a) }, "str": func(a []MalType) (MalType, error) { return str(a) }, @@ -133,6 +173,8 @@ var NS = map[string]MalType{ "list?": func(a []MalType) (MalType, error) { return List_Q(a[0]), nil }, + "sequential?": func(a []MalType) (MalType, error) { + return Sequential_Q(a[0]), nil }, "cons": cons, "concat": concat, "nth": nth, @@ -140,4 +182,6 @@ var NS = map[string]MalType{ "rest": rest, "empty?": empty_Q, "count": count, + "apply": apply, + "map": do_map, } -- cgit v1.2.3 From ad7e866ea1d4d035d876e58bca681a72099449af Mon Sep 17 00:00:00 2001 From: Joel Martin Date: Thu, 9 Oct 2014 18:27:47 -0500 Subject: go: add readline.go that wraps libreadline/libedit --- go/src/core/core.go | 3 +++ 1 file changed, 3 insertions(+) (limited to 'go/src/core') diff --git a/go/src/core/core.go b/go/src/core/core.go index b3961e1..cd63930 100644 --- a/go/src/core/core.go +++ b/go/src/core/core.go @@ -10,6 +10,7 @@ import ( . "types" "reader" "printer" + "readline" ) // Errors/Exceptions @@ -150,6 +151,8 @@ var NS = map[string]MalType{ "read-string": func(a []MalType) (MalType, error) { return reader.Read_str(a[0].(string)) }, "slurp": slurp, + "readline": func(a []MalType) (MalType, error) { + return readline.Readline(a[0].(string)) }, "<": func(a []MalType) (MalType, error) { return a[0].(int) < a[1].(int), nil }, -- cgit v1.2.3 From f2c9811fd8cbb205fad68952ebc1ba5d310f148d Mon Sep 17 00:00:00 2001 From: Joel Martin Date: Thu, 9 Oct 2014 19:14:43 -0500 Subject: go: add hash-map support. --- go/src/core/core.go | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) (limited to 'go/src/core') diff --git a/go/src/core/core.go b/go/src/core/core.go index cd63930..cdb7d8f 100644 --- a/go/src/core/core.go +++ b/go/src/core/core.go @@ -46,6 +46,72 @@ func slurp(a []MalType) (MalType, error) { } +// Hash Map functions +func assoc(a []MalType) (MalType, error) { + if len(a) <3 { return nil, errors.New("assoc requires at least 3 arguments") } + if (len(a) % 2 != 1) { return nil, errors.New("assoc requires odd number of arguments") } + if !HashMap_Q(a[0]) { return nil, errors.New("assoc called on non-hash map") } + old_hm := a[0].(map[string]MalType) + new_hm := map[string]MalType{} + // copy + for k, v := range old_hm { new_hm[k] = v } + for i := 1; i < len(a); i+=2 { + key := a[i] + if !String_Q(key) { return nil, errors.New("assoc called with non-string key") } + new_hm[key.(string)] = a[i+1] + } + return new_hm, nil +} + +func dissoc(a []MalType) (MalType, error) { + if len(a) <2 { return nil, errors.New("dissoc requires at least 3 arguments") } + if !HashMap_Q(a[0]) { return nil, errors.New("dissoc called on non-hash map") } + old_hm := a[0].(map[string]MalType) + new_hm := map[string]MalType{} + // copy + for k, v := range old_hm { new_hm[k] = v } + for i := 1; i < len(a); i+=1 { + key := a[i] + if !String_Q(key) { return nil, errors.New("dissoc called with non-string key") } + delete(new_hm,key.(string)) + } + return new_hm, nil +} + +func get(a []MalType) (MalType, error) { + if len(a) != 2 { return nil, errors.New("get requires 2 arguments") } + if Nil_Q(a[0]) { return nil, nil } + if !HashMap_Q(a[0]) { return nil, errors.New("get called on non-hash map") } + if !String_Q(a[1]) { return nil, errors.New("get called with non-string key") } + return a[0].(map[string]MalType)[a[1].(string)], nil +} + +func contains_Q(hm MalType, key MalType) (MalType, error) { + if Nil_Q(hm) { return nil, nil } + if !HashMap_Q(hm) { return nil, errors.New("get called on non-hash map") } + if !String_Q(key) { return nil, errors.New("get called with non-string key") } + _, ok := hm.(map[string]MalType)[key.(string)] + return ok, nil +} + +func keys(a []MalType) (MalType, error) { + if !HashMap_Q(a[0]) { return nil, errors.New("keys called on non-hash map") } + slc := []MalType{} + for k, _ := range a[0].(map[string]MalType) { + slc = append(slc, k) + } + return List{slc}, nil +} +func vals(a []MalType) (MalType, error) { + if !HashMap_Q(a[0]) { return nil, errors.New("keys called on non-hash map") } + slc := []MalType{} + for _, v := range a[0].(map[string]MalType) { + slc = append(slc, v) + } + return List{slc}, nil +} + + // Sequence functions func cons(a []MalType) (MalType, error) { @@ -98,6 +164,7 @@ func count(a []MalType) (MalType, error) { switch obj := a[0].(type) { case List: return len(obj.Val), nil case Vector: return len(obj.Val), nil + case map[string]MalType: return len(obj), nil case nil: return 0, nil default: return nil, errors.New("Count called on non-sequence") } @@ -175,6 +242,21 @@ var NS = map[string]MalType{ return List{a}, nil }, "list?": func(a []MalType) (MalType, error) { return List_Q(a[0]), nil }, + "vector": func(a []MalType) (MalType, error) { + return Vector{a}, nil }, + "vector?": func(a []MalType) (MalType, error) { + return Vector_Q(a[0]), nil }, + "hash-map": func(a []MalType) (MalType, error) { + return NewHashMap(List{a}) }, + "map?": func(a []MalType) (MalType, error) { + return HashMap_Q(a[0]), nil }, + "assoc": assoc, + "dissoc": dissoc, + "get": get, + "contains?": func(a []MalType) (MalType, error) { + return contains_Q(a[0], a[1]) }, + "keys": keys, + "vals": vals, "sequential?": func(a []MalType) (MalType, error) { return Sequential_Q(a[0]), nil }, -- cgit v1.2.3 From f2544a9467ea032aff505b3ced3b4b3510a828fe Mon Sep 17 00:00:00 2001 From: Joel Martin Date: Thu, 9 Oct 2014 21:37:00 -0500 Subject: go: add metadata and atoms. HashMap dedicated type. HashMap needs a dedicated type now to be able to store the metadata. --- go/src/core/core.go | 104 ++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 81 insertions(+), 23 deletions(-) (limited to 'go/src/core') diff --git a/go/src/core/core.go b/go/src/core/core.go index cdb7d8f..f5d5842 100644 --- a/go/src/core/core.go +++ b/go/src/core/core.go @@ -47,18 +47,21 @@ func slurp(a []MalType) (MalType, error) { // Hash Map functions +func copy_hash_map(hm HashMap) (HashMap) { + new_hm := HashMap{map[string]MalType{},nil} + for k, v := range hm.Val { new_hm.Val[k] = v } + return new_hm +} + func assoc(a []MalType) (MalType, error) { if len(a) <3 { return nil, errors.New("assoc requires at least 3 arguments") } if (len(a) % 2 != 1) { return nil, errors.New("assoc requires odd number of arguments") } if !HashMap_Q(a[0]) { return nil, errors.New("assoc called on non-hash map") } - old_hm := a[0].(map[string]MalType) - new_hm := map[string]MalType{} - // copy - for k, v := range old_hm { new_hm[k] = v } + new_hm := copy_hash_map(a[0].(HashMap)) for i := 1; i < len(a); i+=2 { key := a[i] if !String_Q(key) { return nil, errors.New("assoc called with non-string key") } - new_hm[key.(string)] = a[i+1] + new_hm.Val[key.(string)] = a[i+1] } return new_hm, nil } @@ -66,14 +69,11 @@ func assoc(a []MalType) (MalType, error) { func dissoc(a []MalType) (MalType, error) { if len(a) <2 { return nil, errors.New("dissoc requires at least 3 arguments") } if !HashMap_Q(a[0]) { return nil, errors.New("dissoc called on non-hash map") } - old_hm := a[0].(map[string]MalType) - new_hm := map[string]MalType{} - // copy - for k, v := range old_hm { new_hm[k] = v } + new_hm := copy_hash_map(a[0].(HashMap)) for i := 1; i < len(a); i+=1 { key := a[i] if !String_Q(key) { return nil, errors.New("dissoc called with non-string key") } - delete(new_hm,key.(string)) + delete(new_hm.Val,key.(string)) } return new_hm, nil } @@ -83,32 +83,32 @@ func get(a []MalType) (MalType, error) { if Nil_Q(a[0]) { return nil, nil } if !HashMap_Q(a[0]) { return nil, errors.New("get called on non-hash map") } if !String_Q(a[1]) { return nil, errors.New("get called with non-string key") } - return a[0].(map[string]MalType)[a[1].(string)], nil + return a[0].(HashMap).Val[a[1].(string)], nil } func contains_Q(hm MalType, key MalType) (MalType, error) { if Nil_Q(hm) { return nil, nil } if !HashMap_Q(hm) { return nil, errors.New("get called on non-hash map") } if !String_Q(key) { return nil, errors.New("get called with non-string key") } - _, ok := hm.(map[string]MalType)[key.(string)] + _, ok := hm.(HashMap).Val[key.(string)] return ok, nil } func keys(a []MalType) (MalType, error) { if !HashMap_Q(a[0]) { return nil, errors.New("keys called on non-hash map") } slc := []MalType{} - for k, _ := range a[0].(map[string]MalType) { + for k, _ := range a[0].(HashMap).Val { slc = append(slc, k) } - return List{slc}, nil + return List{slc,nil}, nil } func vals(a []MalType) (MalType, error) { if !HashMap_Q(a[0]) { return nil, errors.New("keys called on non-hash map") } slc := []MalType{} - for _, v := range a[0].(map[string]MalType) { + for _, v := range a[0].(HashMap).Val { slc = append(slc, v) } - return List{slc}, nil + return List{slc,nil}, nil } @@ -118,7 +118,7 @@ func cons(a []MalType) (MalType, error) { val := a[0] lst, e := GetSlice(a[1]); if e != nil { return nil, e } - return List{append([]MalType{val}, lst...)}, nil + return List{append([]MalType{val}, lst...),nil}, nil } func concat(a []MalType) (MalType, error) { @@ -128,7 +128,7 @@ func concat(a []MalType) (MalType, error) { slc2, e := GetSlice(a[i]); if e != nil { return nil, e } slc1 = append(slc1, slc2...) } - return List{slc1}, nil + return List{slc1,nil}, nil } func nth(a []MalType) (MalType, error) { @@ -147,7 +147,7 @@ func first(a []MalType) (MalType, error) { func rest(a []MalType) (MalType, error) { slc, e := GetSlice(a[0]); if e != nil { return nil, e } if len(slc) == 0 { return List{}, nil } - return List{slc[1:]}, nil + return List{slc[1:],nil}, nil } @@ -192,10 +192,60 @@ func do_map(a []MalType) (MalType, error) { results = append(results, res) if e != nil { return nil, e } } - return List{results}, nil + return List{results,nil}, nil } +// Metadata functions +func with_meta(a []MalType) (MalType, error) { + if len(a) != 2 { return nil, errors.New("with-meta requires 2 args") } + obj := a[0]; m := a[1] + switch tobj := obj.(type) { + case List: return List{tobj.Val,m}, nil + case Vector: return Vector{tobj.Val,m}, nil + case HashMap: return HashMap{tobj.Val,m}, nil + case MalFunc: fn := tobj; fn.Meta = m; return fn, nil + default: return nil, errors.New("with-meta not supported on type") + } +} + +func meta(a []MalType) (MalType, error) { + obj := a[0] + switch tobj := obj.(type) { + case List: return tobj.Meta, nil + case Vector: return tobj.Meta, nil + case HashMap: return tobj.Meta, nil + case MalFunc: return tobj.Meta, nil + default: return nil, errors.New("meta not supported on type") + } +} + + +// Atom functions +func deref(a []MalType) (MalType, error) { + if !Atom_Q(a[0]) { return nil, errors.New("deref called with non-atom") } + return a[0].(*Atom).Val, nil +} + +func reset_BANG(a []MalType) (MalType, error) { + if !Atom_Q(a[0]) { return nil, errors.New("reset! called with non-atom") } + a[0].(*Atom).Set(a[1]) + return a[1], nil +} + +func swap_BANG(a []MalType) (MalType, error) { + if !Atom_Q(a[0]) { return nil, errors.New("swap! called with non-atom") } + if len(a) < 2 { return nil, errors.New("swap! requires at least 2 args") } + atm := a[0].(*Atom) + args := []MalType{atm.Val} + f := a[1] + args = append(args, a[2:]...) + res, e := Apply(f, args) + if e != nil { return nil, e } + atm.Set(res) + return res, nil +} + // core namespace var NS = map[string]MalType{ @@ -239,15 +289,15 @@ var NS = map[string]MalType{ return a[0].(int) / a[1].(int), nil }, "list": func(a []MalType) (MalType, error) { - return List{a}, nil }, + return List{a,nil}, nil }, "list?": func(a []MalType) (MalType, error) { return List_Q(a[0]), nil }, "vector": func(a []MalType) (MalType, error) { - return Vector{a}, nil }, + return Vector{a,nil}, nil }, "vector?": func(a []MalType) (MalType, error) { return Vector_Q(a[0]), nil }, "hash-map": func(a []MalType) (MalType, error) { - return NewHashMap(List{a}) }, + return NewHashMap(List{a,nil}) }, "map?": func(a []MalType) (MalType, error) { return HashMap_Q(a[0]), nil }, "assoc": assoc, @@ -269,4 +319,12 @@ var NS = map[string]MalType{ "count": count, "apply": apply, "map": do_map, + + "with-meta": with_meta, + "meta": meta, + "atom": func(a []MalType) (MalType, error) { + return &Atom{a[0],nil}, nil }, + "deref": deref, + "reset!": reset_BANG, + "swap!": swap_BANG, } -- cgit v1.2.3 From 1771ab50b87c745181e4e30f94b63e3f23d33dac Mon Sep 17 00:00:00 2001 From: Joel Martin Date: Thu, 9 Oct 2014 22:10:15 -0500 Subject: go: update README. Backport Func usage. --- go/src/core/core.go | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'go/src/core') diff --git a/go/src/core/core.go b/go/src/core/core.go index f5d5842..57cf932 100644 --- a/go/src/core/core.go +++ b/go/src/core/core.go @@ -195,6 +195,34 @@ func do_map(a []MalType) (MalType, error) { return List{results,nil}, nil } +func conj(a []MalType) (MalType, error) { + if len(a) <2 { return nil, errors.New("conj requires at least 2 arguments") } + switch seq := a[0].(type) { + case List: + new_slc := []MalType{} + for i := len(a)-1 ; i > 0 ; i-=1 { + new_slc = append(new_slc, a[i]) + } + return List{append(new_slc, seq.Val...),nil}, nil + case Vector: + new_slc := seq.Val + for _, x := range a[1:] { + new_slc = append(new_slc, x) + } + return Vector{new_slc,nil}, nil + } + + if !HashMap_Q(a[0]) { return nil, errors.New("dissoc called on non-hash map") } + new_hm := copy_hash_map(a[0].(HashMap)) + for i := 1; i < len(a); i+=1 { + key := a[i] + if !String_Q(key) { return nil, errors.New("dissoc called with non-string key") } + delete(new_hm.Val,key.(string)) + } + return new_hm, nil +} + + // Metadata functions func with_meta(a []MalType) (MalType, error) { @@ -204,6 +232,7 @@ func with_meta(a []MalType) (MalType, error) { case List: return List{tobj.Val,m}, nil case Vector: return Vector{tobj.Val,m}, nil case HashMap: return HashMap{tobj.Val,m}, nil + case Func: return Func{tobj.Fn,m}, nil case MalFunc: fn := tobj; fn.Meta = m; return fn, nil default: return nil, errors.New("with-meta not supported on type") } @@ -215,6 +244,7 @@ func meta(a []MalType) (MalType, error) { case List: return tobj.Meta, nil case Vector: return tobj.Meta, nil case HashMap: return tobj.Meta, nil + case Func: return tobj.Meta, nil case MalFunc: return tobj.Meta, nil default: return nil, errors.New("meta not supported on type") } @@ -319,11 +349,14 @@ var NS = map[string]MalType{ "count": count, "apply": apply, "map": do_map, + "conj": conj, "with-meta": with_meta, "meta": meta, "atom": func(a []MalType) (MalType, error) { return &Atom{a[0],nil}, nil }, + "atom?": func(a []MalType) (MalType, error) { + return Atom_Q(a[0]), nil }, "deref": deref, "reset!": reset_BANG, "swap!": swap_BANG, -- cgit v1.2.3 From fb5c165838a658c79c9772c264a0a1673bc5081b Mon Sep 17 00:00:00 2001 From: Joel Martin Date: Mon, 27 Oct 2014 23:49:55 -0500 Subject: go: add time-ms. Ruby: fix step9,A content. --- go/src/core/core.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'go/src/core') diff --git a/go/src/core/core.go b/go/src/core/core.go index 57cf932..17e92f0 100644 --- a/go/src/core/core.go +++ b/go/src/core/core.go @@ -4,6 +4,7 @@ import ( "errors" "io/ioutil" "fmt" + "time" ) import ( @@ -45,6 +46,11 @@ func slurp(a []MalType) (MalType, error) { return string(b), nil } +// Number functions +func time_ms(a []MalType) (MalType, error) { + return int(time.Now().UnixNano() / int64(time.Millisecond)), nil +} + // Hash Map functions func copy_hash_map(hm HashMap) (HashMap) { @@ -87,7 +93,7 @@ func get(a []MalType) (MalType, error) { } func contains_Q(hm MalType, key MalType) (MalType, error) { - if Nil_Q(hm) { return nil, nil } + if Nil_Q(hm) { return false, nil } if !HashMap_Q(hm) { return nil, errors.New("get called on non-hash map") } if !String_Q(key) { return nil, errors.New("get called with non-string key") } _, ok := hm.(HashMap).Val[key.(string)] @@ -317,6 +323,7 @@ var NS = map[string]MalType{ return a[0].(int) * a[1].(int), nil }, "/": func(a []MalType) (MalType, error) { return a[0].(int) / a[1].(int), nil }, + "time-ms": time_ms, "list": func(a []MalType) (MalType, error) { return List{a,nil}, nil }, -- cgit v1.2.3 From b8ee29b22fbaa7a01f2754b4d6dd9af52e02017c Mon Sep 17 00:00:00 2001 From: Joel Martin Date: Thu, 18 Dec 2014 20:33:49 -0600 Subject: All: add keywords. Also, fix nth and count to match cloure. --- go/src/core/core.go | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'go/src/core') diff --git a/go/src/core/core.go b/go/src/core/core.go index 17e92f0..2acca69 100644 --- a/go/src/core/core.go +++ b/go/src/core/core.go @@ -140,7 +140,11 @@ func concat(a []MalType) (MalType, error) { func nth(a []MalType) (MalType, error) { slc, e := GetSlice(a[0]); if e != nil { return nil, e } idx := a[1].(int) - return slc[idx], nil + if idx < len(slc) { + return slc[idx], nil + } else { + return nil, errors.New("nth: index out of range") + } } func first(a []MalType) (MalType, error) { @@ -294,8 +298,14 @@ var NS = map[string]MalType{ return True_Q(a[0]), nil }, "false?": func(a []MalType) (MalType, error) { return False_Q(a[0]), nil }, + "symbol": func(a []MalType) (MalType, error) { + return Symbol{a[0].(string)}, nil }, "symbol?": func(a []MalType) (MalType, error) { return Symbol_Q(a[0]), nil }, + "keyword": func(a []MalType) (MalType, error) { + return NewKeyword(a[0].(string)) }, + "keyword?": func(a []MalType) (MalType, error) { + return Keyword_Q(a[0]), nil }, "pr-str": func(a []MalType) (MalType, error) { return pr_str(a) }, "str": func(a []MalType) (MalType, error) { return str(a) }, -- cgit v1.2.3