crisp 0.0.8 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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