diff options
Diffstat (limited to 'go/src/core/core.go')
| -rw-r--r-- | go/src/core/core.go | 686 |
1 files changed, 411 insertions, 275 deletions
diff --git a/go/src/core/core.go b/go/src/core/core.go index 2acca69..159acc7 100644 --- a/go/src/core/core.go +++ b/go/src/core/core.go @@ -1,380 +1,516 @@ package core import ( - "errors" - "io/ioutil" - "fmt" - "time" + "errors" + "fmt" + "io/ioutil" + "time" ) import ( - . "types" - "reader" - "printer" - "readline" + "printer" + "reader" + "readline" + . "types" ) // Errors/Exceptions func throw(a []MalType) (MalType, error) { - return nil, MalError{a[0]} + return nil, MalError{a[0]} } - // String functions func pr_str(a []MalType) (MalType, error) { - return printer.Pr_list(a, true, "", "", " "), nil + return printer.Pr_list(a, true, "", "", " "), nil } func str(a []MalType) (MalType, error) { - return printer.Pr_list(a, false, "", "", ""), nil + return printer.Pr_list(a, false, "", "", ""), nil } func prn(a []MalType) (MalType, error) { - fmt.Println(printer.Pr_list(a, true, "", "", " ")) - return nil, nil + 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 + fmt.Println(printer.Pr_list(a, false, "", "", " ")) + 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 + b, e := ioutil.ReadFile(a[0].(string)) + if e != nil { + return nil, e + } + return string(b), nil } // Number functions func time_ms(a []MalType) (MalType, error) { - return int(time.Now().UnixNano() / int64(time.Millisecond)), nil + return int(time.Now().UnixNano() / int64(time.Millisecond)), nil } - // 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 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") } - 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.Val[key.(string)] = a[i+1] - } - return new_hm, nil + 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") + } + 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.Val[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") } - 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 + 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") + } + 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 } 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].(HashMap).Val[a[1].(string)], nil + 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].(HashMap).Val[a[1].(string)], nil } func contains_Q(hm MalType, key MalType) (MalType, error) { - 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)] - return ok, 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)] + 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].(HashMap).Val { - slc = append(slc, k) - } - return List{slc,nil}, nil + if !HashMap_Q(a[0]) { + return nil, errors.New("keys called on non-hash map") + } + slc := []MalType{} + for k, _ := range a[0].(HashMap).Val { + slc = append(slc, k) + } + 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].(HashMap).Val { - slc = append(slc, v) - } - return List{slc,nil}, nil + if !HashMap_Q(a[0]) { + return nil, errors.New("keys called on non-hash map") + } + slc := []MalType{} + for _, v := range a[0].(HashMap).Val { + slc = append(slc, v) + } + return List{slc, nil}, nil } - // Sequence functions func cons(a []MalType) (MalType, error) { - val := a[0] - lst, e := GetSlice(a[1]); if e != nil { return nil, e } + val := a[0] + lst, e := GetSlice(a[1]) + if e != nil { + return nil, e + } - return List{append([]MalType{val}, lst...),nil}, nil + return List{append([]MalType{val}, lst...), nil}, nil } func concat(a []MalType) (MalType, error) { - 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}, nil + 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}, nil } func nth(a []MalType) (MalType, error) { - slc, e := GetSlice(a[0]); if e != nil { return nil, e } - idx := a[1].(int) - if idx < len(slc) { - return slc[idx], nil - } else { - return nil, errors.New("nth: index out of range") - } + slc, e := GetSlice(a[0]) + if e != nil { + return nil, e + } + idx := a[1].(int) + if idx < len(slc) { + return slc[idx], nil + } else { + return nil, errors.New("nth: index out of range") + } } 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 + 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}, nil + slc, e := GetSlice(a[0]) + if e != nil { + return nil, e + } + if len(slc) == 0 { + return List{}, nil + } + return List{slc[1:], nil}, nil } - 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") - } + 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 map[string]MalType: return len(obj), nil - case nil: return 0, nil - default: return nil, errors.New("Count called on non-sequence") - } + 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") + } } 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) + 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}, nil + 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}, 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 + 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) { - 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 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") - } + 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 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") + } } 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 Func: return tobj.Meta, nil - case MalFunc: return tobj.Meta, nil - default: return nil, errors.New("meta not supported on type") - } + 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 Func: + 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 + 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 + 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 + 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{ - "=": 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{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) }, - "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, - "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 }, - "<=": 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 }, - "time-ms": time_ms, - - "list": func(a []MalType) (MalType, error) { - 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}, nil }, - "vector?": func(a []MalType) (MalType, error) { - return Vector_Q(a[0]), nil }, - "hash-map": func(a []MalType) (MalType, error) { - return NewHashMap(List{a,nil}) }, - "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 }, - "cons": cons, - "concat": concat, - "nth": nth, - "first": first, - "rest": rest, - "empty?": empty_Q, - "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, - } + "=": 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{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) }, + "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, + "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 + }, + "<=": 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 + }, + "time-ms": time_ms, + + "list": func(a []MalType) (MalType, error) { + 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}, nil + }, + "vector?": func(a []MalType) (MalType, error) { + return Vector_Q(a[0]), nil + }, + "hash-map": func(a []MalType) (MalType, error) { + return NewHashMap(List{a, nil}) + }, + "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 + }, + "cons": cons, + "concat": concat, + "nth": nth, + "first": first, + "rest": rest, + "empty?": empty_Q, + "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, +} |
