Переглянути джерело

Crisp::Type -> Crisp::Expr

master
rhysd 9 роки тому
джерело
коміт
0c01804b7b
8 змінених файлів з 55 додано та 55 видалено
  1. +2
    -2
      spec/crisp/interpreter_spec.cr
  2. +8
    -8
      src/crisp/core.cr
  3. +4
    -4
      src/crisp/env.cr
  4. +12
    -12
      src/crisp/evaluator.cr
  5. +6
    -6
      src/crisp/interpreter.cr
  6. +3
    -3
      src/crisp/printer.cr
  7. +6
    -6
      src/crisp/reader.cr
  8. +14
    -14
      src/crisp/types.cr

+ 2
- 2
spec/crisp/interpreter_spec.cr Переглянути файл

@ -5,7 +5,7 @@ describe "Crisp::Interpreter" do
it "takes arguments as string value" do
i = Crisp::Interpreter.new %w(foo bar baz)
result = i.eval_string("*ARGV*")
result.should be_a(Crisp::Type)
result.should be_a(Crisp::Expr)
unwrapped = result.unwrap
unwrapped.should be_a(Crisp::List)
if unwrapped.is_a? Crisp::List
@ -27,7 +27,7 @@ describe "Crisp::Interpreter" do
it "evaluates string of Crisp expression" do
i = Crisp::Interpreter.new
result = i.eval_string "(+ 1 2)"
result.should be_a(Crisp::Type)
result.should be_a(Crisp::Expr)
unwrapped = result.unwrap
unwrapped.should be_a(Int32)
unwrapped.should eq(3)

+ 8
- 8
src/crisp/core.cr Переглянути файл

