aboutsummaryrefslogtreecommitdiff
path: root/go
diff options
context:
space:
mode:
authorJoel Martin <github@martintribe.org>2014-12-18 20:33:49 -0600
committerJoel Martin <github@martintribe.org>2015-01-09 16:16:50 -0600
commitb8ee29b22fbaa7a01f2754b4d6dd9af52e02017c (patch)
treef4d977ed220e9a3f665cfbf4f68770a81e4c2095 /go
parentaaba249304b184e12e2445ab22d66df1f39a51a5 (diff)
downloadmal-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.go12
-rw-r--r--go/src/env/env.go14
-rw-r--r--go/src/printer/printer.go4
-rw-r--r--go/src/reader/reader.go2
-rw-r--r--go/src/step3_env/step3_env.go14
-rw-r--r--go/src/step4_if_fn_do/step4_if_fn_do.go8
-rw-r--r--go/src/step5_tco/step5_tco.go8
-rw-r--r--go/src/step6_file/step6_file.go14
-rw-r--r--go/src/step7_quote/step7_quote.go14
-rw-r--r--go/src/step8_macros/step8_macros.go22
-rw-r--r--go/src/step9_try/step9_try.go24
-rw-r--r--go/src/stepA_interop/stepA_interop.go22
-rw-r--r--go/src/types/types.go22
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 }