aster 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 58243f4638f7370eaedd71419622f967f24bd60e
4
- data.tar.gz: 8426cc93373842fb7cf66d2fcc3c389a47cdecf1
3
+ metadata.gz: 0c85417587339f5f431df3347c2045046b742aae
4
+ data.tar.gz: 72836e9ed31cd3f4ba159509bebcbbfe28bca42c
5
5
  SHA512:
6
- metadata.gz: 1adc2b41461422e04081c6fa8c4d9f2c460b8661691ee0aff87bacf5fc7d9b611fa031a7e1115b680221e767f071ec0c61ca953d44761e2062191fbb863a7ae4
7
- data.tar.gz: 1cdcbe16dff0aaf31ec201df89181461416f94d3c1044d890de17ad664b60c8a06fcf7f8b6622266cc051f950fe647b2d3172770a2d3e3e7b3439b194bcd65ef
6
+ metadata.gz: 54058d24e135d2efee5e8abfc2755b32067f84a4f4210029cdfa688460d478b43ab4ca6f83f2a3904b65a7ea93eb4e84bed1d2e98367e3e0fcac974573122557
7
+ data.tar.gz: b8d77eb5a75520e918749ebb2e875e3488e25e055c017749a853db83d662caa3da0a975352e36880a45219e18f6b02106786e0aee8d1dbb75ea0ea78181758b5
data/README.md CHANGED
@@ -2,9 +2,10 @@
2
2
 
3
3
  Aster is a programming language that's designed to make configuration management more fun.
4
4
 
5
- ## Example
5
+ ### Example
6
6
 
7
7
  server web
8
+
8
9
  default-instance-vars
9
10
  var username root
10
11
  var ssh-port 22
@@ -17,6 +18,7 @@ Aster is a programming language that's designed to make configuration management
17
18
  config-set username admin
18
19
  config-set ssh-port 2222
19
20
  upload sample.conf /etc/conf
21
+ exec set-hostname $instance.hostname
20
22
 
21
23
  add-remote-file-runner .rb
22
24
  exec `which ruby`
@@ -43,10 +45,24 @@ Aster is a programming language that's designed to make configuration management
43
45
  create-server-instance web
44
46
  configure-instance {{instance.id}}
45
47
 
46
- ## Install
48
+ ### Install
47
49
 
48
50
  gem install aster
49
51
 
50
- ## Usage
52
+ ### Usage
53
+
54
+ #### Adding ruby-side macro
55
+
56
+ class Server
57
+ end
58
+
59
+ e = Aster::Environment.new
60
+
61
+ # Make a special form of "server" that
62
+ e.define_macro "server" do |arguments, body|
63
+ body.parse_tree
64
+ end
65
+
66
+ ### Notes
51
67
 
52
68
  Aster is not a configuration management application. Right now it is an experimental language that supports other languages embedded within `.aster` files.
data/TODO CHANGED
@@ -1,4 +1,12 @@
1
1
  # TODO
2
2
 
3
- * reserve gem name
3
+
4
+
5
+ # Done
6
+
7
+ * implement sub-language text gathering
8
+ * implement ruby-side macros
9
+ * implement equal
10
+ * implement not
4
11
  * eval sub-commands like "equal {add 1 1} 2"
12
+ * reserve gem name
@@ -24,4 +24,5 @@ Gem::Specification.new do |spec|
24
24
  spec.add_development_dependency "bundler", "~> 1.6"
25
25
  spec.add_development_dependency "rake"
26
26
  spec.add_development_dependency "pry"
27
+ spec.add_development_dependency "ZenTest"
27
28
  end
@@ -12,4 +12,5 @@ require_relative './aster/command'
12
12
  require_relative './aster/environment'
13
13
  require_relative './aster/function'
14
14
  require_relative './aster/parser'
15
+ require_relative './aster/macro'
15
16
 
@@ -1,24 +1,31 @@
1
1
  module Aster
2
2
  class Command
3
- attr_accessor :text, :sublines
3
+ attr_accessor :text, :sub_commands, :sub_text
4
4
 
5
- def initialize(commands, sublines = [])
6
- @commands = commands
7
- @sublines = sublines
8
- end
9
-
10
- def rest
11
- @text.split(' ', 2)[1]
5
+ def initialize(commands, subcommands = [])
6
+ @commands = make_commands commands
7
+ @sub_commands = sub_commands
12
8
  end
13
9
 
14
10
  def arguments
15
- _, *args = @commands
16
- args
11
+ @commands[1..-1]
17
12
  end
18
13
 
19
14
  def function_name
20
15
  @function_name ||= @commands.first.to_sym
21
16
  end
22
17
 