@ -10,10 +10,10 @@ module Crisp
extend self
macro calc_op(op)
-> (args : Array(Crisp::Type)) {
-> (args : Array(Crisp::Expr)) {
x, y = args[0].unwrap, args[1].unwrap
Crisp.eval_error "invalid arguments for binary operator {{op.id}}" unless x.is_a?(Int32) && y.is_a?(Int32)
Crisp::Type.new(x {{op.id}} y)
Crisp::Expr.new(x {{op.id}} y)
}
end
@ -77,7 +77,7 @@ module Crisp
end
def cons(args)
head, tail = args[0] as Crisp::Type, args[1].unwrap
head, tail = args[0] as Crisp::Expr, args[1].unwrap
Crisp.eval_error "2nd arg of cons must be list" unless tail.is_a? Array
([head] + tail).to_crisp_value
end
@ -245,7 +245,7 @@ module Crisp
return nil unless a0.is_a? Crisp::HashMap
Crisp.eval_error "2nd argument of get must be string" unless a1.is_a? String
# a0[a1]? isn't available because type ofa0[a1] is infered NoReturn
# a0[a1]? isn't available because type of a0[a1] is inferred NoReturn
a0.has_key?(a1) ? a0[a1] : nil
end
@ -259,7 +259,7 @@ module Crisp
def keys(args)
head = args.first.unwrap
Crisp.eval_error "1st argument of assoc must be hashmap" unless head.is_a? Crisp::HashMap
head.keys.each_with_object(Crisp::List.new){|e,l| l << Crisp::Type.new(e)}
head.keys.each_with_object(Crisp::List.new){|e,l| l << Crisp::Expr.new(e)}
end
def vals(args)
@ -345,11 +345,11 @@ module Crisp
# Note:
# Simply using ->self.some_func doesn't work
macro func(name)
-> (args : Array(Crisp::Type)) { Crisp::Type.new self.{{name.id}}(args) }
-> (args : Array(Crisp::Expr)) { Crisp::Expr.new self.{{name.id}}(args) }
end
macro rel_op(op)
-> (args : Array(Crisp::Type)) { Crisp::Type.new (args[0] {{op.id}} args[1]) }
-> (args : Array(Crisp::Expr)) { Crisp::Expr.new (args[0] {{op.id}} args[1]) }
end
NameSpace = {
@ -377,7 +377,7 @@ module Crisp
"nth" => func(:nth)
"first" => func(:first)
"rest" => func(:rest)
"throw" => -> (args : Array(Crisp::Type)) { raise Crisp::RuntimeException.new args[0] }
"throw" => -> (args : Array(Crisp::Expr)) { raise Crisp::RuntimeException.new args[0] }
"apply" => func(:apply)
"map" => func(:map)
"nil?" => func(:nil?)

+ 4
- 4
src/crisp/env.cr Переглянути файл

@ -7,11 +7,11 @@ module Crisp
property data
def initialize(@outer = nil)
@data = {} of String => Crisp::Type
@data = {} of String => Crisp::Expr
end
def initialize(@outer, binds, exprs : Array(Crisp::Type))
@data = {} of String => Crisp::Type
def initialize(@outer, binds, exprs : Array(Crisp::Expr))
@data = {} of String => Crisp::Expr
Crisp.eval_error "binds must be list or vector" unless binds.is_a? Array
@ -27,7 +27,7 @@ module Crisp
Crisp.eval_error "bind name must be symbol" unless next_param.is_a? Crisp::Symbol
var_args = Crisp::List.new
exprs[idx..-1].each{|e| var_args << e} if idx < exprs.size
@data[next_param.str] = Crisp::Type.new var_args
@data[next_param.str] = Crisp::Expr.new var_args
break
end

+ 12
- 12
src/crisp/evaluator.cr Переглянути файл

@ -12,18 +12,18 @@ module Crisp
class Evaluator
def func_of(env, binds, body)
-> (args : Array(Crisp::Type)) {
-> (args : Array(Crisp::Expr)) {
new_env = Crisp::Env.new(env, binds, args)
eval(body, new_env)
} as Crisp::Func
end
def eval_ast(ast, env)
return ast.map{|n| eval(n, env) as Crisp::Type} if ast.is_a? Array
return ast.map{|n| eval(n, env) as Crisp::Expr} if ast.is_a? Array
val = ast.unwrap
Crisp::Type.new case val
Crisp::Expr.new case val
when Crisp::Symbol
if e = env.get(val.str)
e
@ -51,7 +51,7 @@ module Crisp
list = ast.unwrap
unless pair?(list)
return Crisp::Type.new(
return Crisp::Expr.new(
Crisp::List.new << gen_type(Crisp::Symbol, "quote") << ast
)
end
@ -64,13 +64,13 @@ module Crisp
list[1]
# (("splice-unquote" ...) ...)
when pair?(head) && (arg0 = head.first.unwrap).is_a?(Crisp::Symbol) && arg0.str == "splice-unquote"
tail = Crisp::Type.new list[1..-1].to_crisp_value
Crisp::Type.new(
tail = Crisp::Expr.new list[1..-1].to_crisp_value
Crisp::Expr.new(
Crisp::List.new << gen_type(Crisp::Symbol, "concat") << head[1] << quasiquote(tail)
)
else
tail = Crisp::Type.new list[1..-1].to_crisp_value
Crisp::Type.new(
tail = Crisp::Expr.new list[1..-1].to_crisp_value
Crisp::Expr.new(
Crisp::List.new << gen_type(Crisp::Symbol, "cons") << quasiquote(list.first) << quasiquote(tail)
)
end
@ -148,7 +148,7 @@ module Crisp
return invoke_list(list, env) unless head.is_a? Crisp::Symbol
return Crisp::Type.new case head.str
return Crisp::Expr.new case head.str
when "def!"
Crisp.eval_error "wrong number of argument for 'def!'" unless list.size == 3
a1 = list[1].unwrap
@ -173,7 +173,7 @@ module Crisp
next # TCO
when "do"
if list.empty?
ast = Crisp::Type.new nil
ast = Crisp::Expr.new nil
next
end
@ -182,7 +182,7 @@ module Crisp
next # TCO
when "if"
ast = unless eval(list[1], env).unwrap
list.size >= 4 ? list[3] : Crisp::Type.new(nil)
list.size >= 4 ? list[3] : Crisp::Expr.new(nil)
else
list[2]
end
@ -219,7 +219,7 @@ module Crisp
new_env = Crisp::Env.new(env, [catch_list[1]], [e.thrown])
eval(catch_list[2], new_env)
rescue e
new_env = Crisp::Env.new(env, [catch_list[1]], [Crisp::Type.new e.message])
new_env = Crisp::Env.new(env, [catch_list[1]], [Crisp::Expr.new e.message])
eval(catch_list[2], new_env)
end
else

+ 6
- 6
src/crisp/interpreter.cr Переглянути файл

@ -17,8 +17,8 @@ module Crisp
@evaluator = Evaluator.new
@env = Crisp::Env.new
Crisp::NameSpace.each{|k,v| @env.set(k, Crisp::Type.new(v))}
@env.set("eval", Crisp::Type.new -> (args: Array(Crisp::Type)){ @evaluator.eval(args[0], @env) })
Crisp::NameSpace.each{|k,v| @env.set(k, Crisp::Expr.new(v))}
@env.set("eval", Crisp::Expr.new -> (args: Array(Crisp::Expr)){ @evaluator.eval(args[0], @env) })
eval_string "(def! not (fn* (a) (if a false true)))"
eval_string "(def! load-file (fn* (f) (eval (read-string (str \"(do \" (slurp f) \")\")))))"
@ -30,11 +30,11 @@ module Crisp
if args
args.each do |a|
argv << Crisp::Type.new a
argv << Crisp::Expr.new a
end
end
@env.set("*ARGV*", Crisp::Type.new argv)
@env.set("*ARGV*", Crisp::Expr.new argv)
end
def read(str)
@ -49,12 +49,12 @@ module Crisp
@evaluator.eval(read(str), @env)
end
def eval(t : Crisp::Type)
def eval(t : Crisp::Expr)
@evaluator.eval(t, @env)
end
def eval(val)
@evaluator.eval(Crisp::Type.new val, @env)
@evaluator.eval(Crisp::Expr.new val, @env)
end
def run(filename = nil)

+ 3
- 3
src/crisp/printer.cr Переглянути файл

@ -29,12 +29,12 @@ module Crisp
when Crisp::Atom
"(atom #{print(value.val)})"
else
raise "invalid CrispType: #{value.to_s}"
raise "invalid CrispExpr: #{value.to_s}"
end
end
def print(t : Crisp::Type)
print(t.unwrap) + (t.macro? ? " (macro)" : "")
def print(e : Crisp::Expr)
print(e.unwrap) + (e.macro? ? " (macro)" : "")
end
end
end

+ 6
- 6
src/crisp/reader.cr Переглянути файл

@ -49,15 +49,15 @@ module Crisp
end
def read_list
Crisp::Type.new read_sequence(Crisp::List.new, '(', ')')
Crisp::Expr.new read_sequence(Crisp::List.new, '(', ')')
end
def read_vector
Crisp::Type.new read_sequence(Crisp::Vector.new, '[', ']')
Crisp::Expr.new read_sequence(Crisp::Vector.new, '[', ']')
end
def read_hashmap
types = read_sequence([] of Crisp::Type, '{', '}')
types = read_sequence([] of Crisp::Expr, '{', '}')
Crisp.parse_error "odd number of elements for hash-map: #{types.size}" if types.size.odd?
map = Crisp::HashMap.new
@ -72,14 +72,14 @@ module Crisp
end
end
Crisp::Type.new map
Crisp::Expr.new map
end
def read_atom
token = self.next
Crisp.parse_error "expected Atom but got EOF" unless token
Crisp::Type.new case
Crisp::Expr.new case
when token =~ /^-?\d+$/ then token.to_i
when token == "true" then true
when token == "false" then false
@ -100,7 +100,7 @@ module Crisp
Crisp.parse_error "unexpected EOF" unless token
Crisp.parse_error "unexpected comment" if token[0] == ';'
Crisp::Type.new case token
Crisp::Expr.new case token
when "(" then read_list
when ")" then Crisp.parse_error "unexpected ')'"
when "[" then read_vector

+ 14
- 14
src/crisp/types.cr Переглянути файл

@ -13,13 +13,13 @@ module Crisp
end
end
class List < Array(Type)
class List < Array(Expr)
end
class Vector < Array(Type)
class Vector < Array(Expr)
end
class HashMap < Hash(String, Type)
class HashMap < Hash(String, Expr)
end
class Atom
@ -38,21 +38,21 @@ module Crisp
end
end
class Type
alias Func = (Array(Type) -> Type)
alias ValueType = Nil | Bool | Int32 | String | Symbol | List | Vector | HashMap | Func | Closure | Atom
class Expr
alias Func = (Array(Expr) -> Expr)
alias ValueExpr = Nil | Bool | Int32 | String | Symbol | List | Vector | HashMap | Func | Closure | Atom
is_macro :: Bool
meta :: Type
meta :: Expr
property :is_macro, :meta
def initialize(@val : ValueType)
def initialize(@val : ValueExpr)
@is_macro = false
@meta = nil
end
def initialize(other : Type)
def initialize(other : Expr)
@val = other.unwrap
@is_macro = other.is_macro
@meta = other.meta
@ -71,19 +71,19 @@ module Crisp
end
def dup
Type.new(@val).tap do |t|
Expr.new(@val).tap do |t|
t.is_macro = @is_macro
t.meta = @meta
end
end
def ==(other : Type)
def ==(other : Expr)
@val == other.unwrap
end
macro rel_op(*ops)
{% for op in ops %}
def {{op.id}}(other : Crisp::Type)
def {{op.id}}(other : Crisp::Expr)
l, r = @val, other.unwrap
{% for t in [Int32, String] %}
if l.is_a?({{t}}) && r.is_a?({{t}})
@ -101,11 +101,11 @@ module Crisp
rel_op :<, :>, :<=, :>=
end
alias Func = Type::Func
alias Func = Expr::Func
end
macro gen_type(t, *args)
Crisp::Type.new {{t.id}}.new({{*args}})
Crisp::Expr.new {{t.id}}.new({{*args}})
end
class Array

Завантаження…
Відмінити
Зберегти