crisp 0.0.8 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,8 @@
1
- ## 0.0.9 (2011-xx-xx)
1
+ ## 0.1.0 (2011-04-27)
2
2
 
3
- * ...
3
+ * head/tail functions for array operations
4
+ * more examples
5
+ * alias function
4
6
 
5
7
  ## 0.0.8 (2011-01-06)
6
8
 
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source :rubygems
2
+ gemspec
3
+
4
+ gem 'rake'
5
+ gem 'jeweler'
@@ -0,0 +1,39 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ crisp (0.1.0)
5
+ crisp
6
+ jeweler
7
+ rake
8
+ treetop (~> 1.4.9)
9
+
10
+ GEM
11
+ remote: http://rubygems.org/
12
+ specs:
13
+ diff-lcs (1.1.2)
14
+ git (1.2.5)
15
+ jeweler (1.5.2)
16
+ bundler (~> 1.0.0)
17
+ git (>= 1.2.5)
18
+ rake
19
+ polyglot (0.3.1)
20
+ rake (0.8.7)
21
+ rspec (2.5.0)
22
+ rspec-core (~> 2.5.0)
23
+ rspec-expectations (~> 2.5.0)
24
+ rspec-mocks (~> 2.5.0)
25
+ rspec-core (2.5.1)
26
+ rspec-expectations (2.5.0)
27
+ diff-lcs (~> 1.1.2)
28
+ rspec-mocks (2.5.0)
29
+ treetop (1.4.9)
30
+ polyglot (>= 0.3.1)
31
+
32
+ PLATFORMS
33
+ ruby
34
+
35
+ DEPENDENCIES
36
+ crisp!
37
+ jeweler
38
+ rake
39
+ rspec (~> 2.5.0)
data/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License
2
2
 
3
- Copyright (c) 2010 Markus Gerdes
3
+ Copyright (c) 2010-2011 Markus Gerdes
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- ## Crisp
1
+ # Crisp
2
2
 
3
3
  Crisp is an experimental language written in Ruby, using treetop.
4
4
 
@@ -6,25 +6,52 @@ Crisp has a Lisp syntax and immutable data structures.
6
6
 
7
7
  The main purpose of the language is to deal with the issues and problems when creating your own programming language.
8
8
 
