ql 0.0.2

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.
data/lib/q/scope.rb ADDED
@@ -0,0 +1,94 @@
1
+ module Q
2
+ class Scope
3
+ def initialize parents = nil
4
+ @map = {}
5
+ @args = []
6
+ @parents = [ parents ].flatten.compact
7
+ @this = nil
8
+ end
9
+
10
+ def [] name
11
+ return @map[name] if has_own? name
12
+
13
+ @parents.each do |parent|
14
+ if parent.has? name
15
+ return parent[name]
16
+ end
17
+ end
18
+
19
+ return nil
20
+ end
21
+
22
+ def []= name, value
23
+ return @map[name] = value if has_own? name
24
+
25
+ @parents.each do |parent|
26
+ if parent.has? name
27
+ return parent[name] = value
28
+ end
29
+ end
30
+
31
+ @map[name] = value
32
+ end
33
+
34
+ def has? name
35
+ if has_own? name
36
+ return true
37
+ end
38
+
39
+ @parents.each do |parent|
40
+ if parent.has? name
41
+ return true
42
+ end
43
+ end
44
+
45
+ return false
46
+ end
47
+
48
+ def has_own? name
49
+ @map.has_key? name
50
+ end
51
+
52
+ def args= args
53
+ @args = [args].flatten
54
+ end
55
+
56
+ def args
57
+ @args
58
+ end
59
+
60
+ def this= th
61
+ if has_own? '@'
62
+ return @map['@'] = @this = th
63
+ end
64
+
65
+ @this = th
66
+ end
67
+
68
+ def this
69
+ if has_own? '@'
70
+ return @this = @map['@']
71
+ end
72
+
73
+ @this
74
+ end
75
+
76
+ def inspect
77
+ str = "Q::Scope --\n"
78
+
79
+ @map.each do |key, value|
80
+ str += " #{key} => #{value}\n"
81
+ end
82
+
83
+ if not @parents.empty?
84
+ str += "\n parents:\n"
85
+
86
+ @parents.each do |parent|
87
+ str += " #{parent.inspect}\n"
88
+ end
89
+ end
90
+
91
+ str
92
+ end
93
+ end
94
+ end
data/lib/q/syntax.rb ADDED
@@ -0,0 +1,51 @@
1
+ require 'treetop'
2
+
3
+ module Q
4
+ module Syntax
5
+
6
+ class Function < Treetop::Runtime::SyntaxNode
7
+ def eval prefscope
8
+ defargs = args
9
+
10
+ prefscope['_'] = this = lambda { |scope|
11
+ argscope = Q::Scope.new
12
+
13
+ defargs.each_with_index do |arg, i|
14
+ argscope[arg] = scope.args[i]
15
+ end
16
+
17
+ fscope = Q::Scope.new [argscope, scope, prefscope]
18
+ fscope.this = this
19
+
20
+ fscope['_'] = statements.eval fscope
21
+
22
+ return fscope.this
23
+ }
24
+ end
25
+
26
+ def args
27
+ arguments.elements.map do |argument|
28
+ argument.identifier.text_value
29
+ end
30
+ end
31
+ end
32
+
33
+ class Conditional < Treetop::Runtime::SyntaxNode
34
+ def eval scope
35
+ if condition.eval(scope) == true
36
+ return consequence.eval(scope)
37
+ end
38
+
39
+ if has_otherwise?
40
+ return otherwise.consequence.eval(scope)
41
+ end
42
+
43
+ false
44
+ end
45
+
46
+ def has_otherwise?
47
+ not otherwise.elements.nil?
48
+ end
49
+ end
50
+ end
51
+ end
data/lib/q/version.rb ADDED
@@ -0,0 +1,3 @@
1
+ module Q
2
+ VERSION = "0.0.2"
3
+ end
data/lib/q/vm.rb ADDED
@@ -0,0 +1,72 @@
1
+ require 'q/scope'
2
+ require 'q/parser'
3
+
4
+ module Q
5
+ class ParsingException < StandardError
6
+ def initialize input, failure_line, failure_index, failure_reason
7
+ @input = input
8
+ @failure_line = failure_line
9
+ @failure_index = failure_index
10
+ @failure_reason = failure_reason
11
+ end
12
+
13
+ def to_s
14
+ @failure_reason
15
+ end
16
+
17
+ def reason
18
+ [
19
+ point,
20
+ @failure_reason
21
+ ] * '\n'
22
+ end
23
+
24
+ private
25
+ def line
26
+ @failure_line = @input.split('\n')[@failure_line - 1] if @failure_line.kind_of? Fixnum
27
+
28
+ @failure_line
29
+ end
30
+
31
+ def point
32
+ [
33
+ line,
34
+ " " * (@failure_index + 1) + "^"
35
+ ] * '\n'
36
+ end
37
+ end
38
+
39
+ class ToplevelScope < Q::Scope
40
+ def initialize
41
+ super()
42
+
43
+ self['puts'] = lambda { |scope|
44
+ puts scope.args
45
+ }
46
+ end
47
+ end
48
+
49
+ class VM
50
+ def initialize
51
+ Q.load
52
+
53
+ @scope = ToplevelScope.new
54
+ @parser = QParser.new
55
+ end
56
+
57
+ def eval input
58
+ parsed = @parser.parse input
59
+
60
+ if parsed.nil?
61
+ raise ParsingException.new input, @parser.failure_line, @parser.failure_index, @parser.failure_reason
62
+ end
63
+
64
+ parsed.eval @scope
65
+ end
66
+
67
+ def reset with_scope = false
68
+ @parser = QParser.new
69
+ @scope = Q::Scope.new if with_scope
70
+ end
71
+ end
72
+ end
data/ql.gemspec ADDED
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'q/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "ql"
8
+ spec.version = Q::VERSION
9
+ spec.authors = ["Stojan Dimitrovski"]
10
+ spec.email = ["s.dimitrovski@gmail.com"]
11
+ spec.summary = %q{Q, a simple programming language.}
12
+ spec.description = %q{Q is a simple programming language implemented on top of Ruby with Treetop.}
13
+ spec.homepage = "https://github.com/hf/q"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.5"
22
+ spec.add_development_dependency "rspec"
23
+ spec.add_development_dependency "rake"
24
+
25
+ spec.add_dependency "treetop", "~> 1.4"
26
+ end
@@ -0,0 +1,45 @@
1
+ require 'q/scope'
2
+ require 'q/parser'
3
+
4
+ describe "Binomial" do
5
+ before do
6
+ @scope = Q::Scope.new
7
+ end
8
+
9
+ it "should be a number" do
10
+ expect(eval "3378;").to eq 3378
11
+ expect(eval "-3378;").to eq -3378
12
+ expect(eval "18.;").to eq 18.0
13
+ expect(eval "-18.;").to eq -18.0
14
+ expect(eval "18.789;").to eq 18.789
15
+ expect(eval "-18.232;").to eq -18.232
16
+ end
17
+
18
+ it "should do addition" do
19
+ expect(eval "30 + 21;").to eq 30 + 21
20
+ expect(eval "30 + -21;").to eq 30 + (-21)
21
+
22
+ @scope['a'] = 15
23
+ @scope['b'] = 30
24
+
25
+ expect(eval "a + b;").to eq @scope['a'] + @scope['b']
26
+ end
27
+
28
+ it "should do subtraction" do
29
+ expect(eval "30 - 15;").to eq 30 - 15
30
+ expect(eval "-10 - 15;").to eq -10 - 15
31
+
32
+ @scope['a'] = -15
33
+ @scope['b'] = 80
34
+
35
+ expect(eval "a - b;").to eq @scope['a'] - @scope['b']
36
+ end
37
+
38
+ def eval input
39
+ if not input.end_with? ";"
40
+ input = input + ";"
41
+ end
42
+
43
+ QParser.new.parse(input).eval(@scope)
44
+ end
45
+ end
@@ -0,0 +1,8 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ # our gem
4
+ require 'doctor_toons'
5
+
6
+ RSpec.configure do |config|
7
+
8
+ end
metadata ADDED
@@ -0,0 +1,122 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ql
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Stojan Dimitrovski
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-03-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.5'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: treetop
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.4'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.4'
69
+ description: Q is a simple programming language implemented on top of Ruby with Treetop.
70
+ email:
71
+ - s.dimitrovski@gmail.com
72
+ executables:
73
+ - q
74
+ extensions: []
75
+ extra_rdoc_files: []
76
+ files:
77
+ - ".gitignore"
78
+ - Gemfile
79
+ - Gemfile.lock
80
+ - LICENSE
81
+ - LICENSE.txt
82
+ - README
83
+ - Rakefile
84
+ - bin/q
85
+ - examples/factorial.q
86
+ - lib/q.rb
87
+ - lib/q.treetop
88
+ - lib/q/parser.rb
89
+ - lib/q/scope.rb
90
+ - lib/q/syntax.rb
91
+ - lib/q/version.rb
92
+ - lib/q/vm.rb
93
+ - ql.gemspec
94
+ - spec/binomial_spec.rb
95
+ - spec/spec_helper.rb
96
+ homepage: https://github.com/hf/q
97
+ licenses:
98
+ - MIT
99
+ metadata: {}
100
+ post_install_message:
101
+ rdoc_options: []
102
+ require_paths:
103
+ - lib
104
+ required_ruby_version: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - ">="
107
+ - !ruby/object:Gem::Version
108
+ version: '0'
109
+ required_rubygems_version: !ruby/object:Gem::Requirement
110
+ requirements:
111
+ - - ">="
112
+ - !ruby/object:Gem::Version
113
+ version: '0'
114
+ requirements: []
115
+ rubyforge_project:
116
+ rubygems_version: 2.2.2
117
+ signing_key:
118
+ specification_version: 4
119
+ summary: Q, a simple programming language.
120
+ test_files:
121
+ - spec/binomial_spec.rb
122
+ - spec/spec_helper.rb