diff options
| author | Joel Martin <github@martintribe.org> | 2014-12-18 20:33:49 -0600 |
|---|---|---|
| committer | Joel Martin <github@martintribe.org> | 2015-01-09 16:16:50 -0600 |
| commit | b8ee29b22fbaa7a01f2754b4d6dd9af52e02017c (patch) | |
| tree | f4d977ed220e9a3f665cfbf4f68770a81e4c2095 /go | |
| parent | aaba249304b184e12e2445ab22d66df1f39a51a5 (diff) | |
| download | mal-b8ee29b22fbaa7a01f2754b4d6dd9af52e02017c.tar.gz mal-b8ee29b22fbaa7a01f2754b4d6dd9af52e02017c.zip | |
All: add keywords.
Also, fix nth and count to match cloure.
Diffstat (limited to 'go')
| -rw-r--r-- | go/src/core/core.go | 12 | ||||
| -rw-r--r-- | go/src/env/env.go | 14 | ||||
| -rw-r--r-- | go/src/printer/printer.go | 4 | ||||
| -rw-r--r-- | go/src/reader/reader.go | 2 | ||||
| -rw-r--r-- | go/src/step3_env/step3_env.go | 14 | ||||
| -rw-r--r-- | go/src/step4_if_fn_do/step4_if_fn_do.go | 8 | ||||
| -rw-r--r-- | go/src/step5_tco/step5_tco.go | 8 | ||||
| -rw-r--r-- | go/src/step6_file/step6_file.go | 14 | ||||
| -rw-r--r-- | go/src/step7_quote/step7_quote.go | 14 | ||||
| -rw-r--r-- | go/src/step8_macros/step8_macros.go | 22 | ||||
| -rw-r--r-- | go/src/step9_try/step9_try.go | 24 | ||||
| -rw-r--r-- | go/src/stepA_interop/stepA_interop.go | 22 | ||||
| -rw-r--r-- | go/src/types/types.go | 22 |
13 files changed, 103 insertions, 77 deletions
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) }, diff --git a/go/src/env/env.go b/go/src/env/env.go index 4d20857..584c9a7 100644 --- a/go/src/env/env.go +++ b/go/src/env/env.go @@ -35,8 +35,8 @@ func NewEnv(outer EnvType, binds_mt MalType, exprs_mt MalType) (EnvType, error) return env, nil } -func (e Env) Find(key string) EnvType { - if _, ok := e.data[key]; ok { +func (e Env) Find(key Symbol) EnvType { + if _, ok := e.data[key.Val]; ok { return e } else if (e.outer != nil) { return e.outer.Find(key) @@ -45,15 +45,15 @@ func (e Env) Find(key string) EnvType { } } -func (e Env) Set(key string, value MalType) MalType { - e.data[key] = value +func (e Env) Set(key Symbol, value MalType) MalType { + e.data[key.Val] = value return value } -func (e Env) Get(key string) (MalType, error) { +func (e Env) Get(key Symbol) (MalType, error) { env := e.Find(key) if env == nil { - return nil, errors.New("'" + key + "' not found") + return nil, errors.New("'" + key.Val + "' not found") } - return env.(Env).data[key], nil + return env.(Env).data[key.Val], nil } diff --git a/go/src/printer/printer.go b/go/src/printer/printer.go index 428958e..1b8e9fe 100644 --- a/go/src/printer/printer.go +++ b/go/src/printer/printer.go @@ -32,7 +32,9 @@ func Pr_str(obj types.MalType, print_readably bool) string { } return "{" + strings.Join(str_list, " ") + "}" case string: - if print_readably { + if strings.HasPrefix(tobj, "\u029e") { + return ":" + tobj[2:len(tobj)] + } else if print_readably { return `"` + strings.Replace( strings.Replace( strings.Replace(tobj,`\`,`\\`, -1), diff --git a/go/src/reader/reader.go b/go/src/reader/reader.go index 6fbe311..9cacb8b 100644 --- a/go/src/reader/reader.go +++ b/go/src/reader/reader.go @@ -64,6 +64,8 @@ func read_atom(rdr Reader) (MalType, error) { return strings.Replace( strings.Replace(str, `\"`, `"`, -1), `\n`, "\n", -1), nil + } else if (*token)[0] == ':' { + return NewKeyword((*token)[1:len(*token)]) } else if *token == "nil" { return nil, nil } else if *token == "true" { diff --git a/go/src/step3_env/step3_env.go b/go/src/step3_env/step3_env.go index 0d975ba..0c45bf2 100644 --- a/go/src/step3_env/step3_env.go +++ b/go/src/step3_env/step3_env.go @@ -23,7 +23,7 @@ func READ(str string) (MalType, error) { func eval_ast(ast MalType, env EnvType) (MalType, error) { //fmt.Printf("eval_ast: %#v\n", ast) if Symbol_Q(ast) { - return env.Get(ast.(Symbol).Val) + return env.Get(ast.(Symbol)) } else if List_Q(ast) { lst := []MalType{} for _, a := range ast.(List).Val { @@ -83,7 +83,7 @@ func EVAL(ast MalType, env EnvType) (MalType, error) { case "def!": res, e := EVAL(a2, env) if e != nil { return nil, e } - return env.Set(a1.(Symbol).Val, res), nil + return env.Set(a1.(Symbol), res), nil case "let*": let_env, e := NewEnv(env, nil, nil) if e != nil { return nil, e } @@ -95,7 +95,7 @@ func EVAL(ast MalType, env EnvType) (MalType, error) { } exp, e := EVAL(arr1[i+1], let_env) if e != nil { return nil, e } - let_env.Set(arr1[i].(Symbol).Val, exp) + let_env.Set(arr1[i].(Symbol), exp) } return EVAL(a2, let_env) default: @@ -127,13 +127,13 @@ func rep(str string) (MalType, error) { } func main() { - repl_env.Set("+", func(a []MalType) (MalType, error) { + repl_env.Set(Symbol{"+"}, func(a []MalType) (MalType, error) { return a[0].(int) + a[1].(int), nil }) - repl_env.Set("-", func(a []MalType) (MalType, error) { + repl_env.Set(Symbol{"-"}, func(a []MalType) (MalType, error) { return a[0].(int) - a[1].(int), nil }) - repl_env.Set("*", func(a []MalType) (MalType, error) { + repl_env.Set(Symbol{"*"}, func(a []MalType) (MalType, error) { return a[0].(int) * a[1].(int), nil }) - repl_env.Set("/", func(a []MalType) (MalType, error) { + repl_env.Set(Symbol{"/"}, func(a []MalType) (MalType, error) { return a[0].(int) / a[1].(int), nil }) // repl loop diff --git a/go/src/step4_if_fn_do/step4_if_fn_do.go b/go/src/step4_if_fn_do/step4_if_fn_do.go index f63017b..d90a720 100644 --- a/go/src/step4_if_fn_do/step4_if_fn_do.go +++ b/go/src/step4_if_fn_do/step4_if_fn_do.go @@ -24,7 +24,7 @@ func READ(str string) (MalType, error) { func eval_ast(ast MalType, env EnvType) (MalType, error) { //fmt.Printf("eval_ast: %#v\n", ast) if Symbol_Q(ast) { - return env.Get(ast.(Symbol).Val) + return env.Get(ast.(Symbol)) } else if List_Q(ast) { lst := []MalType{} for _, a := range ast.(List).Val { @@ -84,7 +84,7 @@ func EVAL(ast MalType, env EnvType) (MalType, error) { case "def!": res, e := EVAL(a2, env) if e != nil { return nil, e } - return env.Set(a1.(Symbol).Val, res), nil + return env.Set(a1.(Symbol), res), nil case "let*": let_env, e := NewEnv(env, nil, nil) if e != nil { return nil, e } @@ -96,7 +96,7 @@ func EVAL(ast MalType, env EnvType) (MalType, error) { } exp, e := EVAL(arr1[i+1], let_env) if e != nil { return nil, e } - let_env.Set(arr1[i].(Symbol).Val, exp) + let_env.Set(arr1[i].(Symbol), exp) } return EVAL(a2, let_env) case "do": @@ -154,7 +154,7 @@ func rep(str string) (MalType, error) { func main() { // core.go: defined using go for k, v := range core.NS { - repl_env.Set(k, v) + repl_env.Set(Symbol{k}, v) } // core.mal: defined using the language itself diff --git a/go/src/step5_tco/step5_tco.go b/go/src/step5_tco/step5_tco.go index 9e176bb..8c6ff37 100644 --- a/go/src/step5_tco/step5_tco.go +++ b/go/src/step5_tco/step5_tco.go @@ -24,7 +24,7 @@ func READ(str string) (MalType, error) { func eval_ast(ast MalType, env EnvType) (MalType, error) { //fmt.Printf("eval_ast: %#v\n", ast) if Symbol_Q(ast) { - return env.Get(ast.(Symbol).Val) + return env.Get(ast.(Symbol)) } else if List_Q(ast) { lst := []MalType{} for _, a := range ast.(List).Val { @@ -86,7 +86,7 @@ func EVAL(ast MalType, env EnvType) (MalType, error) { case "def!": res, e := EVAL(a2, env) if e != nil { return nil, e } - return env.Set(a1.(Symbol).Val, res), nil + return env.Set(a1.(Symbol), res), nil case "let*": let_env, e := NewEnv(env, nil, nil) if e != nil { return nil, e } @@ -98,7 +98,7 @@ func EVAL(ast MalType, env EnvType) (MalType, error) { } exp, e := EVAL(arr1[i+1], let_env) if e != nil { return nil, e } - let_env.Set(arr1[i].(Symbol).Val, exp) + let_env.Set(arr1[i].(Symbol), exp) } ast = a2 env = let_env @@ -164,7 +164,7 @@ func rep(str string) (MalType, error) { func main() { // core.go: defined using go for k, v := range core.NS { - repl_env.Set(k, Func{v.(func([]MalType)(MalType,error)),nil}) + repl_env.Set(Symbol{k}, Func{v.(func([]MalType)(MalType,error)),nil}) } // core.mal: defined using the language itself diff --git a/go/src/step6_file/step6_file.go b/go/src/step6_file/step6_file.go index 748d158..701ac47 100644 --- a/go/src/step6_file/step6_file.go +++ b/go/src/step6_file/step6_file.go @@ -25,7 +25,7 @@ func READ(str string) (MalType, error) { func eval_ast(ast MalType, env EnvType) (MalType, error) { //fmt.Printf("eval_ast: %#v\n", ast) if Symbol_Q(ast) { - return env.Get(ast.(Symbol).Val) + return env.Get(ast.(Symbol)) } else if List_Q(ast) { lst := []MalType{} for _, a := range ast.(List).Val { @@ -87,7 +87,7 @@ func EVAL(ast MalType, env EnvType) (MalType, error) { case "def!": res, e := EVAL(a2, env) if e != nil { return nil, e } - return env.Set(a1.(Symbol).Val, res), nil + return env.Set(a1.(Symbol), res), nil case "let*": let_env, e := NewEnv(env, nil, nil) if e != nil { return nil, e } @@ -99,7 +99,7 @@ func EVAL(ast MalType, env EnvType) (MalType, error) { } exp, e := EVAL(arr1[i+1], let_env) if e != nil { return nil, e } - let_env.Set(arr1[i].(Symbol).Val, exp) + let_env.Set(arr1[i].(Symbol), exp) } ast = a2 env = let_env @@ -165,11 +165,11 @@ func rep(str string) (MalType, error) { func main() { // core.go: defined using go for k, v := range core.NS { - repl_env.Set(k, Func{v.(func([]MalType)(MalType,error)),nil}) + repl_env.Set(Symbol{k}, Func{v.(func([]MalType)(MalType,error)),nil}) } - repl_env.Set("eval", Func{func(a []MalType) (MalType, error) { + repl_env.Set(Symbol{"eval"}, Func{func(a []MalType) (MalType, error) { return EVAL(a[0], repl_env) },nil}) - repl_env.Set("*ARGV*", List{}) + repl_env.Set(Symbol{"*ARGV*"}, List{}) // core.mal: defined using the language itself rep("(def! not (fn* (a) (if a false true)))") @@ -181,7 +181,7 @@ func main() { for _,a := range os.Args[2:] { args = append(args, a) } - repl_env.Set("*ARGV*", List{args,nil}) + repl_env.Set(Symbol{"*ARGV*"}, List{args,nil}) if _,e := rep("(load-file \"" + os.Args[1] + "\")"); e != nil { fmt.Printf("Error: %v\n", e) os.Exit(1) diff --git a/go/src/step7_quote/step7_quote.go b/go/src/step7_quote/step7_quote.go index 999129e..d93f620 100644 --- a/go/src/step7_quote/step7_quote.go +++ b/go/src/step7_quote/step7_quote.go @@ -54,7 +54,7 @@ func quasiquote(ast MalType) MalType { func eval_ast(ast MalType, env EnvType) (MalType, error) { //fmt.Printf("eval_ast: %#v\n", ast) if Symbol_Q(ast) { - return env.Get(ast.(Symbol).Val) + return env.Get(ast.(Symbol)) } else if List_Q(ast) { lst := []MalType{} for _, a := range ast.(List).Val { @@ -116,7 +116,7 @@ func EVAL(ast MalType, env EnvType) (MalType, error) { case "def!": res, e := EVAL(a2, env) if e != nil { return nil, e } - return env.Set(a1.(Symbol).Val, res), nil + return env.Set(a1.(Symbol), res), nil case "let*": let_env, e := NewEnv(env, nil, nil) if e != nil { return nil, e } @@ -128,7 +128,7 @@ func EVAL(ast MalType, env EnvType) (MalType, error) { } exp, e := EVAL(arr1[i+1], let_env) if e != nil { return nil, e } - let_env.Set(arr1[i].(Symbol).Val, exp) + let_env.Set(arr1[i].(Symbol), exp) } ast = a2 env = let_env @@ -198,11 +198,11 @@ func rep(str string) (MalType, error) { func main() { // core.go: defined using go for k, v := range core.NS { - repl_env.Set(k, Func{v.(func([]MalType)(MalType,error)),nil}) + repl_env.Set(Symbol{k}, Func{v.(func([]MalType)(MalType,error)),nil}) } - repl_env.Set("eval", Func{func(a []MalType) (MalType, error) { + repl_env.Set(Symbol{"eval"}, Func{func(a []MalType) (MalType, error) { return EVAL(a[0], repl_env) },nil}) - repl_env.Set("*ARGV*", List{}) + repl_env.Set(Symbol{"*ARGV*"}, List{}) // core.mal: defined using the language itself rep("(def! not (fn* (a) (if a false true)))") @@ -214,7 +214,7 @@ func main() { for _,a := range os.Args[2:] { args = append(args, a) } - repl_env.Set("*ARGV*", List{args,nil}) + repl_env.Set(Symbol{"*ARGV*"}, List{args,nil}) if _,e := rep("(load-file \"" + os.Args[1] + "\")"); e != nil { fmt.Printf("Error: %v\n", e) os.Exit(1) diff --git a/go/src/step8_macros/step8_macros.go b/go/src/step8_macros/step8_macros.go index 3264159..86db33b 100644 --- a/go/src/step8_macros/step8_macros.go +++ b/go/src/step8_macros/step8_macros.go @@ -55,8 +55,8 @@ func is_macro_call(ast MalType, env EnvType) bool { if List_Q(ast) { slc, _ := GetSlice(ast) a0 := slc[0] - if Symbol_Q(a0) && env.Find(a0.(Symbol).Val) != nil { - mac, e := env.Get(a0.(Symbol).Val) + if Symbol_Q(a0) && env.Find(a0.(Symbol)) != nil { + mac, e := env.Get(a0.(Symbol)) if e != nil { return false } if MalFunc_Q(mac) { return mac.(MalFunc).GetMacro() @@ -72,7 +72,7 @@ func macroexpand(ast MalType, env EnvType) (MalType, error) { for ; is_macro_call(ast, env) ; { slc, _ := GetSlice(ast) a0 := slc[0] - mac, e = env.Get(a0.(Symbol).Val); if e != nil { return nil, e } + mac, e = env.Get(a0.(Symbol)); if e != nil { return nil, e } fn := mac.(MalFunc) ast, e = Apply(fn, slc[1:]); if e != nil { return nil, e } } @@ -82,7 +82,7 @@ func macroexpand(ast MalType, env EnvType) (MalType, error) { func eval_ast(ast MalType, env EnvType) (MalType, error) { //fmt.Printf("eval_ast: %#v\n", ast) if Symbol_Q(ast) { - return env.Get(ast.(Symbol).Val) + return env.Get(ast.(Symbol)) } else if List_Q(ast) { lst := []MalType{} for _, a := range ast.(List).Val { @@ -148,7 +148,7 @@ func EVAL(ast MalType, env EnvType) (MalType, error) { case "def!": res, e := EVAL(a2, env) if e != nil { return nil, e } - return env.Set(a1.(Symbol).Val, res), nil + return env.Set(a1.(Symbol), res), nil case "let*": let_env, e := NewEnv(env, nil, nil) if e != nil { return nil, e } @@ -160,7 +160,7 @@ func EVAL(ast MalType, env EnvType) (MalType, error) { } exp, e := EVAL(arr1[i+1], let_env) if e != nil { return nil, e } - let_env.Set(arr1[i].(Symbol).Val, exp) + let_env.Set(arr1[i].(Symbol), exp) } ast = a2 env = let_env @@ -172,7 +172,7 @@ func EVAL(ast MalType, env EnvType) (MalType, error) { fn, e := EVAL(a2, env) fn = fn.(MalFunc).SetMacro() if e != nil { return nil, e } - return env.Set(a1.(Symbol).Val, fn), nil + return env.Set(a1.(Symbol), fn), nil case "macroexpand": return macroexpand(a1, env) case "do": @@ -237,11 +237,11 @@ func rep(str string) (MalType, error) { func main() { // core.go: defined using go for k, v := range core.NS { - repl_env.Set(k, Func{v.(func([]MalType)(MalType,error)),nil}) + repl_env.Set(Symbol{k}, Func{v.(func([]MalType)(MalType,error)),nil}) } - repl_env.Set("eval", Func{func(a []MalType) (MalType, error) { + repl_env.Set(Symbol{"eval"}, Func{func(a []MalType) (MalType, error) { return EVAL(a[0], repl_env) },nil}) - repl_env.Set("*ARGV*", List{}) + repl_env.Set(Symbol{"*ARGV*"}, List{}) // core.mal: defined using the language itself rep("(def! not (fn* (a) (if a false true)))") @@ -255,7 +255,7 @@ func main() { for _,a := range os.Args[2:] { args = append(args, a) } - repl_env.Set("*ARGV*", List{args,nil}) + repl_env.Set(Symbol{"*ARGV*"}, List{args,nil}) if _,e := rep("(load-file \"" + os.Args[1] + "\")"); e != nil { fmt.Printf("Error: %v\n", e) os.Exit(1) diff --git a/go/src/step9_try/step9_try.go b/go/src/step9_try/step9_try.go index 322ee36..18f3c9c 100644 --- a/go/src/step9_try/step9_try.go +++ b/go/src/step9_try/step9_try.go @@ -55,8 +55,8 @@ func is_macro_call(ast MalType, env EnvType) bool { if List_Q(ast) { slc, _ := GetSlice(ast) a0 := slc[0] - if Symbol_Q(a0) && env.Find(a0.(Symbol).Val) != nil { - mac, e := env.Get(a0.(Symbol).Val) + if Symbol_Q(a0) && env.Find(a0.(Symbol)) != nil { + mac, e := env.Get(a0.(Symbol)) if e != nil { return false } if MalFunc_Q(mac) { return mac.(MalFunc).GetMacro() @@ -72,7 +72,7 @@ func macroexpand(ast MalType, env EnvType) (MalType, error) { for ; is_macro_call(ast, env) ; { slc, _ := GetSlice(ast) a0 := slc[0] - mac, e = env.Get(a0.(Symbol).Val); if e != nil { return nil, e } + mac, e = env.Get(a0.(Symbol)); if e != nil { return nil, e } fn := mac.(MalFunc) ast, e = Apply(fn, slc[1:]); if e != nil { return nil, e } } @@ -82,7 +82,7 @@ func macroexpand(ast MalType, env EnvType) (MalType, error) { func eval_ast(ast MalType, env EnvType) (MalType, error) { //fmt.Printf("eval_ast: %#v\n", ast) if Symbol_Q(ast) { - return env.Get(ast.(Symbol).Val) + return env.Get(ast.(Symbol)) } else if List_Q(ast) { lst := []MalType{} for _, a := range ast.(List).Val { @@ -148,7 +148,7 @@ func EVAL(ast MalType, env EnvType) (MalType, error) { case "def!": res, e := EVAL(a2, env) if e != nil { return nil, e } - return env.Set(a1.(Symbol).Val, res), nil + return env.Set(a1.(Symbol), res), nil case "let*": let_env, e := NewEnv(env, nil, nil) if e != nil { return nil, e } @@ -160,7 +160,7 @@ func EVAL(ast MalType, env EnvType) (MalType, error) { } exp, e := EVAL(arr1[i+1], let_env) if e != nil { return nil, e } - let_env.Set(arr1[i].(Symbol).Val, exp) + let_env.Set(arr1[i].(Symbol), exp) } ast = a2 env = let_env @@ -172,7 +172,7 @@ func EVAL(ast MalType, env EnvType) (MalType, error) { fn, e := EVAL(a2, env) fn = fn.(MalFunc).SetMacro() if e != nil { return nil, e } - return env.Set(a1.(Symbol).Val, fn), nil + return env.Set(a1.(Symbol), fn), nil case "macroexpand": return macroexpand(a1, env) case "try*": @@ -259,14 +259,13 @@ func rep(str string) (MalType, error) { func main() { // core.go: defined using go for k, v := range core.NS { - repl_env.Set(k, Func{v.(func([]MalType)(MalType,error)),nil}) + repl_env.Set(Symbol{k}, Func{v.(func([]MalType)(MalType,error)),nil}) } - repl_env.Set("eval", Func{func(a []MalType) (MalType, error) { + repl_env.Set(Symbol{"eval"}, Func{func(a []MalType) (MalType, error) { return EVAL(a[0], repl_env) },nil}) - repl_env.Set("*ARGV*", List{}) + repl_env.Set(Symbol{"*ARGV*"}, List{}) // core.mal: defined using the language itself - rep("(def! *host-language* \"go\")") rep("(def! not (fn* (a) (if a false true)))") rep("(def! load-file (fn* (f) (eval (read-string (str \"(do \" (slurp f) \")\")))))") rep("(defmacro! cond (fn* (& xs) (if (> (count xs) 0) (list 'if (first xs) (if (> (count xs) 1) (nth xs 1) (throw \"odd number of forms to cond\")) (cons 'cond (rest (rest xs)))))))") @@ -278,7 +277,7 @@ func main() { for _,a := range os.Args[2:] { args = append(args, a) } - repl_env.Set("*ARGV*", List{args,nil}) + repl_env.Set(Symbol{"*ARGV*"}, List{args,nil}) if _,e := rep("(load-file \"" + os.Args[1] + "\")"); e != nil { fmt.Printf("Error: %v\n", e) os.Exit(1) @@ -287,7 +286,6 @@ func main() { } // repl loop - rep("(println (str \"Mal [\" *host-language* \"]\"))") for { text, err := readline.Readline("user> ") text = strings.TrimRight(text, "\n"); diff --git a/go/src/stepA_interop/stepA_interop.go b/go/src/stepA_interop/stepA_interop.go index 322ee36..808022a 100644 --- a/go/src/stepA_interop/stepA_interop.go +++ b/go/src/stepA_interop/stepA_interop.go @@ -55,8 +55,8 @@ func is_macro_call(ast MalType, env EnvType) bool { if List_Q(ast) { slc, _ := GetSlice(ast) a0 := slc[0] - if Symbol_Q(a0) && env.Find(a0.(Symbol).Val) != nil { - mac, e := env.Get(a0.(Symbol).Val) + if Symbol_Q(a0) && env.Find(a0.(Symbol)) != nil { + mac, e := env.Get(a0.(Symbol)) if e != nil { return false } if MalFunc_Q(mac) { return mac.(MalFunc).GetMacro() @@ -72,7 +72,7 @@ func macroexpand(ast MalType, env EnvType) (MalType, error) { for ; is_macro_call(ast, env) ; { slc, _ := GetSlice(ast) a0 := slc[0] - mac, e = env.Get(a0.(Symbol).Val); if e != nil { return nil, e } + mac, e = env.Get(a0.(Symbol)); if e != nil { return nil, e } fn := mac.(MalFunc) ast, e = Apply(fn, slc[1:]); if e != nil { return nil, e } } @@ -82,7 +82,7 @@ func macroexpand(ast MalType, env EnvType) (MalType, error) { func eval_ast(ast MalType, env EnvType) (MalType, error) { //fmt.Printf("eval_ast: %#v\n", ast) if Symbol_Q(ast) { - return env.Get(ast.(Symbol).Val) + return env.Get(ast.(Symbol)) } else if List_Q(ast) { lst := []MalType{} for _, a := range ast.(List).Val { @@ -148,7 +148,7 @@ func EVAL(ast MalType, env EnvType) (MalType, error) { case "def!": res, e := EVAL(a2, env) if e != nil { return nil, e } - return env.Set(a1.(Symbol).Val, res), nil + return env.Set(a1.(Symbol), res), nil case "let*": let_env, e := NewEnv(env, nil, nil) if e != nil { return nil, e } @@ -160,7 +160,7 @@ func EVAL(ast MalType, env EnvType) (MalType, error) { } exp, e := EVAL(arr1[i+1], let_env) if e != nil { return nil, e } - let_env.Set(arr1[i].(Symbol).Val, exp) + let_env.Set(arr1[i].(Symbol), exp) } ast = a2 env = let_env @@ -172,7 +172,7 @@ func EVAL(ast MalType, env EnvType) (MalType, error) { fn, e := EVAL(a2, env) fn = fn.(MalFunc).SetMacro() if e != nil { return nil, e } - return env.Set(a1.(Symbol).Val, fn), nil + return env.Set(a1.(Symbol), fn), nil case "macroexpand": return macroexpand(a1, env) case "try*": @@ -259,11 +259,11 @@ func rep(str string) (MalType, error) { func main() { // core.go: defined using go for k, v := range core.NS { - repl_env.Set(k, Func{v.(func([]MalType)(MalType,error)),nil}) + repl_env.Set(Symbol{k}, Func{v.(func([]MalType)(MalType,error)),nil}) } - repl_env.Set("eval", Func{func(a []MalType) (MalType, error) { + repl_env.Set(Symbol{"eval"}, Func{func(a []MalType) (MalType, error) { return EVAL(a[0], repl_env) },nil}) - repl_env.Set("*ARGV*", List{}) + repl_env.Set(Symbol{"*ARGV*"}, List{}) // core.mal: defined using the language itself rep("(def! *host-language* \"go\")") @@ -278,7 +278,7 @@ func main() { for _,a := range os.Args[2:] { args = append(args, a) } - repl_env.Set("*ARGV*", List{args,nil}) + repl_env.Set(Symbol{"*ARGV*"}, List{args,nil}) if _,e := rep("(load-file \"" + os.Args[1] + "\")"); e != nil { fmt.Printf("Error: %v\n", e) os.Exit(1) diff --git a/go/src/types/types.go b/go/src/types/types.go index 613bfb5..54e4176 100644 --- a/go/src/types/types.go +++ b/go/src/types/types.go @@ -4,6 +4,7 @@ import ( "reflect" "errors" "fmt" + "strings" ) // Errors/Exceptions @@ -21,10 +22,9 @@ type MalType interface { } type EnvType interface { - //Find(key string) *EnvType - Find(key string) EnvType - Set(key string, value MalType) MalType - Get(key string) (MalType, error) + Find(key Symbol) EnvType + Set(key Symbol, value MalType) MalType + Get(key Symbol) (MalType, error) } // Scalars @@ -57,6 +57,20 @@ func Symbol_Q(obj MalType) bool { } +// Keywords +func NewKeyword(s string) (MalType, error) { + return "\u029e" + s, nil; +} + +func Keyword_Q(obj MalType) bool { + if obj == nil { return false } + switch s := obj.(type) { + case string: return strings.HasPrefix(s, "\u029e") + default: return false + } +} + + // Strings func String_Q(obj MalType) bool { if obj == nil { return false } |