9
- ### Example
9
+ ## Language features
10
+
11
+ * binding values to a symbol with **def**
12
+ * calculations with **+**, **-**, __*__ and __/__
13
+ * comparisons with **>**, **<** and **=**
14
+ * conditional statements with **if**
15
+ * loop statements with **loop**/**recur**
16
+ * console output with **println**
17
+ * function creation with **fn**
18
+ * switch/case conditions with **cond**
19
+ * local binding with **let**
20
+ * dynamic loading of crisp source files with **load**
21
+ * head and tail functions for array with **head** and **tail**
22
+ * calling native ruby with **.**
23
+
24
+ ## Example
10
25
 
11
26
  # crisp
12
- >> (* 2 3)
13
- => 6
14
- >> (def foo 4)
15
- => 4
16
- >> (/ (* foo foo) 2 2)
17
- => 4
18
- >> (def add2 (fn [arg] (+ 2 arg)))
19
- => #<Crisp::Function:0x85d1bc0>
20
- >> (add2 5)
21
- => 7
22
-
23
- ### Installation
27
+ >> (println "Hello World")
28
+ Hello World
29
+ =>
30
+ >> (def fib (
31
+ ?> fn [n]
32
+ ?> (if (< n 2)
33
+ ?> n
34
+ ?> (+ (fib (- n 1)) (fib (- n i))))))
35
+ => #<Crisp::Function:0x1005c2500>
36
+ >> (fib 10)
37
+ => 55
38
+ >> (def factorial
39
+ ?> (fn [n]
40
+ ?> (loop [cnt n acc 1]
41
+ ?> (if (= 0 cnt)
42
+ ?> acc
43
+ ?> (recur (- cnt 1) (* acc cnt))))))
44
+ => #<Crisp::Function:0x1001ad9d8>
45
+ >> (factorial 12)
46
+ => 479001600
47
+
48
+ For more examples see the examples directory in the repository.
49
+
50
+ ## Installation
24
51
 
25
52
  gem install crisp
26
53
 
27
- ### Usage
54
+ ## Usage
28
55
 
29
56
  To start an interactive shell:
30
57
  crisp
data/Rakefile CHANGED
@@ -15,7 +15,7 @@ begin
15
15
  gem.homepage = "http://github.com/mgsnova/crisp"
16
16
  gem.authors = ['Markus Gerdes']
17
17
  gem.add_dependency 'treetop', '~> 1.4.9'
18
- gem.add_development_dependency 'rspec', '~> 2.4.0'
18
+ gem.add_development_dependency 'rspec', '~> 2.5.0'
19
19
  end
20
20
 
21
21
  Jeweler::GemcutterTasks.new
data/bin/crisp CHANGED
@@ -6,7 +6,7 @@ if ARGV.size == 0
6
6
  Crisp::Shell.new.run
7
7
  elsif ARGV.size == 1
8
8
  ast = Crisp::Parser.new.parse(File.read(ARGV[0]))
9
- Crisp::Runtime.new.run(ast).to_s
9
+ Crisp::Runtime.new.run(ast)
10
10
  else
11
11
  puts "to many args"
12
12
  exit 1
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{crisp}
8
- s.version = "0.0.8"
8
+ s.version = "0.1.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Markus Gerdes"]
12
- s.date = %q{2011-01-06}
12
+ s.date = %q{2011-04-27}
13
13
  s.default_executable = %q{crisp}
14
14
  s.email = %q{github@mgsnova.de}
15
15
  s.executables = ["crisp"]
@@ -19,12 +19,17 @@ Gem::Specification.new do |s|
19
19
  ]
20
20
  s.files = [
21
21
  "CHANGELOG.md",
22
+ "Gemfile",
23
+ "Gemfile.lock",
22
24
  "LICENSE",
23
25
  "README.md",
24
26
  "Rakefile",
25
27
  "autotest/discover.rb",
26
28
  "bin/crisp",
27
29
  "crisp.gemspec",
30
+ "examples/array.crisp",
31
+ "examples/calculation.crisp",
32
+ "examples/comparisons.crisp",
28
33
  "examples/factorial.crisp",
29
34
  "examples/fibonacci.crisp",
30
35
  "examples/run.crisp",
@@ -37,6 +42,7 @@ Gem::Specification.new do |s|
37
42
  "lib/crisp/function_runner.rb",
38
43
  "lib/crisp/functions.rb",
39
44
  "lib/crisp/functions/arithmetic.rb",
45
+ "lib/crisp/functions/array.rb",
40
46
  "lib/crisp/functions/core.rb",
41
47
  "lib/crisp/native_call_invoker.rb",
42
48
  "lib/crisp/nodes.rb",
@@ -56,6 +62,7 @@ Gem::Specification.new do |s|
56
62
  "lib/crisp/runtime.rb",
57
63
  "lib/crisp/shell.rb",
58
64
  "spec/crisp/arithmetics_spec.rb",
65
+ "spec/crisp/array_spec.rb",
59
66
  "spec/crisp/basic_spec.rb",
60
67
  "spec/crisp/core_spec.rb",
61
68
  "spec/crisp/function_spec.rb",
@@ -70,6 +77,7 @@ Gem::Specification.new do |s|
70
77
  s.summary = %q{a tiny lisp-like language written in ruby using treetop.}
71
78
  s.test_files = [
72
79
  "spec/crisp/arithmetics_spec.rb",
80
+ "spec/crisp/array_spec.rb",
73
81
  "spec/crisp/basic_spec.rb",
74
82
  "spec/crisp/core_spec.rb",
75
83
  "spec/crisp/function_spec.rb",
@@ -84,15 +92,27 @@ Gem::Specification.new do |s|
84
92
  s.specification_version = 3
85
93
 
86
94
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
95
+ s.add_runtime_dependency(%q<crisp>, [">= 0"])
96
+ s.add_runtime_dependency(%q<rake>, [">= 0"])
97
+ s.add_runtime_dependency(%q<jeweler>, [">= 0"])
98
+ s.add_development_dependency(%q<rspec>, ["~> 2.5.0"])
87
99
  s.add_runtime_dependency(%q<treetop>, ["~> 1.4.9"])
88
- s.add_development_dependency(%q<rspec>, ["~> 2.4.0"])
100
+ s.add_development_dependency(%q<rspec>, ["~> 2.5.0"])
89
101
  else
102
+ s.add_dependency(%q<crisp>, [">= 0"])
103
+ s.add_dependency(%q<rake>, [">= 0"])
104
+ s.add_dependency(%q<jeweler>, [">= 0"])
105
+ s.add_dependency(%q<rspec>, ["~> 2.5.0"])
90
106
  s.add_dependency(%q<treetop>, ["~> 1.4.9"])
91
- s.add_dependency(%q<rspec>, ["~> 2.4.0"])
107
+ s.add_dependency(%q<rspec>, ["~> 2.5.0"])
92
108
  end
93
109
  else
110
+ s.add_dependency(%q<crisp>, [">= 0"])
111
+ s.add_dependency(%q<rake>, [">= 0"])
112
+ s.add_dependency(%q<jeweler>, [">= 0"])
113
+ s.add_dependency(%q<rspec>, ["~> 2.5.0"])
94
114
  s.add_dependency(%q<treetop>, ["~> 1.4.9"])
95
- s.add_dependency(%q<rspec>, ["~> 2.4.0"])
115
+ s.add_dependency(%q<rspec>, ["~> 2.5.0"])
96
116
  end
97
117
  end
98
118
 
@@ -0,0 +1,3 @@
1
+ (println "head of [1,2,3] is " (head [1 2 3]))
2
+
3
+ (println "tail of [1,2,3] is " (tail [1 2 3]))
@@ -0,0 +1,7 @@
1
+ (println "1 plus 1 is " (+ 1 1))
2
+
3
+ (println "3 minus 2 is " (- 3 2))
4
+
5
+ (println "2 multiplied with 3 is " (* 2 3))
6
+
7
+ (println "8 divided by 2 is " (/ 8 2))
@@ -0,0 +1,18 @@
1
+ (if (= 2 2)
2
+ (println "2 equals 2"))
3
+
4
+ (if (= 2 1)
5
+ (println "2 equals 1")
6
+ (println "2 does not equals 1"))
7
+
8
+ (cond
9
+ (> 2 1) (println "2 is greater than 1"))
10
+
11
+ (cond
12
+ (> 1 2) (println "1 is greater than 2")
13
+ (< 1 2) (println "1 is less than 2"))
14
+
15
+ (cond
16
+ (> 1 1) (println "1 is greater than 1")
17
+ (< 1 1) (println "1 is less then 1")
18
+ else (println "1 is probably equal 1"))
@@ -1,5 +1,8 @@
1
1
  (load "fibonacci")
2
2
  (load "factorial")
3
+ (load "comparisons")
4
+ (load "calculation")
5
+ (load "array")
3
6
 
4
7
  (println "fibonacci for 10 is" (fib 10))
5
8
  (println "factorial of 10 is" (factorial 10))
@@ -3,7 +3,7 @@ require "treetop"
3
3
  require "pp"
4
4
 
5
5
  module Crisp
6
- VERSION = '0.0.8'
6
+ VERSION = '0.1.0'
7
7
  end
8
8
 
9
9
  require 'crisp/errors'
@@ -39,5 +39,10 @@ module Crisp
39
39
  def global_loop_data=(data)
40
40
  @second.global_loop_data = data
41
41
  end
42
+
43
+ # set alias to global/second env
44
+ def alias(to, from)
45
+ @second.alias(to, from)
46
+ end
42
47
  end
43
48
  end
@@ -16,7 +16,13 @@ module Crisp
16
16
 
17
17
  # Returns the value for the given key.
18
18
  def [](key)
19
- @map[key.to_sym]
19
+ result = @map[key.to_sym]
20
+
21
+ if result.class == Hash and result[:alias_to]
22
+ self[result[:alias_to]]
23
+ else
24
+ result
25
+ end
20
26
  end
21
27
 
22
28
  # Store the key/value pair.
@@ -26,5 +32,10 @@ module Crisp
26
32
  raise EnvironmentError, "#{key} already binded" if @map.has_key?(key)
27
33
  @map[key] = val
28
34
  end
35
+
36
+ # Store alias
37
+ def alias(to, from)
38
+ self[to] = {:alias_to => from}
39
+ end
29
40
  end
30
41
  end
@@ -3,11 +3,13 @@ module Crisp
3
3
  # require all files that are defining functions
4
4
  require 'crisp/functions/core'
5
5
  require 'crisp/functions/arithmetic'
6
+ require 'crisp/functions/array'
6
7
 
7
8
  # Load all defined function to the given environment
8
9
  def self.load(env)
9
10
  Core.load(env)
10
11
  Arithmetic.load(env)
12
+ Array.load(env)
11
13
  end
12
14
  end
13
15
  end
@@ -0,0 +1,49 @@
1
+ module Crisp
2
+ module Functions
3
+ # Defining array crisp functions
4
+ class Array
5
+ # load the functions and bind them into the given environment
6
+ def self.load(current_env)
7
+
8
+ # head
9
+ # return head of array
10
+ #
11
+ # (head [1 2 3])
12
+ # => 1
13
+ Function.new do
14
+ validate_args_count(1, args.size)
15
+
16
+ if args[0].class.name != "Crisp::Nodes::ArrayLiteral"
17
+ raise ArgumentError, "argument is not an array"
18
+ end
19
+
20
+ if raw_head = args[0].raw_elements[0]
21
+ raw_head.resolve(env)
22
+ else
23
+ nil
24
+ end
25
+ end.bind('head', current_env)
26
+
27
+ # tail
28
+ # return tail of array
29
+ #
30
+ # (tail [1 2 3])
31
+ # => [2 3]
32
+ Function.new do
33
+ validate_args_count(1, args.size)
34
+
35
+ if args[0].class.name != "Crisp::Nodes::ArrayLiteral"
36
+ raise ArgumentError, "argument is not an array"
37
+ end
38
+
39
+ if raw_tail = args[0].raw_elements[1..-1]
40
+ raw_tail.map { |arg| arg.resolve(env) }
41
+ else
42
+ []
43
+ end
44
+ end.bind('tail', current_env)
45
+
46
+ end
47
+ end
48
+ end
49
+ end
@@ -256,6 +256,21 @@ module Crisp
256
256
  true
257
257
  end.bind('load', current_env)
258
258
 
259
+ # alias
260
+ # create alias from one symbol to another
261
+ #
262
+ # (alias p println)
263
+ # (p 123)
264
+ # 123
265
+ Function.new do
266
+ validate_args_count(2, args.size)
267
+
268
+ to = args[0].text_value
269
+ from = args[1].text_value
270
+
271
+ env.alias(to, from)
272
+ end.bind('alias', current_env)
273
+
259
274
  end
260
275
  end
261
276
  end
@@ -3,86 +3,86 @@ require 'spec_helper'
3
3
  describe "arithemtic functions" do
4
4
  include Crisp::SpecHelper
5
5
 
6
- it "adds integer values" do
6
+ it "should add integer values" do
7
7
  evaluate("(+ 1 2)").should == 3
8
8
  evaluate("(+ 12 13 1 5)").should == 31
9
9
  evaluate("(+ 12 13 -1 -5)").should == 19
10
10
  end
11
11
 
12
- it "substracts integer values" do
12
+ it "should substract integer values" do
13
13
  evaluate("(- 3 1)").should == 2
14
14
  evaluate("(- 14 1 4 8)").should == 1
15
15
  evaluate("(- 2 5)").should == -3
16
16
  evaluate("(- 2 -5)").should == 7
17
17
  end
18
18
 
19
- it "multiplies integer values" do
19
+ it "should multiply integer values" do
20
20
  evaluate("(* 2 3)").should == 6
21
21
  evaluate("(* 0 3)").should == 0
22
22
  evaluate("(* 2 -3 1 10)").should == -60
23
23
  end
24
24
 
25
- it "divides integer values" do
25
+ it "should divide integer values" do
26
26
  evaluate("(/ 12 3)").should == 4
27
27
  evaluate("(/ 48 2 12)").should == 2
28
28
  evaluate("(/ 30 -3 2)").should == -5
29
29
  end
30
30
 
31
- it "calculates different nested operations" do
31
+ it "should calculate different nested operations" do
32
32
  evaluate("(+ 1 2 (+ 2 3) (- 5 1)) ").should == 12
33
33
  evaluate("(+ 1 2 (* 2 3) (/ 10 2)) ").should == 14
34
34
  evaluate("(+ 1 2 (- 10 2 3) (* 1 2 3) (/ 12 4)) ").should == 17
35
35
  evaluate("(/ 20 2 (+ 2 3) (- 5 3)) ").should == 1
36
36
  end
37
37
 
38
- it "adds float values" do
38
+ it "should add float values" do
39
39
  evaluate("(+ 1.0 2.)").should == 3.0
40
40
  evaluate("(+ 12.5 13 1.4 5)").should == 31.9
41
41
  evaluate("(+ 12. 13.5 -1.9 -5.1)").should == 18.5
42
42
  end
43
43
 
44
- it "substracts float values" do
44
+ it "should substract float values" do
45
45
  evaluate("(- 3. 1.4)").should == 1.6
46
46
  evaluate("(- 2 5.5)").should == -3.5
47
47
  evaluate("(- 2.40 -5)").should == 7.4
48
48
  end
49
49
 
50
- it "multiplies float values" do
50
+ it "should multiply float values" do
51
51
  evaluate("(* 2.1 3.4)").should == 7.14
52
52
  evaluate("(* 0 3.5)").should == 0
53
53
  evaluate("(* 2 -3.1 1.9 10.1)").should == -118.978
54
54
  end
55
55
 
56
- it "divides float values" do
56
+ it "should divide float values" do
57
57
  evaluate("(/ 12.5 3.1)").should be_within(0.0000001).of(4.03225806451613)
58
58
  evaluate("(/ 48 2.000 12.5)").should == 1.92
59
59
  evaluate("(/ 30.0 -3 2.5)").should == -4.0
60
60
  end
61
61
 
62
- it "calculates different nested operations" do
62
+ it "should calculate different nested operations" do
63
63
  evaluate("(+ 1 2.3 (* 2 3.5) (/ 10 4)) ").should == 12.3
64
64
  evaluate("(+ 1.5 2 (- 10 2.4 3) (* 1.0 2 3) (/ 12 3.0)) ").should == 18.1
65
65
  evaluate("(/ 20.4 2 (+ 2.5 3) (- 5.5 3)) ").should be_within(0.000000001).of(0.741818181818182)
66
66
  end
67
67
 
68
- it "compares values for equality" do
68
+ it "should compare values for equality" do
69
69
  evaluate("(= 1 1)").should == true
70
70
  evaluate("(= 1 2)").should == false
71
71
  end
72
72
 
73
- it "compares values that are greater than others" do
73
+ it "should compare values that are greater than others" do
74
74
  evaluate("(> 2 1)").should == true
75
75
  evaluate("(> 1 1)").should == false
76
76
  evaluate("(> 1 2)").should == false
77
77
  end
78
78
 
79
- it "compares values that are less than others" do
79
+ it "should compare values that are less than others" do
80
80
  evaluate("(< 2 1)").should == false
81
81
  evaluate("(< 1 1)").should == false
82
82
  evaluate("(< 1 2)").should == true
83
83
  end
84
84
 
85
- it "calculates fibonacci numbers" do
85
+ it "should calculate fibonacci numbers" do
86
86
  evaluate("
87
87
  (def fib (
88
88
  fn [n]
@@ -0,0 +1,49 @@
1
+ require 'spec_helper'
2
+
3
+ describe "the language array features" do
4
+ include Crisp::SpecHelper
5
+
6
+ it "should raise an error on wrong number of arguments for head" do
7
+ lambda do
8
+ evaluate("(head)")
9
+ end.should raise_error(Crisp::ArgumentError, "wrong number of arguments for 'head' (0 for 1)")
10
+
11
+ lambda do
12
+ evaluate("(head 1 2)")
13
+ end.should raise_error(Crisp::ArgumentError, "wrong number of arguments for 'head' (2 for 1)")
14
+ end
15
+
16
+ it "should raise an error on invalid argument for head" do
17
+ lambda do
18
+ evaluate("(head 3)")
19
+ end.should raise_error(Crisp::ArgumentError, "argument is not an array")
20
+ end
21
+
22
+ it "should calculate the head of an array" do
23
+ evaluate("(head [1 2 3])").should == 1
24
+ evaluate("(head [2])").should == 2
25
+ evaluate("(head [])").should == nil
26
+ end
27
+
28
+ it "should raise an error on wrong number of arguments for tail" do
29
+ lambda do
30
+ evaluate("(tail)")
31
+ end.should raise_error(Crisp::ArgumentError, "wrong number of arguments for 'tail' (0 for 1)")
32
+
33
+ lambda do
34
+ evaluate("(tail 1 2)")
35
+ end.should raise_error(Crisp::ArgumentError, "wrong number of arguments for 'tail' (2 for 1)")
36
+ end
37
+
38
+ it "should raise an error on invalid argument for tail" do
39
+ lambda do
40
+ evaluate("(tail 3)")
41
+ end.should raise_error(Crisp::ArgumentError, "argument is not an array")
42
+ end
43
+
44
+ it "should calculate the tail of an array" do
45
+ evaluate("(tail [1 2 3])").should == [2, 3]
46
+ evaluate("(tail [2])").should == []
47
+ evaluate("(tail [])").should == []
48
+ end
49
+ end
@@ -3,23 +3,23 @@ require 'spec_helper'
3
3
  describe "the language" do
4
4
  include Crisp::SpecHelper
5
5
 
6
- it "does not bother whitspace characters in expressions" do
6
+ it "should not bother whitspace characters in expressions" do
7
7
  evaluate(" \r\t\n (\r+\t 1\n2 \t(\n - 9\r\t \n 2)\r)\r\t ").should == 10
8
8
  end
9
9
 
10
- it "raises a syntax error on invalid expressions" do
10
+ it "should raise a syntax error on invalid expressions" do
11
11
  lambda do
12
12
  evaluate("(()")
13
13
  end.should raise_error(Crisp::SyntaxError, "syntax error at : 0")
14
14
  end
15
15
 
16
- it "binds arrays to symbols" do
16
+ it "should bind arrays to symbols" do
17
17
  evaluate("(def bla [1 2 3])").size.should == 3
18
18
  evaluate("(def bla [1 2 3])")[1].should == 2
19
19
  evaluate("(def foo 5)(def bla [1 2 foo])")[2].should == 5
20
20
  end
21
21
 
22
- it "does not evaluate numbers" do
22
+ it "should not evaluate numbers" do
23
23
  lambda do
24
24
  evaluate("(3)")
25
25
  end.should raise_error(Crisp::SyntaxError, "syntax error at : 0")
@@ -3,38 +3,38 @@ require 'spec_helper'
3
3
  describe "the core language features" do
4
4
  include Crisp::SpecHelper
5
5
 
6
- it "prints results" do
6
+ it "should print results" do
7
7
  evaluate("(println (+ 1 1))")
8
8
  end
9
9
 
10
- it "binds values to symbols" do
10
+ it "should bind values to symbols" do
11
11
  evaluate("(def bla 3)")
12
12
  end
13
13
 
14
- it "does not allow to bind symbols twice" do
14
+ it "should not allow to bind symbols twice" do
15
15
  lambda do
16
16
  evaluate("(def name 123)(def name 123)")
17
17
  end.should raise_error(Crisp::EnvironmentError, "name already binded")
18
18
  end
19
19
 
20
- it "produces an error when calling bind function with arguments" do
20
+ it "should produce an error when calling bind function with arguments" do
21
21
  lambda do
22
22
  evaluate("(def bla 1 2)")
23
23
  end.should raise_error(Crisp::ArgumentError, "wrong number of arguments for 'def' (3 for 2)")
24
24
  end
25
25
 
26
- it "uses binded values in later expressions" do
26
+ it "should use binded values in later expressions" do
27
27
  evaluate("(def bla 2) (* 4 bla)").should == 8
28
28
  evaluate("(def bla (* 2 3)) (* 4 bla 2)").should == 48
29
29
  end
30
30
 
31
- it "can not resolve unbound symbols" do
31
+ it "should not resolve unbound symbols" do
32
32
  lambda do
33
33
  evaluate("n")
34
34
  end.should raise_error(Crisp::EnvironmentError, "n is unbound")
35
35
  end
36
36
 
37
- it "can resolve primitve types" do
37
+ it "should resolve primitve types" do
38
38
  evaluate("2").should == 2
39
39
  evaluate("2.1").should == 2.1
40
40
  evaluate("nil").should == nil
@@ -44,30 +44,30 @@ describe "the core language features" do
44
44
  evaluate("[1 2 3]").should == [1, 2, 3]
45
45
  end
46
46
 
47
- it "can resolve bounded symbols" do
47
+ it "should resolve bounded symbols" do
48
48
  evaluate("(def foo 23) foo").should == 23
49
49
  evaluate('(def foo "foo") foo').should == 'foo'
50
50
  end
51
51
 
52
- it "binds symbols to value of already bound symbol" do
52
+ it "should bind symbols to value of already bound symbol" do
53
53
  evaluate("(def a 1)
54
54
  (def b a)
55
55
  b").should == 1
56
56
  end
57
57
 
58
- it "has if statements" do
58
+ it "should evaluate if statements" do
59
59
  evaluate("(if true 1)").should == 1
60
60
  evaluate("(if false 1)").should == nil
61
61
  evaluate("(if nil 1)").should == nil
62
62
  end
63
63
 
64
- it "has if else statements" do
64
+ it "should evaluate if else statements" do
65
65
  evaluate("(if true 1 2)").should == 1
66
66
  evaluate("(if false 1 2)").should == 2
67
67
  evaluate("(if nil 1 2)").should == 2
68
68
  end
69
69
 
70
- it "does not run if statements with wrong number of arguments" do
70
+ it "should not run if statements with wrong number of arguments" do
71
71
  lambda do
72
72
  evaluate("(if true true false 2)")
73
73
  end.should raise_error(Crisp::ArgumentError, "wrong number of arguments for 'if' (4 for 2..3)")
@@ -77,51 +77,51 @@ describe "the core language features" do
77
77
  end.should raise_error(Crisp::ArgumentError, "wrong number of arguments for 'if' (1 for 2..3)")
78
78
  end
79
79
 
80
- it "resolves symbols in if statements" do
80
+ it "should resolve symbols in if statements" do
81
81
  evaluate("(def foo 2)(if true foo)").should == 2
82
82
  end
83
83
 
84
- it "uses local binding with let" do
84
+ it "should use local binding with let" do
85
85
  evaluate("(let [x 1] x)").should == 1
86
86
  end
87
87
 
88
- it "uses more complex local bindings with let" do
88
+ it "should use more complex local bindings with let" do
89
89
  evaluate("(let [x 2 y x] (* x y))").should == 4
90
90
  end
91
91
 
92
- it "evaluates several expressions within local binding" do
92
+ it "should evaluate several expressions within local binding" do
93
93
  evaluate("(let [x 2 y 3] (* x y) (+ x y))").should == 5
94
94
  end
95
95
 
96
- it "binds symbols to global binding within local binding" do
96
+ it "should bind symbols to global binding within local binding" do
97
97
  evaluate("(let [x 1 y 2] (def foo (+ x y))) foo").should == 3
98
98
  end
99
99
 
100
- it "overrides global binding within local binding" do
100
+ it "should override global binding within local binding" do
101
101
  evaluate("(def x 1)(let [x 2] x)").should == 2
102
102
  end
103
103
 
104
- it "ensures that local binding is only valid within let" do
104
+ it "should ensure that local binding is only valid within let" do
105
105
  evaluate("(def x 1)(let [x 2] x) x").should == 1
106
106
  end
107
107
 
108
- it "can handle emtpy local binding" do
108
+ it "should handle emtpy local binding" do
109
109
  evaluate("(let [] 2)").should == 2
110
110
  end
111
111
 
112
- it "raises an error when calling let without correct argument" do
112
+ it "should raise an error when calling let without correct argument" do
113
113
  lambda do
114
114
  evaluate("(let 2 2)")
115
115
  end.should raise_error(Crisp::ArgumentError, "no argument list defined")
116
116
  end
117
117
 
118
- it "raises an error when calling let with odd binding list" do
118
+ it "should raise an error when calling let with odd binding list" do
119
119
  lambda do
120
120
  evaluate("(let [x 1 y] 2)")
121
121
  end.should raise_error(Crisp::ArgumentError, "argument list has to contain even list of arguments")
122
122
  end
123
123
 
124
- it "raises an error if file to be load not there" do
124
+ it "should raise an error if file to be load not there" do
125
125
  lambda do
126
126
  evaluate('(load "not_there")')
127
127
  end.should raise_error(Crisp::ArgumentError, /file (.*) not found/)
@@ -131,7 +131,7 @@ describe "the core language features" do
131
131
  end.should raise_error(Crisp::ArgumentError, "file /not_there.crisp not found")
132
132
  end
133
133
 
134
- it "loads other crisp files" do
134
+ it "should load other crisp files" do
135
135
  File.open("/tmp/crisp_test_file.crisp", 'w') do |f|
136
136
  f << "(def foo 123)"
137
137
  end
@@ -139,7 +139,7 @@ describe "the core language features" do
139
139
  evaluate('(load "/tmp/crisp_test_file")(+ 1 foo)').should == 124
140
140
  end
141
141
 
142
- it "uses the current environment when loading other crisp source files" do
142
+ it "should use the current environment when loading other crisp source files" do
143
143
  File.open("/tmp/crisp_test_file.crisp", 'w') do |f|
144
144
  f << "(def bla 123)"
145
145
  end
@@ -149,13 +149,13 @@ describe "the core language features" do
149
149
  end.should raise_error(Crisp::EnvironmentError, "bla already binded")
150
150
  end
151
151
 
152
- it "raises an error if calling cond with wrong number of arguments" do
152
+ it "should raise an error if calling cond with wrong number of arguments" do
153
153
  lambda do
154
154
  evaluate("(cond false 1 true)")
155
155
  end.should raise_error(Crisp::ArgumentError, "argument list has to contain even list of arguments")
156
156
  end
157
157
 
158
- it "has cond statement" do
158
+ it "should evaluate cond statement" do
159
159
  evaluate("(cond)").should == nil
160
160
  evaluate("(cond false 1 false 2)").should == nil
161
161
  evaluate("(cond true 3)").should == 3
@@ -165,41 +165,41 @@ describe "the core language features" do
165
165
  evaluate("(cond true 3 true 2 true 1)").should == 3
166
166
  end
167
167
 
168
- it "does not eval expressions for unmatched condition" do
168
+ it "should not eval expressions for unmatched condition" do
169
169
  evaluate("(cond false (def foo 1) true 2)(def foo 2) foo").should == 2
170
170
  end
171
171
 
172
- it "has a default condition in cond" do
172
+ it "should have a default condition in cond" do
173
173
  evaluate("(cond false 1 true 2 else 3)").should == 2
174
174
  evaluate("(cond true 1 true 2 else 3)").should == 1
175
175
  evaluate("(cond false 1 else 2 true 3)").should == 2
176
176
  end
177
177
 
178
- it "raises an error when calling loop without correct argument" do
178
+ it "should raise an error when calling loop without correct argument" do
179
179
  lambda do
180
180
  evaluate("(loop 2 2)")
181
181
  end.should raise_error(Crisp::ArgumentError, "no argument list defined")
182
182
  end
183
183
 
184
- it "raises an error when calling loop with odd binding list" do
184
+ it "should raise an error when calling loop with odd binding list" do
185
185
  lambda do
186
186
  evaluate("(loop [x 1 y] 2)")
187
187
  end.should raise_error(Crisp::ArgumentError, "argument list has to contain even list of arguments")
188
188
  end
189
189
 
190
- it "raises an error when calling recur outside a loop" do
190
+ it "should raise an error when calling recur outside a loop" do
191
191
  lambda do
192
192
  evaluate("(recur 1)")
193
193
  end.should raise_error(Crisp::LoopError, "recur called outside loop")
194
194
  end
195
195
 
196
- it "raises an error when calling recur with wrong number of arguments" do
196
+ it "should raise an error when calling recur with wrong number of arguments" do
197
197
  lambda do
198
198
  evaluate("(loop [x 1] (recur 1 2))")
199
199
  end.should raise_error(Crisp::ArgumentError, "wrong number of arguments for 'recur' (2 for 1)")
200
200
  end
201
201
 
202
- it "calculates factorials using loop recur" do
202
+ it "should calculate factorials using loop recur" do
203
203
  evaluate("
204
204
  (def factorial
205
205
  (fn [n]
@@ -211,9 +211,17 @@ describe "the core language features" do
211
211
  ").should == 120
212
212
  end
213
213
 
214
- it "raises an error when nesting loops" do
214
+ it "should raise an error when nesting loops" do
215
215
  lambda do
216
216
  evaluate("(loop [x 1] (loop [a 1 b 2] (+ a b)))")
217
217
  end.should raise_error(Crisp::LoopError, "nested loops are not allowed")
218
218
  end
219
+
220
+ it "should create an alias to a function symbol" do
221
+ evaluate("(alias fed def) (fed a 1) a").should == 1
222
+ end
223
+
224
+ it "should create an alias to a value symbol" do
225
+ evaluate("(def foo 123) (alias bar foo) foo").should == 123
226
+ end
219
227
  end
@@ -3,48 +3,48 @@ require 'spec_helper'
3
3
  describe "the languages functions" do
4
4
  include Crisp::SpecHelper
5
5
 
6
- it "does not create a function when providing wrong number of arguments" do
6
+ it "should not create a function when providing wrong number of arguments" do
7
7
  lambda do
8
8
  evaluate("(fn [] (+ 1 2) [])")
9
9
  end.should raise_error(Crisp::ArgumentError, "wrong number of arguments for 'fn' (3 for 2)")
10
10
  end
11
11
 
12
- it "does not create a function when not providing a proper argument list" do
12
+ it "should not create a function when not providing a proper argument list" do
13
13
  lambda do
14
14
  evaluate("(fn (+ 2 1) (+ 1 2))")
15
15
  end.should raise_error(Crisp::ArgumentError, "no argument list defined")
16
16
  end
17
17
 
18
- it "does return primitive values as result" do
18
+ it "should return primitive values as result" do
19
19
  evaluate("((fn [] 1))").should == 1
20
20
  evaluate('((fn [] "abc"))').should == 'abc'
21
21
  evaluate('((fn [] [1 2 3]))').should == [1, 2, 3]
22
22
  evaluate("((fn [x] x) 2)").should == 2
23
23
  end
24
24
 
25
- it "creates functions" do
25
+ it "should create functions" do
26
26
  evaluate("(fn [arg] (+ 2 arg))")
27
27
  end
28
28
 
29
- it "binds functions to symbols" do
29
+ it "should bind functions to symbols" do
30
30
  evaluate("(def myfn (fn [arg] (+ 1 arg)))").class.name.should == "Crisp::Function"
31
31
  end
32
32
 
33
- it "calls functions" do
33
+ it "should call functions" do
34
34
  evaluate("(def myfn (fn [a b] (+ 1 1)))(myfn 1 2)").should == 2
35
35
  end
36
36
 
37
- it "calls functions with arguments" do
37
+ it "should call functions with arguments" do
38
38
  evaluate("(def myfn (fn [a b] (+ a b)))(myfn 5 2)").should == 7
39
39
  end
40
40
 
41
- it "does not calls functions with wrong number of arguments" do
41
+ it "should not call functions with wrong number of arguments" do
42
42
  lambda do
43
43
  evaluate("(def myfn (fn [a1 a2 a3] (+ 1 1)))(myfn 1)")
44
44
  end.should raise_error(Crisp::ArgumentError, "wrong number of arguments for 'myfn' (1 for 3)")
45
45
  end
46
46
 
47
- it "instantly evaluates a function" do
47
+ it "should instantly evaluate a function" do
48
48
  evaluate("((fn [] (+ 1 2)))").should == 3
49
49
  end
50
50
  end
@@ -3,7 +3,7 @@ require 'spec_helper'
3
3
  describe "internals" do
4
4
  include Crisp::SpecHelper
5
5
 
6
- it "sets and gets values to and from the env" do
6
+ it "should set and get values to and from the env" do
7
7
  env = Crisp::Env.new
8
8
  env['key'] = 'value'
9
9
 
@@ -13,14 +13,14 @@ describe "internals" do
13
13
  env.has_key?(:key).should == true
14
14
  end
15
15
 
16
- it "handles mismatched env reads" do
16
+ it "should handle mismatched env reads" do
17
17
  env = Crisp::Env.new
18
18
 
19
19
  env.has_key?('not_exists').should == false
20
20
  env['not_exists'].should == nil
21
21
  end
22
22
 
23
- it "is not allowed to set env keys twice" do
23
+ it "should not allow to set env keys twice" do
24
24
  env = Crisp::Env.new
25
25
  env['key'] = 'value'
26
26
 
@@ -29,7 +29,7 @@ describe "internals" do
29
29
  end.should raise_error(Crisp::EnvironmentError, "key already binded")
30
30
  end
31
31
 
32
- it "gets values from a chained env" do
32
+ it "should get values from a chained env" do
33
33
  env1 = Crisp::Env.new
34
34
  env1[:key1] = 'val1'
35
35
  env1[:key2] = 'val2'
@@ -45,7 +45,7 @@ describe "internals" do
45
45
  chained[:key3].should == 'val4'
46
46
  end
47
47
 
48
- it "sets values to a chained env" do
48
+ it "should set values to a chained env" do
49
49
  env1 = Crisp::Env.new
50
50
  env1[:key] = 'val'
51
51
 
@@ -57,4 +57,23 @@ describe "internals" do
57
57
  env2[:key].should == 'other'
58
58
  chained[:key].should == 'val'
59
59
  end
60
+
61
+ it "should set aliases" do
62
+ env = Crisp::Env.new
63
+ env[:key] = 1
64
+ env.alias(:alias, :key)
65
+ env[:alias].should == 1
66
+ end
67
+
68
+ it "should set aliases to a chained env" do
69
+ env1 = Crisp::Env.new
70
+ env1[:key] = 1
71
+ env2 = Crisp::Env.new
72
+
73
+ env = Crisp::ChainedEnv.new(env1, env2)
74
+
75
+ env[:key] = 1
76
+ env.alias(:alias, :key)
77
+ env[:alias].should == 1
78
+ end
60
79
  end
@@ -3,25 +3,25 @@ require 'spec_helper'
3
3
  describe "NativeCallInvoker functionality" do
4
4
  include Crisp::SpecHelper
5
5
 
6
- it "executes ruby native String#reverse" do
6
+ it "should execute ruby native String#reverse" do
7
7
  evaluate('(. reverse "foobar")').should == 'raboof'
8
8
  end
9
9
 
10
- it "executes ruby native Array#first" do
10
+ it "should execute ruby native Array#first" do
11
11
  evaluate('(. first [1 2 3])').should == 1
12
12
  end
13
13
 
14
- it "executes ruby native Array#first(n)" do
14
+ it "should execute ruby native Array#first(n)" do
15
15
  evaluate('(. first [1 2 3] 2)').should == [1,2]
16
16
  end
17
17
 
18
- it "raises a named exception on invalid method" do
18
+ it "should raise a named exception on invalid method" do
19
19
  lambda do
20
20
  evaluate('(. foo "bar")')
21
21
  end.should raise_error(NoMethodError, %q{undefined method `foo' for "bar":String})
22
22
  end
23
23
 
24
- it "executes calls on Ruby classes" do
24
+ it "should execute calls on Ruby classes" do
25
25
  evaluate("(. new String)").should == ''
26
26
  evaluate('(. new String "123")').should == '123'
27
27
  evaluate("(. new Array 5 2)").should == [2, 2, 2, 2, 2]
@@ -3,7 +3,7 @@ require 'spec_helper'
3
3
  describe "string functionality" do
4
4
  include Crisp::SpecHelper
5
5
 
6
- it "concats strings" do
6
+ it "should concat strings" do
7
7
  evaluate('(+ "foo" "bar")').should == 'foobar'
8
8
  end
9
9
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: crisp
3
3
  version: !ruby/object:Gem::Version
4
- hash: 15
4
+ hash: 27
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
+ - 1
8
9
  - 0
9
- - 8
10
- version: 0.0.8
10
+ version: 0.1.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Markus Gerdes
@@ -15,41 +15,83 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-01-06 00:00:00 +01:00
18
+ date: 2011-04-27 00:00:00 +02:00
19
19
  default_executable: crisp
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
22
- name: treetop
23
22
  prerelease: false
24
- requirement: &id001 !ruby/object:Gem::Requirement
23
+ type: :runtime
24
+ name: crisp
25
+ version_requirements: &id001 !ruby/object:Gem::Requirement
25
26
  none: false
26
27
  requirements:
27
- - - ~>
28
+ - - ">="
28
29
  - !ruby/object:Gem::Version
29
- hash: 21
30
+ hash: 3
30
31
  segments:
31
- - 1
32
- - 4
33
- - 9
34
- version: 1.4.9
32
+ - 0
33
+ version: "0"
34
+ requirement: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ prerelease: false
35
37
  type: :runtime
36
- version_requirements: *id001
38
+ name: rake
39
+ version_requirements: &id002 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ hash: 3
45
+ segments:
46
+ - 0
47
+ version: "0"
48
+ requirement: *id002
37
49
  - !ruby/object:Gem::Dependency
38
- name: rspec
39
50
  prerelease: false
40
- requirement: &id002 !ruby/object:Gem::Requirement
51
+ type: :runtime
52
+ name: jeweler
53
+ version_requirements: &id003 !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ hash: 3
59
+ segments:
60
+ - 0
61
+ version: "0"
62
+ requirement: *id003
63
+ - !ruby/object:Gem::Dependency
64
+ prerelease: false
65
+ type: :development
66
+ name: rspec
67
+ version_requirements: &id004 !ruby/object:Gem::Requirement
41
68
  none: false
42
69
  requirements:
43
70
  - - ~>
44
71
  - !ruby/object:Gem::Version
45
- hash: 31
72
+ hash: 27
46
73
  segments:
47
74
  - 2
48
- - 4
75
+ - 5
49
76
  - 0
50
- version: 2.4.0
51
- type: :development
52
- version_requirements: *id002
77
+ version: 2.5.0
78
+ requirement: *id004
79
+ - !ruby/object:Gem::Dependency
80
+ prerelease: false
81
+ type: :runtime
82
+ name: treetop
83
+ version_requirements: &id005 !ruby/object:Gem::Requirement
84
+ none: false
85
+ requirements:
86
+ - - ~>
87
+ - !ruby/object:Gem::Version
88
+ hash: 21
89
+ segments:
90
+ - 1
91
+ - 4
92
+ - 9
93
+ version: 1.4.9
94
+ requirement: *id005
53
95
  description:
54
96
  email: github@mgsnova.de
55
97
  executables:
@@ -61,12 +103,17 @@ extra_rdoc_files:
61
103
  - README.md
62
104
  files:
63
105
  - CHANGELOG.md
106
+ - Gemfile
107
+ - Gemfile.lock
64
108
  - LICENSE
65
109
  - README.md
66
110
  - Rakefile
67
111
  - autotest/discover.rb
68
112
  - bin/crisp
69
113
  - crisp.gemspec
114
+ - examples/array.crisp
115
+ - examples/calculation.crisp
116
+ - examples/comparisons.crisp
70
117
  - examples/factorial.crisp
71
118
  - examples/fibonacci.crisp
72
119
  - examples/run.crisp
@@ -79,6 +126,7 @@ files:
79
126
  - lib/crisp/function_runner.rb
80
127
  - lib/crisp/functions.rb
81
128
  - lib/crisp/functions/arithmetic.rb
129
+ - lib/crisp/functions/array.rb
82
130
  - lib/crisp/functions/core.rb
83
131
  - lib/crisp/native_call_invoker.rb
84
132
  - lib/crisp/nodes.rb
@@ -98,6 +146,7 @@ files:
98
146
  - lib/crisp/runtime.rb
99
147
  - lib/crisp/shell.rb
100
148
  - spec/crisp/arithmetics_spec.rb
149
+ - spec/crisp/array_spec.rb
101
150
  - spec/crisp/basic_spec.rb
102
151
  - spec/crisp/core_spec.rb
103
152
  - spec/crisp/function_spec.rb
@@ -141,6 +190,7 @@ specification_version: 3
141
190
  summary: a tiny lisp-like language written in ruby using treetop.
142
191
  test_files:
143
192
  - spec/crisp/arithmetics_spec.rb
193
+ - spec/crisp/array_spec.rb
144
194
  - spec/crisp/basic_spec.rb
145
195
  - spec/crisp/core_spec.rb
146
196
  - spec/crisp/function_spec.rb