18
+ private
19
+
20
+ def make_commands(cmds)
21
+ cmds.map do |cmd|
22
+ if cmd.is_a?(Array)
23
+ Command.new(cmd)
24
+ else
25
+ cmd
26
+ end
27
+ end
28
+ end
29
+
23
30
  end
24
31
  end
@@ -7,17 +7,9 @@ module Aster
7
7
  def initialize(parent = nil)
8
8
  @parent = parent
9
9
  @env = {}
10
- @stdout = ""
11
- @stderr = ""
10
+ @stdout, @stderr = "", ""
12
11
 
13
- if parent.nil?
14
- define_function :echo, [:_list_] do |arguments|
15
- @stdout << arguments.join(' ')
16
- end
17
- define_function :equal, [:a, :b] do |(a, b)|
18
- a.to_s == b.to_s ? "yes" : "no"
19
- end
20
- end
12
+ define_base_environment if parent.nil?
21
13
  end
22
14
 
23
15
  def child
@@ -38,59 +30,97 @@ module Aster
38
30
  end
39
31
 
40
32
  def define_function(name, args, commands = nil, &block)
41
- @env[name.to_sym] = Function.new(args, commands, &block)
33
+ self[name] = Function.new(args, commands, &block)
34
+ end
35
+
36
+ def define_macro(name, &block)
37
+ self[name] = Macro.new self, block
42
38
  end
43
39
 
44
40
  private
45
41
 
46
- def eval_line(command)
42
+ def define_base_environment
43
+ define_function :echo, [:_list_] do |arguments|
44
+ @stdout << arguments.join(' ')
45
+ end
46
+
47
+ define_function :equal, [:a, :b] do |(a, b)|
48
+ a.to_s == b.to_s ? "yes" : "no"
49
+ end
50
+
51
+ define_function :add, [:_list_] do |arguments|
52
+ arguments.inject(0){|r, s| s.to_i + r}.to_s
53
+ end
54
+
55
+ end
56
+
57
+
58
+ def eval_command(command)
47
59
  case command.function_name
48
60
  when :function
49
61
  fun, *args = command.arguments
50
62
  self.define_function(
51
63
  fun,
52
64
  args,
53
- command.sublines
65
+ command.sub_commands
54
66
  )
55
67
  when :if
56
- cond_value = eval_line Command.new(command.rest)
68
+ cond_value = eval_command Command.new(command.rest)
57
69
  if is_true?(cond_value)
58
- eval_tree command.sublines
70
+ eval_tree command.sub_commands
59
71
  end
60
72
  when :not
61
- cond_value = eval_line Command.new(command.rest)
73
+ cond_value = eval_arguments([command.arguments.first]).first
62
74
  is_true?(cond_value) ? "no" : "yes"
63
75
  else
64
- function = self[command.function_name]
65
- if function
66
- eval_function(function, command.arguments, self.child)
76
+ case function_or_macro = self[command.function_name]
77
+ when Function
78
+ eval_function(
79
+ function_or_macro,
80
+ eval_arguments(command.arguments),
81
+ self.child
82
+ )
83
+ when Macro
84
+ eval_macro(function_or_macro, command)
85
+ else
86
+ # ? binding.pry
87
+ end
88
+ end
89
+ end
90
+
91
+ def eval_arguments(arguments)
92
+ arguments.map do |arg|
93
+ if arg.is_a?(Command)
94
+ eval_command(arg)
95
+ elsif arg.is_a?(Variable)
96
+ self[arg.name]
67
97
  else
68
- #binding.pry
98
+ arg
69
99
  end
70
100
  end
71
101
  end
72
102
 
73
103
  def is_true?(val)
74
- val && value.strip == "yes"
104
+ val && val.strip == "yes"
75
105
  end
76
106
 
77
107
  def eval_tree(tree)
78
- tree.each do |command|
79
- eval_line command
80
- end
108
+ tree.map do |command|
109
+ res = eval_command command
110
+ end.last
81
111
  end
82
112
 
83
- def eval_function(function, arguments, env)
84
- # need to eval args
85
- arguments = arguments.map do |arg|
86
- if arg.is_a?(Variable)
87
- env[arg.name]
88
- else
89
- arg
90
- end
113
+ def eval_macro(macro, command)
114
+ command_or_commands = macro.function(command)
115
+ if command_or_commands.is_a?(Array)
116
+ eval_tree command_or_commands
117
+ else
118
+ eval_command command_or_commands
91
119
  end
120
+ end
92
121
 
93
- # bind arguments
122
+ def eval_function(function, arguments, env)
123
+ # bind arguments to new env
94
124
  function.arguments.each_with_index do |a, i|
95
125
  env[a] = arguments[i]
96
126
  end
@@ -101,13 +131,7 @@ module Aster
101
131
  function.block.call arguments
102
132
  else
103
133
  raise
