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

remove global variable and add Crisp::Interpreter class

master
rhysd 9 роки тому
джерело
коміт
5f2a55a60c
3 змінених файлів з 59 додано та 33 видалено
  1. +1
    -1
      README.md
  2. +51
    -32
      src/crisp.cr
  3. +7
    -0
      src/main.cr

+ 1
- 1
README.md Переглянути файл

@ -24,7 +24,7 @@ This project is a toy box for my dynamic language ideas.
## Installation
1. Install `crystal` command
2. `$ crystal run /path/to/Crisp/src/crisp.cr`
2. `$ crystal run /path/to/Crisp/src/main.cr`
## Development Environment

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

@ -1,5 +1,3 @@
#! /usr/bin/env crystal run
require "colorize"
require "readline"
@ -244,41 +242,62 @@ module Crisp
def rep(str)
print(eval(read(str), $repl_env))
end
end
$repl_env = Crisp::Env.new nil
Crisp::NS.each{|k,v| $repl_env.set(k, Crisp::Type.new(v))}
$repl_env.set("eval", Crisp::Type.new -> (args: Array(Crisp::Type)){ Crisp.eval(args[0], $repl_env) })
Crisp.rep "(def! not (fn* (a) (if a false true)))"
Crisp.rep "(def! load-file (fn* (f) (eval (read-string (str \"(do \" (slurp f) \")\")))))"
Crisp.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)))))))"
Crisp.rep "(defmacro! or (fn* (& xs) (if (empty? xs) nil (if (= 1 (count xs)) (first xs) `(let* (or_FIXME ~(first xs)) (if or_FIXME or_FIXME (or ~@(rest xs))))))))"
Crisp.rep("(def! *host-language* \"crystal\")")
$argv = Crisp::List.new
$repl_env.set("*ARGV*", Crisp::Type.new $argv)
unless ARGV.empty?
if ARGV.size > 1
ARGV[1..-1].each do |a|
$argv << Crisp::Type.new(a)
class ProgramState
def rep(str)
print(eval(read(str), @env))
end
end
begin
Crisp.rep "(load-file \"#{ARGV[0]}\")"
rescue e
STDERR.puts e
exit 1
def initialize(args)
@env = Crisp::Env.new nil
Crisp::NameSpace.each{|k,v| @curent_env.set(k, Crisp::Type.new(v))}
@env.set("eval", Crisp::Type.new -> (args: Array(Crisp::Type)){ Crisp.eval(args[0], @env) })
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)))))))"
rep "(defmacro! or (fn* (& xs) (if (empty? xs) nil (if (= 1 (count xs)) (first xs) `(let* (or_FIXME ~(first xs)) (if or_FIXME or_FIXME (or ~@(rest xs))))))))"
rep "(def! *host-language* \"crystal\")"
argv = Crisp::List.new
if args
args.each do |a|
argv << Crisp::Type.new a
end
end
@env.set("*ARGV*", Crisp::Type.new argv)
end
end
exit
end
class Interpreter
def initialize(args)
@state = ProgramState.new args
end
while line = Readline.readline("Crisp> ", true)
begin
puts Crisp.rep(line)
rescue e
STDERR.puts e
def run(filename = nil)
if filename
begin
Crisp.rep "(load-file \"#{filename}\")"
rescue e
STDERR.puts e
exit 1
end
exit
end
while line = Readline.readline("Crisp> ", true)
begin
puts @state.rep(line)
rescue e
STDERR.puts e
end
end
end
end
end

+ 7
- 0
src/main.cr Переглянути файл

@ -0,0 +1,7 @@
require "./crisp"
if ARGV.empty?
Crisp::Interpreter.new.run
else
Crisp::Interpreter.new(ARGV[1..-1]).run(ARGV.first)
end

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