104
- end
105
-
106
- end
107
-
108
-
109
- def eval_custom(m, args)
110
-
134
+ end
111
135
  end
112
136
 
113
137
  end
@@ -0,0 +1,12 @@
1
+ class Macro
2
+
3
+ def initialize(env, block)
4
+ @env = env
5
+ @block = block
6
+ end
7
+
8
+ def function(command)
9
+ @block.call command
10
+ end
11
+
12
+ end
@@ -1,4 +1,3 @@
1
-
2
1
  require 'treetop'
3
2
 
4
3
  module Aster
@@ -59,7 +58,15 @@ module Aster
59
58
  break
60
59
  end
61
60
  end
62
- command.sublines = parse_lines sublines
61
+
62
+ begin
63
+ command.sub_commands = parse_lines sublines
64
+ rescue
65
+ command.sub_commands = :GARBAGE
66
+ end
67
+ command.sub_text = sublines.map do |subline|
68
+ subline.gsub(/^[ ]{#{next_indent*2}}/, '')
69
+ end.join("\n")
63
70
  end
64
71
  data << command
65
72
  end
@@ -1,6 +1,3 @@
1
-
2
-
3
-
4
1
  grammar Sexp
5
2
 
6
3
  rule body
@@ -13,7 +10,6 @@ grammar Sexp
13
10
  end
14
11
  }
15
12
  end
16
-
17
13
 
18
14
  rule expression
19
15
  space? '{' body '}' space? {
@@ -25,7 +21,6 @@ grammar Sexp
25
21
  end
26
22
  }
27
23
  end
28
-
29
24
 
30
25
  rule variable
31
26
  '$' identifier {
@@ -1,3 +1,3 @@
1
1
  module Aster
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -2,10 +2,32 @@ require_relative './helper'
2
2
 
3
3
  class TestEnvironment < Test::Unit::TestCase
4
4
 
5
+ def eval(text)
6
+ Aster::Environment.new.eval(text)
7
+ end
8
+
5
9
  def test_not
6
10
  e = Aster::Environment.new
7
- #assert_equal "no", e.eval("not yes")
8
- #assert_equal "yes", e.eval("not no")
11
+ assert_equal "no", e.eval("not yes")
12
+ assert_equal "yes", e.eval("not no")
13
+ end
14
+
15
+ def test_sub_not
16
+ e = Aster::Environment.new
17
+ assert_equal "no", e.eval("not {not no}")
18
+ assert_equal "yes", e.eval("not {not {not no}}")
19
+ end
20
+
21
+ def test_equal
22
+ e = Aster::Environment.new
23
+ assert_equal "yes", e.eval("equal 1 1")
24
+ assert_equal "yes", e.eval("equal {not no} yes")
25
+ end
26
+
27
+ def test_add
28
+ assert_equal "12", eval("add 6 6")
29
+ assert_equal "6", eval("add 1 2 3")
30
+ assert_equal "12", eval("add 1 2 3 {add 3 3}")
9
31
  end
10
32
 
11
33
  def test_function
@@ -15,4 +37,19 @@ class TestEnvironment < Test::Unit::TestCase
15
37
  assert_equal("one and two", e.stdout)
16
38
  end
17
39
 
40
+ def test_macro
41
+ e = Aster::Environment.new
42
+ e.define_macro :double do |c|
43
+ assert_kind_of Aster::Command, c
44
+ tree = Aster::Parser.new.parse("add #{c.arguments.first} #{c.arguments.first}")
45
+ tree.first
46
+ end
47
+ assert_equal "32", e.eval("double 16")
48
+ end
49
+
50
+ def test_env
51
+
52
+
53
+ end
54
+
18
55
  end
@@ -55,4 +55,17 @@ function test2 asdf
55
55
  tree = parser.parse file
56
56
  end
57
57
 
58
+ def test_ruby_script
59
+ tree = parse %Q{
60
+ ruby
61
+ require 'rubygems'
62
+ a = ArchiveRecord::Base;
63
+ a.define "s" do |asdf|
64
+ asdf.asdf << #end
65
+ end
66
+ }
67
+ text = "require 'rubygems'\na = ArchiveRecord::Base;\na.define \"s\" do |asdf|\n asdf.asdf << #end\nend\n "
68
+ assert_equal text, tree.first.sub_text
69
+ end
70
+
58
71
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aster
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Murphy
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - '>='
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: ZenTest
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
69
83
  description:
70
84
  email:
71
85
  - sam.murphy@gmail.com
@@ -84,6 +98,7 @@ files:
84
98
  - lib/aster/command.rb
85
99
  - lib/aster/environment.rb
86
100
  - lib/aster/function.rb
101
+ - lib/aster/macro.rb
87
102
  - lib/aster/parser.rb
88
103
  - lib/aster/sexp.treetop
89
104
  - lib/aster/variable.rb